1

コンパイラ: MinGW/GCC

そのファイル タイプに対して登録されているアイコン ウィンドウに基づいてファイル タイプの HICON を取得し、HICON のすべての画像を取得しようとしています。

問題は、32x32 または 16x16 のアイコン以外は何も取得できないことです。また、私は見てきましたGetIconInfoEx()が、その機能では、必要なアイコンのサイズを選択することはできません。Windows がその時点で私に渡したいと感じているものを任意に吐き出すだけです。

少なくとも16x16、32x32、および 48x48 のアイコンをすべて取得したいのですが、渡した HICON に含まれるすべてのサイズを抽出できると本当にうれしいです。

これが私が現在取り組んでいるコードです(これのほとんどをウェブからコピーして貼り付け、つなぎ合わせました):

HBITMAP GetFileTypeIcon(const char* ext, int type, int depth)
{
    HICON hIcon;
    SHFILEINFO sfi= {0};
    UINT flag = SHGFI_ICON|SHGFI_USEFILEATTRIBUTES;
    int wh = 16;
    switch(type)
    {
        default:
        case FILE_ICON_SIZE_16:
        {
            wh = 16; flag|=SHGFI_SMALLICON;
        }
        break;
        case FILE_ICON_SIZE_32:
        {
            wh = 32; flag|=SHGFI_LARGEICON; 
        }
        break;
        case FILE_ICON_SIZE_48:
        {
            wh = 48; flag|=SHGFI_SYSICONINDEX;
        }
        break;
        case FILE_ICON_SIZE_256:
        {
            wh = 256; flag|=SHGFI_SYSICONINDEX;
        }
        break;
    }
    HRESULT hr = SHGetFileInfo(ext,FILE_ATTRIBUTE_NORMAL,&sfi,sizeof(sfi),flag);
    if(SUCCEEDED(hr))
    {
        if((type == FILE_ICON_SIZE_48) || (type == FILE_ICON_SIZE_256))
        {
            // THIS PART DOESN'T COMPILE: undeclared function/indentifiers

            // HIMAGELIST* imageList;
            // hr = SHGetImageList(((type == FILE_ICON_SIZE_256)?SHIL_JUMBO:SHIL_EXTRALARGE), IID_IImageList, (void**)&imageList);
            // if(SUCCEEDED(hr))
            // {
            //     //Get the icon we need from the list. Note that the HIMAGELIST we retrieved
            //     //earlier needs to be casted to the IImageList interface before use.
            //     hr = ((IImageList*)imageList)->GetIcon(sfi.iIcon, ILD_TRANSPARENT, &hIcon);
            // }
        }
        else
        {
            hIcon=sfi.hIcon;
        }
    }

    // Convert to an HBITMAP (to get it out of the icon...)
    HDC hDC = GetDC(NULL);
    HDC hMemDC = CreateCompatibleDC(hDC);
    HBITMAP hMemBmp = CreateCompatibleBitmap(hDC, wh, wh);
    HGDIOBJ hOrgBMP = SelectObject(hMemDC, hMemBmp);

    DrawIconEx(hMemDC, 0, 0, hIcon, wh, wh, 0, NULL, DI_NORMAL);

    SelectObject(hMemDC, hOrgBMP);
    DeleteDC(hMemDC);
    ReleaseDC(NULL, hDC);
    DestroyIcon(hIcon);

    return hMemBmp;
}

色深度についてどうすればよいかさえわかりません。私は推測を危険にさらします:(互換性のあるDCではなく)特定の色深度を持つDCを作成し、それをDrawIconEx()?

編集:多くの調査/作業の後に、私は自分の質問に答えました。

生のアイコンデータを見つけて解析する方法については、以下の私の回答を参照してください。

4

3 に答える 3

1

私は基本的に (Web、Stack Overflow、およびいくつかの MSDN 記事の助けを借りて) 自分ですべてを行う必要があったため、ここに独自のソリューションを投稿することにします。

レジストリを解析して、以前に登録された各ファイル拡張子のアイコンの場所を見つけることになりました。必要な情報を簡単に取得できるはずの API 関数に問題があったためです。

その後、アイコンプログラムの出力を観察することで手元のデータ形式を手動で観察するのに数日を費やし、この情報を手にして画像ローダーを構築することができました.

Allegro ゲーム ライブラリを使用して、BITMAP 画像を簡単に処理できるようにしました。Win32/GDI は処理が多すぎて、コードが非常に煩雑になります。


アイコンの場所とインデックスの検索:

(1) HKEY_CLASSES_ROOT の下の拡張子を探します。HKCR\.foo\(default) = "foofile"

(2)これのデフォルトデータは、次に見るキーです。HKCR\foofile\

(3)ここのデフォルトデータは説明です。HKCR\foofile\(default) = "Foo Document"

(4)アイコンの場所は、私が知っている 2 つの場所のいずれかにある可能性があります。

HKCR\foofile\DefaultIcon\(default) または、アイコンの場所HKCR\foofile\CurVer\(default) = "foofile.1"のキーを確認するように指示するようなエントリがある場合がありHKCR\foofile.1\DefaultIcon\(default)ます。

アイコン位置文字列の解析:

文字列は、カンマ、空白、場合によってはマイナス記号、およびアイコンの「インデックス」を示す数字が続く単純なパスです。

ここで大きな落とし穴があります:アイコン インデックスを N にします。N が負の場合 (負のゼロをチェックしたい場合があります!)、それは指定されたファイル内のリソース IDです。N が正の場合、ファイル内のN番目のアイコンを検索することを意味しますが、アイコンは必ずしもリソース ID 番号 N に


アイコン構造を手動で解析する:

これは大部分のコードと費やされた時間ですが、見事に機能します。まず、カラー データとマスク データのさまざまなセクションのデータ形式を次に示します。

データ ブロックの形式:

32bit ... Color Data:
====================================================================================
Little Endian 4 byte ARGB values.
The rows are stored in reverse order (bottom to top).


24bit ... Color Data:
====================================================================================
Little Endian 3 byte RGB values.
Tightly Packed (NO PADDING).
INSERT PADDING BYTES TO GO UP TO NEXT DWORD AT END OF ROW. SET THEM TO 0x00.
The rows are stored in reverse order (bottom to top).


16bit ... Color Data:
====================================================================================
Little Endian 2 byte RGB values. 5 bits each with MSB = 0.
Tightly Packed (NO PADDING).
INSERT PADDING BYTES TO GO UP TO NEXT DWORD AT END OF ROW. SET THEM TO 0x00.
The rows are stored in reverse order (bottom to top).


8bit ... Palette & Color Data:
====================================================================================
The Palette is Little Endian 4 byte RGB0 values. No alpha.
There *might* be up to 256 palette entries.
If number of colors is reported as zero, assume 256 color entires.
The Pixels are 1 byte index values.
INSERT PADDING BYTES TO GO UP TO NEXT DWORD AT END OF ROW. SET THEM TO 0x00.
The rows are stored in reverse order (bottom to top).


4bit ... Palette & Color Data:
====================================================================================
The Palette is Little Endian 4 byte RGB0 values. No alpha.
There *might* be up to 16 palette entries.
If number of colors is reported as zero, assume 16 color entires.
The Pixels are nybble-length index values.
INSERT PADDING BYTES TO GO UP TO NEXT DWORD AT END OF ROW. SET THEM TO 0x00.
The rows are stored in reverse order (bottom to top).


Mask Data:
====================================================================================
Is a string of bytes with mask bits starting at MSB and going towards LSB.
There are ((imagewidth+31)>>5) DWORDS per row in *BIG ENDIAN* order.
Like the color data, there is a set of DWORDS for each row.
The rows are stored in reverse order (bottom to top).
Set unused padding bits/pixels at end of each row to 1. 
0 indicates opaque and 1 indicates transparent.


1bit ... XOR Mask, AND Mask, & Color Data:
====================================================================================
The Palette is Little Endian 4 byte RGB0 values. No alpha.
There should be exactly 2 palette entries: usually 0x00000000 and 0x00FFFFFF.
The two masks follow the Mask Data format decribed above.
The following results from combining two mask bits:
    XOR AND RESULT:
     0   0  Color #0 (Black)
     0   1  Transparent
     1   0  Color #1 (White)
     1   1  Invert Destination Bitmap

もちろん、このままにしておくつもりはありませんでした。必要なコードがあります。

次のコードは、特定のアイコン位置のすべてのアイコン イメージをロードして、32bpp BITMAP のベクターに変換します。特定の画像の読み込みに失敗した場合、その画像はベクターに追加されません (または、破損したアイコンの場合、破損した画像が生成される可能性が高いため、注意してください)。

このコードは、モノクロ イメージの「反転」カラーをサポートしておらず、アルファが 0 のままの別のカラーを生成するだけです。

警告: いくつかの疑似コードが含まれており、要点だけに短縮されています。

アイコン ローダー コード (サポート: EXE、DLL、32 ビット ICL、ICO):

// Code written by Simion32.
// Please feel free to use it anywhere. 
// Credit would be nice but isn't required.

#include "include.h" //std::vectors and whatever else you need
#include <allegro.h>
#include <winalleg.h> //Allegro and Win32
#include "Shellapi.h"

// In the following block, the (required!!) pragmas
// force correct data alignment. Needed in at least GCC.
#pragma pack( push, 1 ) 
typedef struct
{
    BYTE                bWidth;         // Width, in pixels, of the image
    BYTE                bHeight;        // Height, in pixels, of the image
    BYTE                bColorCount;    // Number of colors in image (0 if >=8bpp)
    BYTE                bReserved;      // Reserved ( must be 0)
    WORD                wPlanes;        // Color Planes
    WORD                wBitCount;      // Bits per pixel
    DWORD               dwBytesInRes;   // How many bytes in this resource?
    DWORD               dwImageOffset;  // Where in the file is this image?
} ICONDIRENTRY, *LPICONDIRENTRY;
typedef struct
{
    WORD                idReserved;     // Reserved (must be 0)
    WORD                idType;         // Resource Type (1 for icons)
    WORD                idCount;        // How many images?
    ICONDIRENTRY        idEntries[1];   // An entry for each image (idCount of 'em)
} ICONDIR, *LPICONDIR;
typedef struct
{
   BITMAPINFOHEADER     icHeader;       // DIB header
   RGBQUAD              icColors[1];    // Color table
   BYTE                 icXOR[1];       // DIB bits for XOR mask
   BYTE                 icAND[1];       // DIB bits for AND mask
} ICONIMAGE, *LPICONIMAGE;
#pragma pack( pop)
#pragma pack( push, 2 )
typedef struct
{
   BYTE                 bWidth;         // Width, in pixels, of the image
   BYTE                 bHeight;        // Height, in pixels, of the image
   BYTE                 bColorCount;    // Number of colors in image (0 if >=8bpp)
   BYTE                 bReserved;      // Reserved
   WORD                 wPlanes;        // Color Planes
   WORD                 wBitCount;      // Bits per pixel
   DWORD                dwBytesInRes;   // total size of the RT_ICON resource referenced by the nID member.
   WORD                 nID;            // resourceID of RT_ICON (LockResource to obtain a pointer to its ICONIMAGE)
} GRPICONDIRENTRY, *LPGRPICONDIRENTRY;
typedef struct 
{
   WORD                 idReserved;     // Reserved (must be 0)
   WORD                 idType;         // Resource type (1 for icons)
   WORD                 idCount;        // How many images?
   GRPICONDIRENTRY      idEntries[1];   // The entries for each image
} GRPICONDIR, *LPGRPICONDIR;
#pragma pack( pop )




uint32_t Convert16BitToARGB(uint16_t value)
{
    return (0xFF000000|((value >>  7) & 0x0000F8)|((value <<  6) & 0x00F800)|((value << 19) & 0xF80000));
}
uint32_t GetMaskBit(uint8_t* data, int x, int y, int w, int h)
{
    uint32_t mask_data_rowsize = (((w+31)>>5) * 4);
    return ((~(data[(mask_data_rowsize * ((h-1)-y)) + (x >> 3)] >> (0x07 - (x & 0x07))) & 1) * 0xFFFFFFFF);
}
uint32_t GetColorMonochrome(uint8_t* xordata, uint8_t* anddata, int x, int y, int w, int h, uint32_t* pal)
{
    uint32_t mask_data_rowsize = (((w+31)>>5) * 4);
    uint32_t xor_bit = (((xordata[(mask_data_rowsize * ((h-1)-y)) + (x >> 3)] >> (0x07 - (x & 0x07))) << 1) & 2);
    uint32_t and_bit = (((anddata[(mask_data_rowsize * ((h-1)-y)) + (x >> 3)] >> (0x07 - (x & 0x07)))     ) & 1);
    uint32_t value = (xor_bit | and_bit);
    return pal[value];
}



BITMAP* CreateBmp32bppFromIconResData(void* data, int size, int depth, int w, int h, int colors)
{
    char* pngheader = "\211PNG\r\n\032\n";
    char* cpd = (char*)data;
    bool is_png = ((cpd[0]==pngheader[0])
                && (cpd[1]==pngheader[1])
                && (cpd[2]==pngheader[2])
                && (cpd[3]==pngheader[3])
                && (cpd[4]==pngheader[4])
                && (cpd[5]==pngheader[5])
                && (cpd[6]==pngheader[6])
                && (cpd[7]==pngheader[7]));
    if(is_png)
    {
        //###########################################################
        //#  PSEUDO-CODE: Somehow convert the PNG file into a bitmap.
        BITMAP* result = ConvertPngFileToBmp32bpp(data, size);
        return result;
    }
    else
    {
        uint32_t ignore_size = ((BITMAPINFOHEADER*)(data))->biSize;
        BITMAP* bmp = create_bitmap_ex(32,w,h);
        uint32_t pixel_count = (w * h);
        uint32_t color_data_size = ((((((w * depth)+7) >> 3) +3) & ~3) * h);
        switch(depth)
        {
            default: return bmp; break;
            case 32:
            {
                uint32_t* src = (uint32_t*)(((uint8_t*)data) + ignore_size);
                for(int yy = h-1; yy >= 0; --yy){
                    for(int xx = 0; xx < w; ++xx){
                        _putpixel32(bmp,xx,yy,src[0]);
                        src++;
                    }
                    //There should never be any padding to jump over here.
                }
                return bmp;
            }
            break;
            case 24:
            {
                uint32_t* src = (uint32_t*)(((uint8_t*)data) + ignore_size);
                uint8_t* bitmask = (uint8_t*)(((uint8_t*)data) + ignore_size + color_data_size);
                int padding_checker = 0;
                for(int yy = h-1; yy >= 0; --yy){
                    for(int xx = 0; xx < w; ++xx){
                        _putpixel32(bmp,xx,yy,((src[0] & 0x00FFFFFF) | 0xFF000000) & GetMaskBit(bitmask, xx, yy, w, h));
                        src++;
                        src = (uint32_t*)(((uint8_t*)src)-1); //go back a byte due to packing
                        padding_checker += 3;
                        padding_checker &= 3;
                    }
                    //This loop jumps over any padding bytes.
                    while(padding_checker)
                    {
                        src = (uint32_t*)(((uint8_t*)src)+1);
                        padding_checker++;
                        padding_checker &= 3;
                    }
                }
                return bmp;
            }
            break;
            case 16:
            {
                //Note: there might be a color table present! ignore it.
                uint16_t* src = (uint16_t*)(((uint8_t*)data) + ignore_size + (colors << 2));
                uint8_t* bitmask = (uint8_t*)(((uint8_t*)data) + ignore_size + (colors << 2) + color_data_size);
                int padding_checker = 0;
                for(int yy = h-1; yy >= 0; --yy){
                    for(int xx = 0; xx < w; ++xx){
                        _putpixel32(bmp,xx,yy,Convert16BitToARGB(src[0]) & GetMaskBit(bitmask, xx, yy, w, h));
                        src++;
                        padding_checker += 2;
                        padding_checker &= 3;
                    }
                    //This loop jumps over any padding bytes.
                    while(padding_checker)
                    {
                        src = (uint16_t*)(((uint8_t*)src)+1);
                        padding_checker++;
                        padding_checker &= 3;
                    }
                }
                return bmp;
            }
            break;
            case 8:
            {
                if(colors > 256) colors = 256; //Color Count must be restricted to 256 entries at the most.
                if(colors <=  0) colors = 256; //Color Count might be reported as zero. This means 256.
                uint8_t* src = (((uint8_t*)data) + ignore_size + (colors << 2));
                uint32_t* pal = ((uint32_t*)(((uint8_t*)data) + ignore_size));
                uint8_t* bitmask = (uint8_t*)(((uint8_t*)data) + ignore_size + (colors << 2) + color_data_size);
                int padding_checker = 0;
                for(int yy = h-1; yy >= 0; --yy){
                    for(int xx = 0; xx < w; ++xx){
                        uint8_t color = src[0];
                        if(color < colors){
                            _putpixel32(bmp,xx,yy,(pal[color] | 0xFF000000) & GetMaskBit(bitmask, xx, yy, w, h));
                        }else{
                            _putpixel32(bmp,xx,yy,0x00FF00FF);
                        }
                        src++;
                        padding_checker++;
                        padding_checker &= 3;
                    }
                    //This loop jumps over any padding bytes.
                    while(padding_checker)
                    {
                        src++;
                        padding_checker++;
                        padding_checker &= 3;
                    }
                }
                return bmp;
            }
            break;
            case 4:
            {
                if(colors > 16) colors = 16; //Color Count must be restricted to 16 entries at the most.
                if(colors <= 0) colors = 16; //Color Count might be reported as zero. This means 16.
                uint8_t* src = (((uint8_t*)data) + ignore_size + (colors << 2));
                uint32_t* pal = ((uint32_t*)(((uint8_t*)data) + ignore_size));
                uint8_t* bitmask = (uint8_t*)(((uint8_t*)data) + ignore_size + (colors << 2) + color_data_size);
                int padding_checker = 0;
                for(int yy = h-1; yy >= 0; --yy){
                    for(int xx = 0; xx < w; ++xx){
                        uint8_t color = src[0];
                        if(xx & 1) color = ( color       & 0x0F);
                        else       color = ((color >> 4) & 0x0F);
                        if(color < colors){
                            _putpixel32(bmp,xx,yy,(pal[color] | 0xFF000000) & GetMaskBit(bitmask, xx, yy, w, h));
                        }else{
                            _putpixel32(bmp,xx,yy,0x00FF00FF);
                        }
                        if(xx & 1)
                        {
                            src++;
                            padding_checker++;
                            padding_checker &= 3;
                        }
                    }
                    //if the pointer hasn't incremented to the next byte yet, do so.
                    if(w & 1) //odd width
                    {
                        src++;
                        padding_checker++;
                        padding_checker &= 3;
                    }
                    //This loop jumps over any padding bytes.
                    while(padding_checker)
                    {
                        src++;
                        padding_checker++;
                        padding_checker &= 3;
                    }
                }
                return bmp;
            }
            break;
            case 1:
            {
                if(colors >  2) colors = 2; //Color Count must be restricted to 2 entries at the most.
                if(colors <= 0) colors = 2; //Color Count might be reported as zero. This means 2.
                uint32_t* pal        = (uint32_t*)(((uint8_t*)data) + ignore_size);
                uint8_t* bitmaskXOR = (uint8_t*)(((uint8_t*)data) + ignore_size + (colors << 2));
                uint8_t* bitmaskAND = (uint8_t*)(((uint8_t*)data) + ignore_size + (colors << 2) + color_data_size);
                uint32_t  ret_colors[4] = {pal[0]|0xFF000000, 0x00FF00FF, pal[1]|0xFF000000, 0x0000FF00};
                for(int yy = h-1; yy >= 0; --yy){
                    for(int xx = 0; xx < w; ++xx){
                        _putpixel32(bmp,xx,yy,GetColorMonochrome(bitmaskXOR, bitmaskAND, xx, yy, w, h, ret_colors));
                    }
                }
                return bmp;
            }
            break;
        }
        return bmp;
    }
}



vector< BITMAP* > ResourceToBitmapVector(HMODULE hm, HRSRC hr, bool is_group_icon)
{
    vector< BITMAP* > results;
    if(is_group_icon)
    {
        HGLOBAL hg = LoadResource(hm,hr);
        GRPICONDIR* gd = (GRPICONDIR*)LockResource(hg);
        if(gd->idType == 1)
        {
            for(int i = 0; i < gd->idCount; ++i)
            {
                //WARNING: The GRPICONDIRENTRY's data might be wrong!
                GRPICONDIRENTRY* ie = (GRPICONDIRENTRY*)&(gd->idEntries[i]);
                HRSRC ihr = FindResource(hm,MAKEINTRESOURCE(ie->nID),RT_ICON);
                if(ihr != NULL)
                {
                    HGLOBAL ihg = LoadResource(hm,ihr);
                    void* data = (void*)LockResource(ihg);
                    DWORD size = SizeofResource(hm,ihr);
                    uint32_t b = ((BITMAPINFOHEADER*)(data))->biBitCount;
                    uint32_t w = ((BITMAPINFOHEADER*)(data))->biWidth;
                    uint32_t h = (((BITMAPINFOHEADER*)(data))->biHeight >> 1); //icons have doubled height value.
                    uint32_t c = ((BITMAPINFOHEADER*)(data))->biClrUsed;
                    results.push_back(CreateBmp32bppFromIconResData(data, size, b, w, h, c));
                }
            }
        }
    }
    else
    {
        HGLOBAL ihg = LoadResource(hm,hr);
        void* data = (void*)LockResource(ihg);
        DWORD size = SizeofResource(hm,hr);
        uint32_t b = ((BITMAPINFOHEADER*)(data))->biBitCount;
        uint32_t w = ((BITMAPINFOHEADER*)(data))->biWidth;
        uint32_t h = (((BITMAPINFOHEADER*)(data))->biHeight >> 1); //icons have doubled height value.
        uint32_t c = ((BITMAPINFOHEADER*)(data))->biClrUsed;
        results.push_back(CreateBmp32bppFromIconResData(data, size, b, w, h, c));
    }
    return results;
}



vector< BITMAP* > IconFileToBitmapVector(void* icon_data, uint32_t icon_size)
{
    vector< BITMAP* > results;
    ICONDIR* gd = (ICONDIR*)icon_data;
    if(gd->idType == 1) 
    {
        for(int i = 0; i < gd->idCount; ++i)
        {
            //WARNING: The ICONDIRENTRY's data might be wrong!
            DWORD offset = gd->idEntries[i].dwImageOffset;
            DWORD size = gd->idEntries[i].dwBytesInRes;
            void* data = (void*)(((uint8_t*)icon_data) + ((uint32_t)offset));
            uint32_t b = ((BITMAPINFOHEADER*)(data))->biBitCount;
            uint32_t w = ((BITMAPINFOHEADER*)(data))->biWidth;
            uint32_t h = (((BITMAPINFOHEADER*)(data))->biHeight >> 1); //icons have doubled height value.
            uint32_t c = ((BITMAPINFOHEADER*)(data))->biClrUsed;
            results.push_back(CreateBmp32bppFromIconResData(data, size, b, w, h, c));
        }
    }
    return results;
}



vector< BITMAP* > UnearthIconResource(string& file, bool self_refrence, bool res_index, int index)
{
    #define LOAD_IGNORE_CODE_AUTHZ_LEVEL 0x00000010

    //prevents a negative indexing error 
    // (the boolean res_index handles whether it's icon index VS resource ID)
    index = abs(index); 

    vector< BITMAP* > results; //array of results to return (pointers to 32bpp images)

    //extract and 'demangle' the file extension by convertng to lowercase.
    string ext = get_file_extension(file.c_str());
    for(int i = 0; i < ext.size(); ++i) ext[i] = tolower(ext[i]);

    bool is_icl = false;
    if((ext == "exe") || (ext == "dll") || (ext == "scr") || (is_icl = (ext == "icl")))
    {
        // Portable Executable Resource (works for both DLL and EXE)
        // Also works for any 32bit Icon Library (Microangelo Studio?)
        HMODULE hm = LoadLibraryEx(file.c_str(), NULL, 
            (DONT_RESOLVE_DLL_REFERENCES | LOAD_IGNORE_CODE_AUTHZ_LEVEL | LOAD_LIBRARY_AS_DATAFILE));
        if(hm != NULL)
        {
            HRSRC hr;
            if(!self_refrence)
            {
                if(res_index)
                {
                    //The icon we want is at the resource ID (==index)
                    bool is_single_icon = false;
                    hr = FindResource(hm,MAKEINTRESOURCE(index),RT_GROUP_ICON);
                    if(hr == NULL)
                    {
                        hr = FindResource(hm,MAKEINTRESOURCE(index),RT_ICON);
                        is_single_icon = (hr != NULL);
                    }
                    if(hr != NULL)
                    {
                        results = ResourceToBitmapVector(hm, hr, !is_single_icon);
                    }
                }
                else
                {
                    //The icon we want is the (index)'th icon in the file
                    //We must preform a manual search for the resource ID!
                    //WARNING: Using EnumResourceNames() *DOES NOT WORK PROPERLY* for this.
                    for(int nicon = 0, i = 0; i < 0x8000; ++i)
                    {
                        bool is_single_icon = false;
                        hr = FindResource(hm,MAKEINTRESOURCE(i),RT_GROUP_ICON);
                        if(hr != NULL)
                        {
                            if(nicon == index)
                            {
                                results = ResourceToBitmapVector(hm, hr, true);
                                break;
                            }
                            nicon++;
                        }
                    }
                }
            }
            else
            {
                //The icon we want is the "first" icon in the file. 
                //Happens when location is a %1.
                //We must preform a manual search for the resource ID!
                //WARNING: Using EnumResourceNames() *DOES NOT WORK PROPERLY* for this.
                for(int i = 0; i < 0x8000; ++i)
                {
                    bool is_single_icon = false;
                    hr = FindResource(hm,MAKEINTRESOURCE(i),RT_GROUP_ICON);
                    if(hr != NULL)
                    {
                        results = ResourceToBitmapVector(hm, hr, true);
                        break;
                    }
                }
            }
            FreeLibrary(hm);
        }
        else /*if(is_icl)
        {//OH NOES. We have to load a *16bit* .icl file!
            //not supported yet. sorry. left as another excecise to the programmer.
        }*/
    }
    else if(ext == "ico")
    {
        //Single Icon File

        //###################################################
        //#  PSEUDO-CODE: Do the file loading yourself ;)
        void* data_pointer = NULL;
        uint32_t data_size = 0;
        if(data_pointer = MyLoadFile(file.c_str(), &data_size))
        {
            if(data_size)
            {
                results = IconFileToBitmapVector((void*)data_pointer, data_size);
            }
        }
        MyCloseFile(data_pointer);
    }
    return results;
}

これでほぼ網羅できると思いますが…

最後に 1 つ注意しなければならないことがあります。アイコン ディレクトリ エントリからのサイズとビット深度の情報は無視してください。それらはしばしば間違っている可能性があります。256 色のイメージが 24 ビットとして報告され、イメージ ローダー内でデータが破損しているのを見たことがあります。

于 2013-05-23T17:46:47.973 に答える