Owner-drawing: ListBox with variable item height

Helpful script writing tricks and HowTo's
just me
Posts: 5151
Joined: 02 Oct 2013, 08:51
Location: Germany

Owner-drawing: ListBox with variable item height

24 Oct 2013, 11:49

I'm not sure if this may be called a tutorial or demo, because my limited English might prevent me from explaining things detailed enough, but now it's here though.

Well, but how to do it?

Of course we have to set the LBS_OWNERDRAWVARIABLE (0x0020) and LBS_HASSTRINGS (0x0040) styles, and then?

MSDN wrote:
  • The owner of an owner-drawn list box can process a WM_MEASUREITEM message to specify the dimensions of list items.
  • The owner of an owner-drawn list box must process the WM_DRAWITEM message.

Just two messages, seems easy.

Actually it isn't as difficult as it seems on the first look. In contrast to list boxes with the LBS_OWNERDRAWFIX (0x0010) style, WM_MEASUREITEM is called once for each item, and the font of the control and the text of the items are already assigned. You can even send a LB_GETITEMRECT message to get width of the item. So the height can be determined 'easily' using the DRAWTEXT() function with the DT_WORDBREAK and DT_CALCRECT flags.
When WM_MEASUREITEM is sent the first time, the control cannot know, whether it has to show a vertical scroll bar. To ensure that all items are calculated using the same width, set the LBS_DISABLENOSCROLL (0x1000) and WS_VSCROLL (0x200000) styles to make the vertical scroll bar permanently visible, if it might/will be shown.

If WM_MEASUREITEM has been processed successfully, it's also 'easy' to draw the text. You can retrieve the assigned text sendingLB_GETTEXTLEN and LB_GETTEXT messages. The DRAWITEMSTRUCT contains the item's rectangle. So DRAWTEXT() with DT_WORDBREAK will do the job.
Some additional work is needed to draw the selected items, but it's feasible. That's it!

The following example does the whole job. It contains four LBODVAR_ functions. The purpose of LBODVAR_MeasureItem() and LBODVAR_DrawItem() should be clear. LBODVAR_Init() activates the message handling of WM_MEASUREITEM and WM_DRAWITEM at load-time. LBODVAR_GetHeightByRows() can by used to determing the control's height appropriate to the passed number of items like the r option of Gui, Add, ....

Code: [Select all] [Expand] [Download] (LBODVAR_demo.ahk)GeSHi © Codebox Plus

Return to “Tutorials”

Who is online

Users browsing this forum: No registered users and 5 guests