Search code examples
c++winapilistitemwin32guicollapsable

Win32 (C++) :- How to make a list item collapsible


I have a listbox in which multiple list items are there. I want to implement something like if we click on the list item, it will collapse and show the summary of the clicked item:

enter image description here

I have been searching this on the web for quite sometime but haven't got any good solution. I am very new to Win32. Any suggestions on how to approach this like which control should I use. Any help will be appreciated.


Solution

  • Standard ListBox and ListView controls do not natively support expanding/collapsing items, however it is possible to implement it in a ListBox with some extra work.

    Give the ListBox the LBS_OWNERDRAWVARIABLE list box style to allow the list to contain items of different heights. When a new item is added to the list, the ListBox will send a WM_MEASUREITEM message to its parent window asking for the item's initial height. Return an appropriate height based on whether the item should be displayed as collapsed or expanded.

    Once an item has been added to the list, you can send the ListBox a LB_SETITEMHEIGHT message to assign a new height for that item based on whether it should now be displayed collapsed or expanded. Then invalidate the ListBox to trigger a repaint of the items.

    The LBS_OWNERDRAW... styles require you to manually draw each list item whenever the ListBox sends a WM_DRAWITEM message to its parent window. You can draw the requested item on the provided HDC however you want, such as with the DrawText() function, configuring its parameters based on whether the item's text is currently being displayed as collapsed or expanded. Also use the state information provided by the message itself to configure the HDC's font and background/foreground colors as desired (particularly important when rendering items in the selected and focused states).

    With that in place, all you have left to do is make your click handler determine the index of the item being clicked on (via GetMessagePos(), ScreenToClient(), and LB_ITEMFROMPOINT), and then assign it a new height based on its new expanded/collapsed state, and let the resulting repaint draw the new text accordingly.