簡體   English   中英

如何將 HICON 保存為 .ico 文件?

[英]How can I save HICON to an .ico file?

我正在從 .exe/.dll 中提取一個圖標,並希望將其保存在一個 .ico 文件中。 做這個的最好方式是什么?

我嘗試使用::OleCreatePictureIndirect() ,然后使用IPicture->SaveAsFile() 它可以工作,但圖標的透明部分被塗成黑色(顯然不再透明了:()。

我嘗試手動解析。 它工作正常,但很麻煩,我擔心 Vista 圖標/.icl 文件/等會出現並發症。

請幫忙。 謝謝。

您可以使用IPicture::SaveAsFile()方法保存HICON 這是一個使用它的示例 C++ 程序:

#include "stdafx.h"
#include <windows.h>
#include <olectl.h>
#pragma comment(lib, "oleaut32.lib")

HRESULT SaveIcon(HICON hIcon, const wchar_t* path) {
    // Create the IPicture intrface
    PICTDESC desc = { sizeof(PICTDESC) };
    desc.picType = PICTYPE_ICON;
    desc.icon.hicon = hIcon;
    IPicture* pPicture = 0;
    HRESULT hr = OleCreatePictureIndirect(&desc, IID_IPicture, FALSE, (void**)&pPicture);
    if (FAILED(hr)) return hr;

    // Create a stream and save the image
    IStream* pStream = 0;
    CreateStreamOnHGlobal(0, TRUE, &pStream);
    LONG cbSize = 0;
    hr = pPicture->SaveAsFile(pStream, TRUE, &cbSize);

    // Write the stream content to the file
    if (!FAILED(hr)) {
        HGLOBAL hBuf = 0;
        GetHGlobalFromStream(pStream, &hBuf);
        void* buffer = GlobalLock(hBuf);
        HANDLE hFile = CreateFile(path, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
        if (!hFile) hr = HRESULT_FROM_WIN32(GetLastError());
        else {
            DWORD written = 0;
            WriteFile(hFile, buffer, cbSize, &written, 0);
            CloseHandle(hFile);
        }
        GlobalUnlock(buffer);
    }
    // Cleanup
    pStream->Release();
    pPicture->Release();
    return hr;

}
int _tmain(int argc, _TCHAR* argv[])
{
    HICON hIcon = (HICON)LoadImage(0, L"c:\\windows\\system32\\perfcentercpl.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE);
    if (!hIcon) return GetLastError();
    HRESULT hr = SaveIcon(hIcon, L"c:\\temp\\test.ico");
    return hr;
}

此代碼正確處理透明度。

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

//
// ICONS (.ICO type 1) are structured like this:
//
// ICONHEADER (just 1)
// ICONDIR [1...n] (an array, 1 for each image)
// [BITMAPINFOHEADER+COLOR_BITS+MASK_BITS] [1...n] (1 after the other, for each image)
//
// CURSORS (.ICO type 2) are identical in structure, but use
// two monochrome bitmaps (real XOR and AND masks, this time).
//

typedef struct
{
    WORD idReserved; // must be 0
    WORD idType; // 1 = ICON, 2 = CURSOR
    WORD idCount; // number of images (and ICONDIRs)

    // ICONDIR [1...n]
    // ICONIMAGE [1...n]

} ICONHEADER;

//
// An array of ICONDIRs immediately follow the ICONHEADER
//
typedef struct
{
    BYTE bWidth;
    BYTE bHeight;
    BYTE bColorCount;
    BYTE bReserved;
    WORD wPlanes; // for cursors, this field = wXHotSpot
    WORD wBitCount; // for cursors, this field = wYHotSpot
    DWORD dwBytesInRes;
    DWORD dwImageOffset; // file-offset to the start of ICONIMAGE

} ICONDIR;

//
// After the ICONDIRs follow the ICONIMAGE structures -
// consisting of a BITMAPINFOHEADER, (optional) RGBQUAD array, then
// the color and mask bitmap bits (all packed together
//
typedef struct
{
    BITMAPINFOHEADER biHeader; // header for color bitmap (no mask header)
    //RGBQUAD rgbColors[1...n];
    //BYTE bXOR[1]; // DIB bits for color bitmap
    //BYTE bAND[1]; // DIB bits for mask bitmap

} ICONIMAGE;

//
// Write the ICO header to disk
//
static UINT WriteIconHeader(HANDLE hFile, int nImages)
{
    ICONHEADER iconheader;
    DWORD nWritten;

    // Setup the icon header
    iconheader.idReserved = 0; // Must be 0
    iconheader.idType = 1; // Type 1 = ICON (type 2 = CURSOR)
    iconheader.idCount = nImages; // number of ICONDIRs

    // Write the header to disk
    WriteFile( hFile, &iconheader, sizeof(iconheader), &nWritten, 0);

    // following ICONHEADER is a series of ICONDIR structures (idCount of them, in fact)
    return nWritten;
}

//
// Return the number of BYTES the bitmap will take ON DISK
//
static UINT NumBitmapBytes(BITMAP *pBitmap)
{
    int nWidthBytes = pBitmap->bmWidthBytes;

    // bitmap scanlines MUST be a multiple of 4 bytes when stored
    // inside a bitmap resource, so round up if necessary
    if(nWidthBytes & 3)
        nWidthBytes = (nWidthBytes + 4) & ~3;

    return nWidthBytes * pBitmap->bmHeight;
}

//
// Return number of bytes written
//
static UINT WriteIconImageHeader(HANDLE hFile, BITMAP *pbmpColor, BITMAP *pbmpMask)
{
    BITMAPINFOHEADER biHeader;
    DWORD nWritten;
    UINT nImageBytes;

    // calculate how much space the COLOR and MASK bitmaps take
    nImageBytes = NumBitmapBytes(pbmpColor) + NumBitmapBytes(pbmpMask);

    // write the ICONIMAGE to disk (first the BITMAPINFOHEADER)
    ZeroMemory(&biHeader, sizeof(biHeader));

    // Fill in only those fields that are necessary
    biHeader.biSize = sizeof(biHeader);
    biHeader.biWidth = pbmpColor->bmWidth;
    biHeader.biHeight = pbmpColor->bmHeight * 2; // height of color+mono
    biHeader.biPlanes = pbmpColor->bmPlanes;
    biHeader.biBitCount = pbmpColor->bmBitsPixel;
    biHeader.biSizeImage = nImageBytes;

    // write the BITMAPINFOHEADER
    WriteFile(hFile, &biHeader, sizeof(biHeader), &nWritten, 0);

    // write the RGBQUAD color table (for 16 and 256 colour icons)
    if(pbmpColor->bmBitsPixel == 2 || pbmpColor->bmBitsPixel == 8)
    {

    }

    return nWritten;
}

//
// Wrapper around GetIconInfo and GetObject(BITMAP)
//
static BOOL GetIconBitmapInfo(HICON hIcon, ICONINFO *pIconInfo, BITMAP *pbmpColor, BITMAP *pbmpMask)
{
    if(!GetIconInfo(hIcon, pIconInfo))
        return FALSE;

    if(!GetObject(pIconInfo->hbmColor, sizeof(BITMAP), pbmpColor))
        return FALSE;

    if(!GetObject(pIconInfo->hbmMask, sizeof(BITMAP), pbmpMask))
        return FALSE;

    return TRUE;
}

//
// Write one icon directory entry - specify the index of the image
//
static UINT WriteIconDirectoryEntry(HANDLE hFile, int nIdx, HICON hIcon, UINT nImageOffset)
{
    ICONINFO iconInfo;
    ICONDIR iconDir;

    BITMAP bmpColor;
    BITMAP bmpMask;

    DWORD nWritten;
    UINT nColorCount;
    UINT nImageBytes;

    GetIconBitmapInfo(hIcon, &iconInfo, &bmpColor, &bmpMask);

    nImageBytes = NumBitmapBytes(&bmpColor) + NumBitmapBytes(&bmpMask);

    if(bmpColor.bmBitsPixel >= 8)
        nColorCount = 0;
    else
        nColorCount = 1 << (bmpColor.bmBitsPixel * bmpColor.bmPlanes);

    // Create the ICONDIR structure
    iconDir.bWidth = (BYTE)bmpColor.bmWidth;
    iconDir.bHeight = (BYTE)bmpColor.bmHeight;
    iconDir.bColorCount = nColorCount;
    iconDir.bReserved = 0;
    iconDir.wPlanes = bmpColor.bmPlanes;
    iconDir.wBitCount = bmpColor.bmBitsPixel;
    iconDir.dwBytesInRes = sizeof(BITMAPINFOHEADER) + nImageBytes;
    iconDir.dwImageOffset = nImageOffset;

    // Write to disk
    WriteFile(hFile, &iconDir, sizeof(iconDir), &nWritten, 0);

    // Free resources
    DeleteObject(iconInfo.hbmColor);
    DeleteObject(iconInfo.hbmMask);

    return nWritten;
}

static UINT WriteIconData(HANDLE hFile, HBITMAP hBitmap)
{
    BITMAP bmp;
    int i;
    BYTE * pIconData;

    UINT nBitmapBytes;
    DWORD nWritten;

    GetObject(hBitmap, sizeof(BITMAP), &bmp);

    nBitmapBytes = NumBitmapBytes(&bmp);

    pIconData = (BYTE *)malloc(nBitmapBytes);

    GetBitmapBits(hBitmap, nBitmapBytes, pIconData);

    // bitmaps are stored inverted (vertically) when on disk..
    // so write out each line in turn, starting at the bottom + working
    // towards the top of the bitmap. Also, the bitmaps are stored in packed
    // in memory - scanlines are NOT 32bit aligned, just 1-after-the-other
    for(i = bmp.bmHeight - 1; i >= 0; i--)
    {
        // Write the bitmap scanline
        WriteFile(
            hFile,
            pIconData + (i * bmp.bmWidthBytes), // calculate offset to the line
            bmp.bmWidthBytes, // 1 line of BYTES
            &nWritten,
            0);

        // extend to a 32bit boundary (in the file) if necessary
        if(bmp.bmWidthBytes & 3)
        {
            DWORD padding = 0;
            WriteFile(hFile, &padding, 4 - bmp.bmWidthBytes, &nWritten, 0);
        }
    }

    free(pIconData);

    return nBitmapBytes;
}

//
// Create a .ICO file, using the specified array of HICON images
//
BOOL SaveIcon3(TCHAR *szIconFile, HICON hIcon[], int nNumIcons)
{
    HANDLE hFile;
    int i;
    int * pImageOffset;

    if(hIcon == 0 || nNumIcons < 1)
        return FALSE;

    // Save icon to disk:
    hFile = CreateFile(szIconFile, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);

    if(hFile == INVALID_HANDLE_VALUE)
        return FALSE;

    //
    // Write the iconheader first of all
    //
    WriteIconHeader(hFile, nNumIcons);

    //
    // Leave space for the IconDir entries
    //
    SetFilePointer(hFile, sizeof(ICONDIR) * nNumIcons, 0, FILE_CURRENT);

    pImageOffset = (int *)malloc(nNumIcons * sizeof(int));

    //
    // Now write the actual icon images!
    //
    for(i = 0; i < nNumIcons; i++)
    {
        ICONINFO iconInfo;
        BITMAP bmpColor, bmpMask;

        GetIconBitmapInfo(hIcon[i], &iconInfo, &bmpColor, &bmpMask);

        // record the file-offset of the icon image for when we write the icon directories
        pImageOffset[i] = SetFilePointer(hFile, 0, 0, FILE_CURRENT);

        // bitmapinfoheader + colortable
        WriteIconImageHeader(hFile, &bmpColor, &bmpMask);

        // color and mask bitmaps
        WriteIconData(hFile, iconInfo.hbmColor);
        WriteIconData(hFile, iconInfo.hbmMask);

        DeleteObject(iconInfo.hbmColor);
        DeleteObject(iconInfo.hbmMask);
    }

    //
    // Lastly, skip back and write the icon directories.
    //
    SetFilePointer(hFile, sizeof(ICONHEADER), 0, FILE_BEGIN);

    for(i = 0; i < nNumIcons; i++)
    {
        WriteIconDirectoryEntry(hFile, i, hIcon[i], pImageOffset[i]);
    }

    free(pImageOffset);

    // finished!
    CloseHandle(hFile);

    return TRUE;
}


int saveIcon(TCHAR* filename, TCHAR* iconFile) {
    HICON hIconLarge;
    HICON hIconSmall;
    BOOL ret;


    if ( ExtractIconEx(filename, 0, &hIconLarge, &hIconSmall, 1) == 0 ) {
        return 1;
    }

    ret = SaveIcon3(iconFile, &hIconSmall, 1);
    if ( ret ) {
        return 0;
    }
    return -1;
}

int _tmain(int argc, TCHAR* argv[]) {
    if ( argc < 3 ) {
        printf("Usage: <exe/dll file> <output ico file>");
        return EXIT_FAILURE;
    }
    _tprintf(_T("src = %s\n"), argv[1]);
    _tprintf(_T("dest = %s\n"), argv[2]);
    saveIcon(argv[1], argv[2]);

    return 0;
}

我遇到了同樣的問題,因此我編寫了一個函數來將圖標從 HICON 句柄保存到 ICO 文件。 下面顯示的SaveIcon()函數支持SaveIcon()和 32 位的顏色深度。 不支持 PNG 圖標格式。

該函數通過直接構建 ICO 文件來工作。 幸運的是,這並不太難,因為ICO格式與BMP文件格式幾乎相同; 此外,BMP 文件格式幾乎與GetDIBits()返回的內存中表示相同。

這是SaveIcon()函數,以及一個小的測試函數 ( _tmain ):

#include <afx.h>
#include <afxwin.h>
#include <atlbase.h>

struct ICONDIRENTRY
{
    UCHAR nWidth;
    UCHAR nHeight;
    UCHAR nNumColorsInPalette; // 0 if no palette
    UCHAR nReserved; // should be 0
    WORD nNumColorPlanes; // 0 or 1
    WORD nBitsPerPixel;
    ULONG nDataLength; // length in bytes
    ULONG nOffset; // offset of BMP or PNG data from beginning of file
};

// Helper class to release GDI object handle when scope ends:
class CGdiHandle
{
public:
    CGdiHandle(HGDIOBJ handle) : m_handle(handle) {};
    ~CGdiHandle(){DeleteObject(m_handle);};
private:
    HGDIOBJ m_handle;
};


// Save icon referenced by handle 'hIcon' as file with name 'szPath'.
// The generated ICO file has the color depth specified in 'nColorBits'.
//
bool SaveIcon(HICON hIcon, int nColorBits, const TCHAR* szPath)
{
    ASSERT(nColorBits == 4 || nColorBits == 8 || nColorBits == 24 || nColorBits == 32);

    if (offsetof(ICONDIRENTRY, nOffset) != 12)
    {
        return false;
    }

    CDC dc;
    dc.Attach(::GetDC(NULL)); // ensure that DC is released when function ends

    // Open file for writing:
    CFile file;
    if (!file.Open(szPath, CFile::modeWrite | CFile::modeCreate))
    {
        return false;
    }

    // Write header:
    UCHAR icoHeader[6] = {0, 0, 1, 0, 1, 0}; // ICO file with 1 image
    file.Write(icoHeader, sizeof(icoHeader));

    // Get information about icon:
    ICONINFO iconInfo;
    GetIconInfo(hIcon, &iconInfo);
    CGdiHandle handle1(iconInfo.hbmColor), handle2(iconInfo.hbmMask); // free bitmaps when function ends
    BITMAPINFO bmInfo = {0};
    bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmInfo.bmiHeader.biBitCount = 0;    // don't get the color table     
    if (!GetDIBits(dc, iconInfo.hbmColor, 0, 0, NULL, &bmInfo, DIB_RGB_COLORS))
    {
        return false;
    }

    // Allocate size of bitmap info header plus space for color table:
    int nBmInfoSize = sizeof(BITMAPINFOHEADER);
    if (nColorBits < 24)
    {
        nBmInfoSize += sizeof(RGBQUAD) * (int)(1 << nColorBits);
    }

    CAutoVectorPtr<UCHAR> bitmapInfo;
    bitmapInfo.Allocate(nBmInfoSize);
    BITMAPINFO* pBmInfo = (BITMAPINFO*)(UCHAR*)bitmapInfo;
    memcpy(pBmInfo, &bmInfo, sizeof(BITMAPINFOHEADER));

    // Get bitmap data:
    ASSERT(bmInfo.bmiHeader.biSizeImage != 0);
    CAutoVectorPtr<UCHAR> bits;
    bits.Allocate(bmInfo.bmiHeader.biSizeImage);
    pBmInfo->bmiHeader.biBitCount = nColorBits;
    pBmInfo->bmiHeader.biCompression = BI_RGB;
    if (!GetDIBits(dc, iconInfo.hbmColor, 0, bmInfo.bmiHeader.biHeight, (UCHAR*)bits, pBmInfo, DIB_RGB_COLORS))
    {
        return false;
    }

    // Get mask data:
    BITMAPINFO maskInfo = {0};
    maskInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    maskInfo.bmiHeader.biBitCount = 0;  // don't get the color table     
    if (!GetDIBits(dc, iconInfo.hbmMask, 0, 0, NULL, &maskInfo, DIB_RGB_COLORS))
    {
        return false;
    }
    ASSERT(maskInfo.bmiHeader.biBitCount == 1);
    CAutoVectorPtr<UCHAR> maskBits;
    maskBits.Allocate(maskInfo.bmiHeader.biSizeImage);
    CAutoVectorPtr<UCHAR> maskInfoBytes;
    maskInfoBytes.Allocate(sizeof(BITMAPINFO) + 2 * sizeof(RGBQUAD));
    BITMAPINFO* pMaskInfo = (BITMAPINFO*)(UCHAR*)maskInfoBytes;
    memcpy(pMaskInfo, &maskInfo, sizeof(maskInfo));
    if (!GetDIBits(dc, iconInfo.hbmMask, 0, maskInfo.bmiHeader.biHeight, (UCHAR*)maskBits, pMaskInfo, DIB_RGB_COLORS))
    {
        return false;
    }

    // Write directory entry:
    ICONDIRENTRY dir;
    dir.nWidth = (UCHAR) pBmInfo->bmiHeader.biWidth;
    dir.nHeight = (UCHAR) pBmInfo->bmiHeader.biHeight;
    dir.nNumColorsInPalette = (nColorBits == 4 ? 16 : 0);
    dir.nReserved = 0;
    dir.nNumColorPlanes = 0;
    dir.nBitsPerPixel = pBmInfo->bmiHeader.biBitCount;
    dir.nDataLength = pBmInfo->bmiHeader.biSizeImage + pMaskInfo->bmiHeader.biSizeImage + nBmInfoSize;
    dir.nOffset = sizeof(dir) + sizeof(icoHeader);
    file.Write(&dir, sizeof(dir));

    // Write DIB header (including color table):
    int nBitsSize = pBmInfo->bmiHeader.biSizeImage;
    pBmInfo->bmiHeader.biHeight *= 2; // because the header is for both image and mask
    pBmInfo->bmiHeader.biCompression = 0;
    pBmInfo->bmiHeader.biSizeImage += pMaskInfo->bmiHeader.biSizeImage; // because the header is for both image and mask
    file.Write(&pBmInfo->bmiHeader, nBmInfoSize);

    // Write image data:
    file.Write((UCHAR*)bits, nBitsSize);

    // Write mask data:
    file.Write((UCHAR*)maskBits, pMaskInfo->bmiHeader.biSizeImage);

    file.Close();

    return true;
}

// Test program for SaveIcon() function.
//
// Usage: first argument is input ICO file (must be 32x32 pixels); second argument is output ICO file
//
int _tmain(int argc, _TCHAR* argv[])
{
    ASSERT(argc == 3);

    // Load a 32x32 icon:
    HICON hIcon = (HICON)LoadImage(0, argv[1], IMAGE_ICON, 32, 32, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
    ASSERT(hIcon != NULL);

    // Save with 24-bits colors:
    if (!SaveIcon(hIcon, 24, argv[2]))
    {
        _ftprintf(stderr, _T("Error: saving icon to %s failed"), argv[2]);
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

非常感謝 user128300。 我使用了他的 snipet 並做了一些小改動來擺脫 MFC/atx/atl 庫的依賴(它還解決了 SMUsamaShah 提到的 Windows.h 的問題)。 我將輸出重定向到向量緩沖區,但將可選輸出保留到文件中:

#include <Windows.h>
#include <shellapi.h>

        struct ICONDIRENTRY
        {
            UCHAR nWidth;
            UCHAR nHeight;
            UCHAR nNumColorsInPalette; // 0 if no palette
            UCHAR nReserved; // should be 0
            WORD nNumColorPlanes; // 0 or 1
            WORD nBitsPerPixel;
            ULONG nDataLength; // length in bytes
            ULONG nOffset; // offset of BMP or PNG data from beginning of file
        };

#define WRITE_ICO_TO_FILE
            bool GetIconData(HICON hIcon, int nColorBits, std::vector<char> &buff)
            {

                if (offsetof(ICONDIRENTRY, nOffset) != 12)
                {
                    return false;
                }

                HDC dc = CreateCompatibleDC(NULL);

#ifdef WRITE_ICO_TO_FILE
                CFile file;
                if (!file.Open(L"S:\\icotest.ico", CFile::modeWrite | CFile::modeCreate))
                {
                    return false;
                }
#endif

                // Write header:
                char icoHeader[6] = { 0, 0, 1, 0, 1, 0 }; // ICO file with 1 image
#ifdef WRITE_ICO_TO_FILE
                file.Write(icoHeader, sizeof(icoHeader));
#endif
                buff.insert(buff.end(), reinterpret_cast<const char *>(icoHeader), reinterpret_cast<const char *>(icoHeader) + sizeof(icoHeader));

                // Get information about icon:
                ICONINFO iconInfo;
                GetIconInfo(hIcon, &iconInfo);
                BITMAPINFO bmInfo = { 0 };
                bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
                bmInfo.bmiHeader.biBitCount = 0;    // don't get the color table     
                if (!GetDIBits(dc, iconInfo.hbmColor, 0, 0, NULL, &bmInfo, DIB_RGB_COLORS))
                {
                    return false;
                }

                // Allocate size of bitmap info header plus space for color table:
                int nBmInfoSize = sizeof(BITMAPINFOHEADER);
                if (nColorBits < 24)
                {
                    nBmInfoSize += sizeof(RGBQUAD) * (int)(1 << nColorBits);
                }

                std::vector<UCHAR> bitmapInfo;
                bitmapInfo.resize(nBmInfoSize);
                BITMAPINFO* pBmInfo = (BITMAPINFO *)bitmapInfo.data();
                memcpy(pBmInfo, &bmInfo, sizeof(BITMAPINFOHEADER));

                // Get bitmap data:
                if (!bmInfo.bmiHeader.biSizeImage)
                    return false;
                std::vector<UCHAR> bits;
                bits.resize(bmInfo.bmiHeader.biSizeImage);
                pBmInfo->bmiHeader.biBitCount = nColorBits;
                pBmInfo->bmiHeader.biCompression = BI_RGB;
                if (!GetDIBits(dc, iconInfo.hbmColor, 0, bmInfo.bmiHeader.biHeight, bits.data(), pBmInfo, DIB_RGB_COLORS))
                {
                    return false;
                }

                // Get mask data:
                BITMAPINFO maskInfo = { 0 };
                maskInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
                maskInfo.bmiHeader.biBitCount = 0;  // don't get the color table     
                if (!GetDIBits(dc, iconInfo.hbmMask, 0, 0, NULL, &maskInfo, DIB_RGB_COLORS) || maskInfo.bmiHeader.biBitCount != 1)
                    return false;

                std::vector<UCHAR> maskBits;
                maskBits.resize(maskInfo.bmiHeader.biSizeImage);
                std::vector<UCHAR> maskInfoBytes;
                maskInfoBytes.resize(sizeof(BITMAPINFO) + 2 * sizeof(RGBQUAD));
                BITMAPINFO* pMaskInfo = (BITMAPINFO*)maskInfoBytes.data();
                memcpy(pMaskInfo, &maskInfo, sizeof(maskInfo));
                if (!GetDIBits(dc, iconInfo.hbmMask, 0, maskInfo.bmiHeader.biHeight, maskBits.data(), pMaskInfo, DIB_RGB_COLORS))
                {
                    return false;
                }

                // Write directory entry:
                ICONDIRENTRY dir;
                dir.nWidth = (UCHAR)pBmInfo->bmiHeader.biWidth;
                dir.nHeight = (UCHAR)pBmInfo->bmiHeader.biHeight;
                dir.nNumColorsInPalette = (nColorBits == 4 ? 16 : 0);
                dir.nReserved = 0;
                dir.nNumColorPlanes = 0;
                dir.nBitsPerPixel = pBmInfo->bmiHeader.biBitCount;
                dir.nDataLength = pBmInfo->bmiHeader.biSizeImage + pMaskInfo->bmiHeader.biSizeImage + nBmInfoSize;
                dir.nOffset = sizeof(dir) + sizeof(icoHeader);
#ifdef WRITE_ICO_TO_FILE
                file.Write(&dir, sizeof(dir));
#endif
                buff.insert(buff.end(), reinterpret_cast<const char *>(&dir), reinterpret_cast<const char *>(&dir) + sizeof(dir));

                // Write DIB header (including color table):
                int nBitsSize = pBmInfo->bmiHeader.biSizeImage;
                pBmInfo->bmiHeader.biHeight *= 2; // because the header is for both image and mask
                pBmInfo->bmiHeader.biCompression = 0;
                pBmInfo->bmiHeader.biSizeImage += pMaskInfo->bmiHeader.biSizeImage; // because the header is for both image and mask
#ifdef WRITE_ICO_TO_FILE
                file.Write(&pBmInfo->bmiHeader, nBmInfoSize);
#endif
                buff.insert(buff.end(), reinterpret_cast<const char *>(&pBmInfo->bmiHeader), reinterpret_cast<const char *>(&pBmInfo->bmiHeader) + nBmInfoSize);

                // Write image data:
#ifdef WRITE_ICO_TO_FILE
                file.Write((UCHAR*)bits, nBitsSize);
#endif
                buff.insert(buff.end(), reinterpret_cast<const char *>(bits.data()), reinterpret_cast<const char *>(bits.data()) + nBitsSize);

                // Write mask data:
#ifdef WRITE_ICO_TO_FILE
                file.Write((UCHAR*)maskBits, pMaskInfo->bmiHeader.biSizeImage);
#endif
                buff.insert(buff.end(), reinterpret_cast<const char *>(maskBits.data()), reinterpret_cast<const char *>(maskBits.data()) + pMaskInfo->bmiHeader.biSizeImage);

#ifdef WRITE_ICO_TO_FILE
                file.Close();
#endif

                DeleteObject(iconInfo.hbmColor);
                DeleteObject(iconInfo.hbmMask);

                DeleteDC(dc);

                return true;
            }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM