0
votes

I have a MFC Dialog based application. I have placed a Picture Control (of type Bitmap) to display an initial/default resource bitmap. That displays just fine when the app starts.

When a user selects an item in a CListbox, I want to change the bitmap resource displayed. A CStatic control variable m_Bitmap was created and I change it based on the users' listbox selection. Then I update the controls.

Upon execution, the original bitmap simply disappears and the control fails to display the new bitmap. I have used the same technique with static text control variables and CStrings and it works fine.

Why are my bitmaps failing to change? Tried calling the picture controls' RedrawWindow() function with a CWnd pointer which does nothing either.

This should be an easy thing to do in MFC...

//Code Snippet
//
//Picture Control (IDC_BitmapCntl), control variable is m_Bitmap
//  DDX_Control(pDX, IDC_BitmapCntl, m_Bitmap);
//
//Code from CList Control, OnLbnSelchange() function, CListbox variable is m_Selection
//

switch (m_Selection) {  //Select a coresponding bitmap to display

case (0):
    m_Bitmap.SetBitmap((HBITMAP)IDB_Bitmap1);
    break;

case (1):   
    m_Bitmap.SetBitmap((HBITMAP)IDB_Bitmap2);
    break;

//additional cases ommited for brevity

default:
    break;
}

UpdateData(FALSE);  //this should update the control but does not display new bitmap

//Failed attempt to then redraw control

CWnd* pDlg;
pDlg = GetDlgItem(IDC_BitmapCntl);
pDlg->RedrawWindow();  //cannot access OnPaint() via a pointer

//end snippet

No errors on compilation. Initial bitmap image displays OK but disappears when user selects an item in listbox. New bitmap is not displayed.

1
Well that works. New code added: CBitmap bm; ... ... case (0): bm.LoadBitmapW(IDB_Bitmap1); break; ... ... m_Bitmap.SetBitmap(bm); UpdateData(FALSE);Strap147
Yes, pls post as answer. Tks for pointing my problem out...Strap147

1 Answers

0
votes

Assuming that IDB_Bitmap1 and IDB_Bitmap2 are (integral) resource identifiers for the bitmaps you want (defined in an .rc or .rc2 file), then you can't just simply cast them with (HBITMAP)IDB_Bitamp1 (HBITMAP is actually a pointer, and it will then point to who-knows-what => the dreaded undefined behaviour).

You have to use the LoadBitmap() function (or something similar) to get the actual bitmap from the application's resources. The simplest way is using a (local) CBitmap object:

//...
CBitmap bitmap;
switch (m_Selection) {  //Select a coresponding bitmap to display
case 0: // Don't really need brackets around case 'values'
    bitmap.LoadBitmap(IDB_Bitmap1); // "LoadBitmap" will have "W" appended for Unicode builds
    break;                          // or "A" appended for non-Unicode ('ASCII') builds.
case 1:
    bitmap.LoadBitmap(IDB_Bitmap2); // Probably best practice to use the 'native' names?
    break;
// Additional cases ...
default: // Strictly speaking, unnecessary, but I like to put this catch-all in ...
    break; // ... and good for you, for also having it!
}
m_Bitmap.SetBitmap(bitmap.operator HBITMAP());
// Strict way to do it, but you can omit the ".operator HBITMAP()" in MOST cases.

Hope this helps!

PS: You really ought to do something (in the default case, maybe) to put a 'valid' bitmap in CBitmap for un-handled cases.