0

I have an application with property sheet in outlook_bar style which I am using as a main dialog. I have created the property sheet with 3 pages on it. I have created 6 bitmaps each dimension(82,82) for displaying on the tabs.At a time 3 of the bitmaps will be used by the property sheet.

Whenever a user navigates to a new tab I would like to change the bitmap displayed on the selected tab. I have written a function ChangeImgList(int selno) below to do this.

The function is called from the OnSetActive function of the respective property pages.When I run the code I get an "Encountered an improper argument error" at the line SetIconsList(m_shtSelImages.m_hImageList).

I get this error when the second time this function is called.

The function is as below:

void AppPropSheet::ChangeImgList(int sel)
{
//m_shtSelImages is of type CImageList and m_bmpimgs[3] is an array of CBitmap
//both are members of AppPropSheet class
    
    static bool firsttime = true;
    int retval;

    if(!firsttime)
    for(int i=0;i<3;i++)
        m_bmpimgs[i].~CBitmap();


    if (sel == 0)
        m_bmpimgs[0].LoadBitmapA(IDB_BITMAP86);
    else
        m_bmpimgs[0].LoadBitmapA(IDB_BITMAP77);

    if (sel == 1)
        m_bmpimgs[1].LoadBitmapA(IDB_BITMAP87);
    else
        m_bmpimgs[1].LoadBitmapA(IDB_BITMAP81);

    if (sel == 2)
        m_bmpimgs[2].LoadBitmapA(IDB_BITMAP88);
    else
        m_bmpimgs[2].LoadBitmapA(IDB_BITMAP79);
    

    if (!firsttime)
        m_shtSelImages.DeleteImageList();

    retval = m_shtSelImages.Create(81, 81, ILC_COLOR24|ILC_MASK , 1, 1);

    retval = m_shtSelImages.Add(&m_bmpimgs[0], RGB(128, 128, 128));
    retval = m_shtSelImages.Add(&m_bmpimgs[1], RGB(128, 128, 128));
    retval = m_shtSelImages.Add(&m_bmpimgs[2], RGB(128, 128, 128));

    //SetIconsList(m_shtSelImages.m_hImageList);
    
    firsttime = false;
    
}
//end of function

In the debugger I found the following : It asserts in the SetIconsList function at line ENSURE(m_Icons.GetSafeHandle()==NULL) in afxpropertysheet.cpp

Apparently the way I am trying to change the bitmap is not provided by the framework.Looking forward to your suggestions.

  • Not sure it's the cause of your problem, but what are your hoping to achieve with `bmpimgs[i].~CBitmap();` and `m_shtSelImages.~CImageList();`? – Adrian Mole Oct 18 '21 at 14:31
  • Or maybe it **is** the problem. You're calling the objects' destructor (which would imply those objects are destroyed) and then, straight after, you're using those objects, in lines like `bmpimgs[0].LoadBitmapA(IDB_BITMAP86);`. ??? – Adrian Mole Oct 18 '21 at 14:37
  • ~CBitmap() is called to destroy the existing bitmap totally before reloading a new bitmap with LoadBitmap function. CImageList has a DeleteImageList but I also found the detach and attach functions so not sure which function(s) to use. – ramesh_deekonda Oct 18 '21 at 14:41
  • Let me try to change the code and see if that is the problem. – ramesh_deekonda Oct 18 '21 at 14:42
  • Possibly useful reading: [calling destructor explicitly](https://stackoverflow.com/q/16720201/10871073) – Adrian Mole Oct 18 '21 at 14:51
  • I used CBitmap::DeleteObject(), changed the ImageList object and removed the line SetIconsList(looks like it should be called only once). I am not still not getting the changed bitmaps. – ramesh_deekonda Oct 18 '21 at 14:58
  • @Adrian Mole Interesting reading about calling destructor explicitly. In my opinion member variables of an object are not really destroyed as long as the object is itself Alive in memory.It depends on what is written in the objects destructor. That's what determines whether to call it or not. – ramesh_deekonda Oct 18 '21 at 15:09
  • Also replaced ~CImageList with call to DeleteImageList but it's still not working.Found a CImageList Replace function. working on it. – ramesh_deekonda Oct 18 '21 at 15:16
  • Try adding a call to `RedrawWindow()`? – Adrian Mole Oct 18 '21 at 15:17
  • Found a function CImageList::Replace() that is used to replace a bitmap in the ImageList. Added a call to GetTabControl()->Invalidate() and also RedrawWindow(). Please note I have removed the call to SetIconsList. Still not able to switch the bitmaps. Last Option is to get the coordinates of the tab bitmaps. No clue how to get those coordinates. – ramesh_deekonda Oct 18 '21 at 15:24
  • 1
    *"It crashes at `ENSURE(...)`"* - That's not a crash. It is a [failed debug assertion](https://learn.microsoft.com/en-us/visualstudio/debugger/assertion-failed-dialog-box). It's telling you which conditions should be true, but isn't. Also, please format the code. As posted, it's hard to even follow through the function. – IInspectable Oct 18 '21 at 15:40
  • Sorry for the formatting. I have corrected it. Thanks to whoever corrected the mix up of code and text which I could not set right. My hunch about the assertion is that SetIconsList can be called only once. – ramesh_deekonda Oct 18 '21 at 15:51
  • @IInspectable Can we call SetIconsList more than once?. The first time is prior to a call to SetLook. How do I attach a Changed Image list with the propertysheet? since SetIconsList is failing. – ramesh_deekonda Oct 18 '21 at 16:42
  • Problem is not yet resolved. Awaiting your feedback. – ramesh_deekonda Oct 19 '21 at 06:56
  • Is my approach correct?. Is there any other ways I can change the bitmaps on the tabs? Tried a BitBlt onto the property sheet but it doesn't work because it gets painted on later by the framework. – ramesh_deekonda Oct 19 '21 at 15:49

1 Answers1

0

The following code in class derived from CMFCPropertySheet class works If there is any other way that works please let me know.

m_wndPane1.RemoveAllButtons();

retval=m_wndPane1.AddButton(m_bmpimgs[0], "Button one text", 10050, 0);
retval=m_wndPane1.AddButton(m_bmpimgs[1], "Button two text", 10051, 1);
retval=m_wndPane1.AddButton(m_bmpimgs[2], "Button three text", 10052, 2);

m_wndPane1.InvalidateButton(0);
m_wndPane1.InvalidateButton(1);
m_wndPane1.InvalidateButton(2);