Home > OS >  Rewrite CListBox as a CCheckListBox
Rewrite CListBox as a CCheckListBox

Time:07-13

I am working on a Windows application using MFC and Visual Studio C 17. I have multiple tabs in the application, one of which is currently implemented using CListBox and needs to be reimplemented using CCheckListBox. CCheckListBox is a child class of CListBox.

I have a vector of unique CString's I want to display in the box. To start simple, I tried making the tab with CListBox and by using CListBox::AddString(), this worked exactly as I wanted it to. It sorted the strings alphabetically, and automatically added a scroll bar on the side when the vector had too many CString's to display all at once in the list.

However, when swapping the CListBox variable to a CCheckListBox variable, I have come across the error when I press run along the lines of:

Debug Assertion Failed! ..... \mfc\winctrl3.cpp Line: 588

I found this GitHub link that has the winctrl3.cpp file and on line 588, there is a function called OnLButtonDblClk which is somewhat explained here.

The trouble is I am unsure of how to swap a variable from a parent class to a child class. Is it so different for Windows classes? In the courses and programs I have taken and written in the past, switching from a parent to child variable was straightforward but this is quite the opposite !

Any help is appreciated, thank you in advance ! :D

CodePudding user response:

There is no assertion in line 588 of the source file in your link. That github upload dates back to 2014. Why not search the winctrl3.cpp source file in your own Visual Studio installation instead? In my own installation, it is in function PreSubclassWindow() and there is indeed an assertion there:

    // CCheckListBoxes must be owner drawn
    ASSERT(GetStyle() & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE));

That is the CCheckListBox must be owner-drawn. Find the CCheckListBox constructor code above, you will notice that it calls the CListBox (parent-class) constructor, applying either of the two owner-drawn styles. Instead, the CListBox constructor calls CWnd::Create() with the "LISTBOX" Windows Class-Name as a parameter. That is, it seems to be a MFC-implemented control, overriding the CListBox class, with an owner-drawn style. There is no mention of a native "Check-ListBox" class or style in the Win32 documentation either. Also the CCheckListBox documentation (in the link you posted) clearly states: CCheckListBox is only for owner-drawn controls because the list contains more than text strings.

Therefore:

  • If you are creating the control using a resource script, add an owner-drawn style (eg LBS_OWNERDRAWFIXED) to the control (or set the Owner-Drawn property in the property editor).
  • If you are creating the control programmatically make sure you are calling the CCheckListBox constructor, not the CListBox one.

Not sure what you mean about the scroll-bar (and why you mention it), doesn't the list-box display a scroll-bar automatically (WS_VSCROLL style - or property), do you have to do something on your own?


EDIT:

Forgot to mention, if you are creating the control using a resource script use the Class Wizard to add a member variable (of "Control" type, not "Value") to the dialog class. The new variable must be of type CCheckListBox (MFC class). This will subclass the control. If the old project already had a CListBox member variable change it to CCheckListBox.

  • Related