Jun 152011

Here is a handy function I use to convert an icon to a HBITMAP. It’s not something you need to do very often, but very useful on the odd time when you need this functionality.

HBITMAP CMyDialog::ConvertIconToBitmap(HICON hIcon, int nWidth, int nHeight, COLORREF clrBackground)
{
    if(hIcon == NULL)
        return NULL;   

    HDC hDC = NULL;
    HDC hMemDC = NULL;
    HBITMAP hBitmap = NULL;
    HBITMAP hOldBitmap = NULL;
    HBRUSH hBrush = NULL;
    HBRUSH hOldBrush = NULL;

    BOOL bGotBitmap = false;

    try {
        hDC = ::GetDC(NULL);
        if (hDC != NULL) {
            hBitmap = CreateCompatibleBitmap(hDC, nWidth, nHeight);
            if (hBitmap != NULL) {
                hMemDC = CreateCompatibleDC(hDC);
                if (hMemDC != NULL) {
                    // Select the bitmap into the memory device context
                    hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);

                    hBrush = CreateSolidBrush(clrBackground);
                    if (hBrush != NULL) {
                        // Fill the bitmap with the background color
                        hOldBrush = (HBRUSH)SelectObject(hMemDC, hBrush);
                        PatBlt(hMemDC, 0, 0, nWidth, nHeight, PATCOPY);

                        // Draw the icon
                        DrawIconEx(hMemDC, 0, 0, hIcon, nWidth, nHeight, 0, NULL, DI_NORMAL);
                        bGotBitmap = true;
                    }
                }
            }
        }

        // Cleanup
        if (hOldBrush != NULL)
            SelectObject(hMemDC, hOldBrush);
        if (hOldBitmap != NULL)
            SelectObject(hMemDC, hOldBitmap);
        if (hBrush != NULL)
            DeleteObject(hBrush);
        if (hMemDC != NULL)
            DeleteDC(hMemDC);
        if (hDC != NULL)
            ::ReleaseDC(NULL, hDC);

        if (!bGotBitmap && hBitmap != NULL) {
            DeleteObject(hBitmap);
            hBitmap = NULL;
        }
    }
    catch(...) {
    }
    return hBitmap;
}

To use this function simply pass in an icon.

HICON hIcon = ::LoadIcon(NULL, IDI_ERROR);
if(hIcon != NULL) {
    hBmp = ConvertIconToBitmap(hIcon, 48, 48, RGB(255,255,255));
    if(hBmp != NULL) {
        CBitmap *cBmp = CBitmap::FromHandle(hBmp);
        // Do whatever you need with the CBitmap
        // ...
        // Remember to clean up the hBmp
        DeleteObject(hBmp);
        // Note: in this case you don't have to destroy the icon since it's a system icon
    }
}

An example of a use for this function is converting an icon returned from a call to SHGetFileInfo to retrieve an icon for a file.

SHFILEINFO sfi;
SHGetFileInfo(
        (LPCTSTR)strFileName,
        FILE_ATTRIBUTE_NORMAL,
        &sfi,
        sizeof(SHFILEINFO),
        SHGFI_ICON | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES);
}

HBITMAP hBmp = ConvertIconToBitmap(sfi.hIcon, 48, 48, RGB(255,255,255));

Then you could use that bitmap to add to a CImageList just as if it were a bitmap you’d read from a file or resource:

if(hBmp != NULL) {
    CBitmap *cBmp = CBitmap::FromHandle(hBmp);
    if(cBmp != NULL)
        m_imageList.Replace(0,cBmp,NULL);
}

Leave a Reply

(required)

(required)