SHGetFileInfoでアイコンが取得できない場合がある

このQ&Aのポイント
  • VC++にてエクスプローラもどきを作成しています。ファイルアイコンを取得するためにSHGetFileInfoを使用していますが、何度も再描画を行うとshfInfo.hIconがNULLになり、アイコンが表示されません。
  • shfInfo.hIconがNULLになる問題について、SHGetFileInfo関数を呼ぶ際に制約がある可能性があります。
  • 具体的な制約がわかりませんが、再描画を行う際には注意が必要です。
回答を見る
  • ベストアンサー

SHGetFileInfoでアイコンが取得できない場合がある

VC++にてエクスプローラもどきを作成しています。 ListViewへファイルアイコンを表示するために、 SHGetFileInfoを使用し、 // 大きいアイコンのハンドル取得 // fnameは拡張子だけの文字列です SHGetFileInfo( fname, NULL, &shfInfo, sizeof(SHFILEINFO), SHGFI_ICON | SHGFI_LARGEICON | SHGFI_USEFILEATTRIBUTES ); licon = shfInfo.hIcon; 上記のようにしてファイルアイコンを取得し、 CImageListへ追加した上で、描画しています。 そして、ダイアログのサイズが変更された際に、 OnSize関数にて、ListView内のアイコンを再度取得し、 再描画しているのですが、 何度もOnSizeで再描画を行っているうちに、 SHGetFileInfoにて取得したshfInfo.hIconが NULLになってしまいます。 一度、shfInfo.hIconがNULLになると、 何度、SHGetFileInfoを呼んでも、返ってくるhIconは 毎回NULLになってしまい、ListView内に アイコンが表示されません。 SHGetFileInfo関数を呼ぶ際の制約等があるのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

 こんにちは。  リソースリークしているのではないでしょうか。  取り敢えず、使い終わったアイコンのハンドルを削除して見て下さい。  因みに以下で再現出来しました。 SHFILEINFO shfInfo; //取り敢えずノートパッド(メモ帳)のアイコンを取って来る TCHAR szPath[] = _T("C:\\WINNT\\notepad.exe"); for(int i = 0; i < 100000; ++i) { SHGetFileInfo( szPath, NULL, &shfInfo, sizeof(SHFILEINFO),SHGFI_ICON | SHGFI_LARGEICON | SHGFI_USEFILEATTRIBUTES ); HICON hicon = shfInfo.hIcon; //此れを呼べば大丈夫 //::DestroyIcon(hicon); if(hicon == NULL) { //いずれココに来る } }

lhouse
質問者

お礼

直りました。ありがとうございます。 SHGetFileInfoでも内部でアイコンを作成しているんですね。 とはいえ、CImageListにAddした直後にDestroyIconしても キチンと表示されているのは不可解な気もしますが。。。 Addしているんだから、描画はAddされたアイコンを使うのでは??? Destroyしちゃったら、何を使って描画させてるんだろう???

関連するQ&A

  • ファイルに関連付けられているアイコンについて

    ファイルに関連付けられているアイコン取得について質問です。 開発環境 OS:XP Visual Studio 2005 言語:C、C++ 調べると、SHGetFileInfo()を使ってアイコンを 取得出来るらしいのですが、 取得するアイコンではなく違うアイコンが取得(表示)されます。 架空のファイル名(実際にないファイル名)でやってみると、 同じアイコンが取得(表示)されます。 ●ソース ーーーーーーーーーーーーーーーーー //アイコン取得部分 SHGetFileInfo("C:/WINDOWS/notepad.exe", 0, &icon, sizeof(icon), SHGFI_PIDL | SHGFI_ICON | SHGFI_SMALLICON); //アイコン表示部分 DrawIcon(hdc, 10, 10, icon.hIcon); ーーーーーーーーーーーーーーーーー SHGetFileInfo()の戻り値は、「1」でした。 間違っている所があるのでしょうか?

  • C# FTPサーバ アイコン取得

    FTPサーバからファイル名とアイコンを取得してListViewに表示させたいのですが アイコンの取得がうまくいきません。ファイル名のみは出来ました。 SHGetFileInfo("ftp://localhost/test.txt", 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), SHGFI_ICON | SHGFI_LARGEICON); みたいな感じで取得できないかと試してみましたが駄目でした。 詳しい方ご教授お願いします。

  • WinAPI SHGetFileInfoでICONファイル名の取得方法?

    SHGetFileInfoでExplorerに表示されるICONのファイル名を取得したいのですが うまくいきません。 int main(int argc, char* argv[]) { SHFILEINFO sfi; ::CoInitialize(NULL); if(0 == ::SHGetFileInfo("C:\\hogehoge.txt", FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi), SHGFI_ICONLOCATION)) return -1; printf("Icon location file = %s\n", sfi.szDisplayName); return 0; } SHGFI_TYPENAMEを指定するとsfi.szTypeNameファイルタイプ名が入るのは確認できたのですが、SHGFI_ICONLOCATIONを指定してもsfi.szDisplayNameにアイコンファイル名が入ってくれません。(sfi.szDisplayName[0]='\0'で終わりになっている...) MSDNを見る限りはこれであっているようなのですが、正しい使い方を教えてください。

  • C#でウィンドウのアイコン取得する方法

    タスクマネージャのアプリケーションタブに 起動しているアプリケーション名とアイコンが一覧で表示されている部分のように 小さいアイコンを取得したいんですがなかなかうまくいきません。 ファイルに紐付くアイコンと解釈していただいても構いません。 とりあえず、下記のWin32 APIの処理を利用してみましたが SHGetFileInfoだけしかうまくいきませんでした。 しかし、SHGetFileInfoも、アイコンは取得できますがこれはファイルに紐付くアイコンではなく 実行体(EXE)に紐付くアイコンで表示されてしまいました。 開いているウィンドウ情報からだと実行プロセスのEXEのパスしか分からないからです。 ★質問★: ファイルに紐付く小さいアイコンの取得方法を教えてください!できればサンプルソース込みだと助かります。 #region 小さいアイコンを取得するためのWin32 API(ファイルパスから) // SHGetFileInfo関数 [DllImport("shell32.dll")] private static extern IntPtr SHGetFileInfo( string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags); // SHGetFileInfo関数で使用するフラグ private const uint SHGFI_ICON = 0x100; // アイコン・リソースの取得 private const uint SHGFI_LARGEICON = 0x0; // 大きいアイコン private const uint SHGFI_SMALLICON = 0x1; // 小さいアイコン private const uint SHGFI_TYPENAME = 0x400;//ファイルの種類 // SHGetFileInfo関数で使用する構造体 private struct SHFILEINFO { public IntPtr hIcon; public IntPtr iIcon; public uint dwAttributes; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szDisplayName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] public string szTypeName; }; #endregion #region 小さいアイコンを取得するためのWin32 API(ウィンドウハンドルからその1) [DllImport("user32.dll", EntryPoint = "GetClassLong")] public static extern IntPtr GetClassLongPtr32(IntPtr hWnd, int nIndex); [DllImport("user32.dll", EntryPoint = "GetClassLongPtr")] public static extern IntPtr GetClassLongPtr64(IntPtr hWnd, int nIndex); const int GCL_HICON = (-14); const int GCL_HICONSM = (-34); #endregion #region 小さいアイコンを取得するためのWin32 API(ウィンドウハンドルからその2) [DllImport("User32.dll", EntryPoint = "SendMessage")] public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); public const int WM_GETICON = 0x7F; public const int WM_SETICON = 0x80; public const int ICON_SMALL = 0; public const int ICON_BIG = 1; #endregion

  • シェルアイコンがイメージリストに登録できない??

    Visual C++においての質問です。 APIで関連づけられたアイコンを取得したあと、イメージリストに登録しようとしてるのですが、 「不正な処理」とかで落ちてしまいます。なんか…マズい処理をやってるんでしょうか?? 大まかなソースは以下の通りです。 超初心者ですので、とんでもない間違いをしてるだけだと思うんですが…。どなたかご教授をお願いします。 CImageList IconList; CString FilePath = "C:\\test.txt"; SHFILEINFO FileInfo; IconList.Create(32,32,ILC_COLORDDB|ILC_MASK,1,1000); ::CoIntialise(NULL); SHGetFileInfo(FilePath,NULL,&FileInfo,sizeof(FileInfo),SHGFI_ICON|SHGFI_SMALLICON);

  • [WinAPI]フォルダ上に表示されるアイコン

    プログラム内でアイコンを2つ使っているのですが 1つはWNDCLASSEX構造体のhIconメンバに渡して 2つめはDrawIconExで描画用に使っています。 しかし、1つめのアイコンはタスクバー上のアイコンとしては表示されるのですが (ウィンドウ自体はリージョンウィンドウで作成したのでタイトルバーはありません。また、タスクトレイと勘違いしてるわけでもないです。) 作成した.exeファイルには2つめのアイコンが表示されてしまいます。 リソースから2つめのアイコンを消すと1つめのアイコンが.exeのアイコンとして表示されるようですが、 2つめのアイコンを使わないわけにはいきません。 リソースファイルには ICON1 ICON "Icon1.ico" ICON2 ICON "Icon2.ico" とだけ指定してあります。 アイコンのロードにはLoadImageで第2引数にはTEXT("ICON1")のように文字列で指定しています。 ウィンドウクラス構造体に指定したアイコンがそのまま、.exeファイルのアイコンとして表示されるのだと認識しているのですが なぜ、描画用にしようしたアイコンが表示されてしまうのでしょう? 解決するための方法や参考になるサイトなどあればご教示ください。

  • アイコンを左上に表示したい

    今VC++.netでプログラミングの学習をしていて、アイコンをタイトルバーの左上に表示したいのですが、上手くいきません。 下のタスクバーにはアイコンが表示されているのですが、タイトルバーにはデフォルトの窓のようなアイコンしか表示されません。 リソースは、 #define IDI_ICON1 105 となっていて、以下のようにウインドウクラスを設定してあります。 //ウインドウクラス構造体を設定します。 wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = (HICON)LoadImage(hInstance,"IDI_ICON1",IMAGE_ICON,0,0,LR_DEFAULTSIZE | LR_SHARED); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.lpszMenuName = "ModelApp"; wcex.lpszClassName = "ModelApp"; wcex.hIconSm = (HICON)LoadImage(hInstance,"IDI_ICON1",IMAGE_ICON,0,0,LR_DEFAULTSIZE | LR_SHARED); 何かヒントでもいいので、よろしくお願いいたします。

  • エクスプローラーに表示されているきれいなアイコン

    お世話になります。 Visual Studio 2015 VB.net Window 10 Pro 上記にて開発しております。 エクスプローラーで任意のフォルダを開き、例えばそこにPDFファイルがあった場合には、きれいなアイコンで表示されています。 VB.Net のWindowsフォーム上にListViewを配置して、System.Drawing.Icon.ExtractAssociatedIcon にてファイルのアイコンイメージを取得してListViewに表示されても、なんていうか汚いアイコンしか表示できません。おそらく違う場所にあのきれいなアイコンが登録してあって呼び出し方も違うのかなと思うのですが、ご存じの方がいらっしゃいましたら何卒ご教授いただければと存じます。 (1) 同じアイコンだけどイメージの作り方が悪いから汚く表示される? (2) 違う方法で、違うアイコンがあり、それを取得すればきれいなアイコンを表示できる? (3) 上記2つ以外の方法がある? 何卒よろしくお願い申し上げます。

  • ホームページアイコンの取得

    WEBブラウザ上で、ページタブの先頭に表示されるアイコンの 取得方法を教えてください。 例えば、 Icon icon = getHomepageIcon("http://okwave.jp/"); とすると、オレンジの背景に白のOKという16×16のアイコンが 取得できるといった使い方をしたいということです。 以上、よろしくお願いいたします。

    • ベストアンサー
    • Java
  • Win32APIにて、アイコンの情報を取得する方法を教えてください。

    いつもお世話になっております。 只今、小生WindowsXPSP3上で、C言語とWin32APIを使い、BCC5.5.1でコンパイルし、Windowsプログラミングを勉強しています。 今回質問させて頂きたいのは、 「ウィンドウにアイコンを描画する際、  BitBlt関数の第4・5引数に指定する転送元画像の幅と高さを取得する  際にはどうすればいいか」 です。 例えば、ビットマップ画像の幅、高さを取得する際は、 GetObject(hBitmap, (int)sizeof(BITMAP), &bmp_info); をして、 w = bmp_info.bmWidth; h = bmp_info.bmHeight; とし、x, yをBitBlt関数の第4・5引数に指定する方法というのは知っているのですが、アイコンの場合はどのようにして、幅、高さを求められるのでしょうか?? 先輩方、ご教授宜しくお願い致します。

専門家に質問してみよう