2016-05-22 8 views
1

Windowsの実行可能ファイルからアイコンを抽出したいとします。私は、Visual Studioでそれを開いて、そのアイコンのIDを取得することができます:ExtractIconとExtractAssociatedIconの違いは?特定のサイズのアイコンを抽出する必要があります

enter image description here

それから私は、48×48サイズのアイコンに興味があるでしょう:

enter image description here

だから私の仮定を行うことでした。

HICON hIcons[4]; 
::ExtractIconEx(L"mstsc.exe", -13011, hIcons, NULL, 4); 
hIconLogo = hIcons[3]; 

が、私はそれを実行すると、メソッドが返すのみ3アイコン:

enter image description here

これらのうちの1つだけが、必要なものの32x32バージョンです。

私は、私のような呼ばExtractAssociatedIconEx APIが見つかりました:

WORD wIcnId = -13011; 
WORD wIcnInd = 3; 
hIconLogo = ::ExtractAssociatedIconEx(hInst, L"mstsc.exe", &wIcnInd, &wIcnId); 

をしかし、それはあまりにも私が期待していなかった他のいくつかのアイコンを提供します。

これらの2つのAPIの違いは何ですか?そして私は何が間違っているのですか?

+0

特定のサイズのアイコンを取得するために 'LoadImage'を試してみてください。 –

+0

@JonathanPotter:ありがとうございます。私はそれを正しく書いているかどうかはわかりませんが。 :: LoadImage(:: LoadLibrary(L "mstsc.exe")、MAKEINTRESOURCE(13011)、IMAGE_ICON、48、48、LR_LOADFROMFILE); 'アクセス違反例外をスローしますが、:: LoadImage :: LoadLibrary(L "mstsc.exe")、L "#13011"、IMAGE_ICON、48、48、LR_LOADFROMFILE); 'はNULLを返します。 – c00000fd

答えて

12

ExtractIconEx関数は、大小2種類のアイコンのみを返すことができます。それらは環境によって定義される相対的なサイズです。 「大きな」アイコンは古典的には32×32ピクセルですが、特定のシステム構成では大きくなる場合があります。 「小さな」アイコンは古典的には16×16ピクセルですが、同じ警告が適用されます。唯一の保証は、「小さな」アイコンが、「大きな」アイコンよりも小さいことです。システム上の実際のサイズを知りたい場合は、「大」アイコンの場合はSM_CXICONSM_CYICON、小さいアイコンの場合はSM_CXSMICONSM_CYSMICONとなり、GetSystemMetrics関数が呼び出されます。

オペレーティングシステムは、内部的に「小さな」アイコンと「大きな」アイコンを使用します。 APIのほとんどは「小さい」と「大きい」(「大きな」アイコンとも呼ばれる)だけを処理します。たとえば、set an icon for a windowの場合は、「小さい」アイコンまたは「大きな」アイコンのいずれかを設定します。それらはあなたの唯一の2つの選択肢です。

ExtractIconExファンクションは、大きなアイコンに対するハンドルの配列へのポインタにphIconLargeパラメータを設定します。 phIconSmallパラメータは、小さなアイコンのハンドルの配列へのポインタに設定されています。 phIconSmallパラメータにNULLを渡したため、小さなアイコンが表示されませんでした。 hIconsはファイル内の "大きな"アイコンのハンドルで埋められています。これは、システム上で32x32アイコンのビット深度が異なります。

ExtractAssociatedIcon関数(およびそのEx brother)は "大きな"アイコンのみを返します。したがって、あなたがExtractIconExに電話する方法と同じように、同じ結果を得る必要があります。私はあなたがと異なる結果を出すと言っているのかどうかは分かりません。インデックスと何か関係があるかもしれません。負のインデックスはExtractIconExに特別な意味を持ちますが、ExtractAssociatedIconに対して有効かどうかはわかりません。ドキュメンテーションはヒントをあまり伝えていません。

SHGetFileInfo機能

から任意のファイル・システム・オブジェクトをアイコンを抽出する能力など、五感の数、でより強力なものの、同じ基本的な制限があります:それはあなたの SHGFI_LARGEICONSHGFI_SMALLICONの選択肢を提供します。

カスタムサイズのアイコン(システムの「小さい」と「大きい」以外のアイコン)を抽出する必要がある場合は、さらに作業する必要があります。アイコンを含むシェルのイメージリストを取得し

  1. コール別のシェルヘルパー関数であるSHGetImageList機能、が、1:基本的に2つのオプションがあります。 (一般的には16x16)、SHIL_LARGE(一般的には32x32)、SHIL_EXTRALARGE(一般的には48x48)、SHIL_JUMBO(通常はVistaとそれ以降では256x256)のアイコンサイズのオプションがあります。したがって、SHIL_EXTRALARGEを求める場合は、あなたが探している48x48のアイコンが表示されます。

    ここでもSHGetFileInfo関数が必要ですが、今回はシェルイメージリスト内の目的のアイコンのインデックスを取得します。 SHGFI_SYSICONINDEXオプションを使用して取得します。

    完全にテストされていないサンプルコードは、コンパイラによって触れたことはありません:

    HICON ExtractExtraLargeIcon(LPCTSTR pszPath) 
    {  
        // Determine the index of the desired icon 
        // in the system image list. 
        SHGETFILEINFO sfi; 
        SHGetFileInfo(pszPath, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX); 
    
        // Retrieve the system image list. 
        // (To get 48x48 icons, we use `SHIL_EXTRALARGE`.) 
        IImageList* piml; 
        if (SHGetImageList(SHIL_EXTRALARGE, IID_IImageList, (void**)&piml) == S_OK) 
        { 
         HICON hIcon; 
         if (piml->GetIcon(sfi.iIcon, ILD_TRANSPARENT, &hIcon) == S_OK) 
         { 
          return hIcon; 
         } 
        } 
    
        // Oops! We failed. 
        return NULL; 
    } 
    
  2. あなたの他のオプションは、ファイルを自分から希望のサイズのアイコンを抽出することです。アイコンのリソースフォーマットはよく文書化されていますが、さまざまな人々がこの知識を使って醜い抽出コードを書いてインターネット上に投稿していますが、より簡単な方法があります。SHDefExtractIcon

    いくつかの時間前にRaymond Chen blogged aboutとして(のコードサンプルは、上記の使用しようとするものである)IExtractIcon::Extractが失敗した場合、SHDefExtractIconはあなたのより強力な代替です。このファンクションの機能は、nIconSizeパラメータで、抽出するアイコンの実際のサイズを指定します。レイモンドさんの例の適応

    :あなたは、API関数がHICONを返すたび、それはあなたにそのリソースの所有権を移転していることを覚えていますどのような

    HICON ExtractArbitrarySizeIcon(LPCTSTR pszPath, int size) 
    {  
        HICON hIcon; 
        if (SHDefExtractIcon(pszPath, 1, 0, &hIcon, NULL, size) == S_OK) 
        { 
         return hIcon; 
        } 
        return NULL; // failure 
    } 
    

。つまり、アイコンを終了したら、DestroyIcon関数を呼び出すことで、アイコンを破棄してリークを回避する必要があります。

+1

すばらしい答え。私からUpvote。 – user2120666

+0

うん。私はこれを以前に見たかったと思う。私はあなたのコードをテストすることはできませんので、私はすでに移動しました。私はあまりにも多くの情報のためにそれをupvoteします。私の場合は、最初のAPIが提供したより小さい32x32のアイコンを貼り付けることに決めました。 – c00000fd

関連する問題