How to create a DIB, set the bits and attach to a CImageList

284 views Asked by At

I am trying to create a Device Independent Bitmap, programatically set the pixels (as opposed to loading from a resource or from disk) and attach the DIB to a CImageList for use in a CComboBoxEx control. I believe the DIB is being created successfully and the bits are being set correctly, but the images displayed in the combo box are all black.

I create the CImageList, draw to the bitmaps and attach the list to the control here:

m_Images.Create(m_nImageWidth, m_nImageHeight, ILC_COLOR32, 0, 1);

// Draw bitmaps
size_t szIndex;
for (szIndex = 0; szIndex < m_aColourMaps.size(); ++szIndex) {
    DrawImage(szIndex);
}

// Attach image list to combo box
m_ctrlColourMapCombo.SetImageList(m_Images.GetSafeHandle());

The function that draws the bitmaps (DrawImage) is here (simplified here to just set all the pixels to red):

CDC* pDC;
pDC = GetDC();

HDC hDC;
hDC = *pDC;

HDC hDCMem;
hDCMem = CreateCompatibleDC(hDC);

BYTE* lpBitmapBits;
lpBitmapBits = nullptr;

BITMAPINFO bi;
ZeroMemory(&bi, sizeof(BITMAPINFO));

bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = m_nImageWidth;
bi.bmiHeader.biHeight = -m_nImageHeight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;

HBITMAP hBitmap = ::CreateDIBSection(hDCMem, &bi, DIB_RGB_COLORS, (LPVOID*)&lpBitmapBits, nullptr, 0);
HGDIOBJ oldbmp = ::SelectObject(hDCMem, hBitmap);

size_t szImageIndex, szIndexX, szIndexY;
float nIndex;
UINT32* pColourData;
pColourData = reinterpret_cast<UINT32*>(lpBitmapBits);
UINT32 nColour;

for (szIndexX = 0; szIndexX < m_nImageWidth; ++szIndexX) {
    szImageIndex = szIndexX;

    for (szIndexY = 0; szIndexY < m_nImageHeight; ++szIndexY) {
        pColourData[szImageIndex] = 0xff0000ff;

        szImageIndex += m_nImageWidth;
    }
}

CBitmap bitmap;
bitmap.Attach(hBitmap);
m_Images.Add(&bitmap, nullptr);
bitmap.Detach();

SelectObject(hDCMem, oldbmp);
DeleteDC(hDCMem);
DeleteObject(hBitmap);

I'm guessing the problem is somewhere in the code that attaches the DIB to a CBitmap and then inserts that into the CImageList, but I've been unable to find any sample code for doing this, though superficially the code looks reasonable to me. Unfortunately both CBitmap and CImageList are defined in afxwin.h, so its difficult / impossible to debug what's actually happening in that portion of the code, but CBitmap.Attach and CImage.Add don't return errors.

1

There are 1 answers

0
Paul Harrison On

I found the issue - the bitmap was already selected into the DC in:

HGDIOBJ oldbmp = ::SelectObject(hDCMem, hBitmap);

This prevented CImageList from adding the bitmap. On removing this (and the the corresponding SelectObject call at the end) the code works fine.