User Tools

Site Tools


scrollable_20list_20boxes

Scrollable list boxes

by Richard Russell, June 2010

There are three main ways in which a scroll bar may be used with a list box:

  1. If the number of items is greater than will fit in the height of the list box, a vertical scroll bar is automatically added. This is the default behaviour.
  2. If the number of items is greater than will fit in the height of the list box, and both the WS_HSCROLL and LBS_MULTICOLUMN style bits are set, a horizontal scroll bar is added. The items can then be scrolled through horizontally.
  3. If the longest item will not fit across the width of the list box, it is possible to arrange for a horizontal scroll bar to be added. However, this requires extra code (see below).


Items 1 and 2 are covered in the main Help documentation. Although the use of the WS_HSCROLL and LBS_MULTICOLUMN style bits is described only in the section covering list boxes in a dialogue box, it is equally applicable to a listbox created on the main output window.

Item 3 is considerably more complicated to achieve, partly for the reasons outlined in this Microsoft article. To make it easier, the code listed below provides two procedures: PROC_addstring and PROC_delstring; if these are called instead of sending the LB_ADDSTRING and LB_DELETESTRING messages to the list box, the horizontal scroll bar will be controlled automatically.

In order to enable a horizontal scroll bar, it is necessary to set the WS_HSCROLL style bit (&100000). When creating the list box in a dialogue box this value should be included in the final parameter of PROC_listbox, for example:

        WS_HSCROLL = &100000
        PROC_listbox(dlg%, "", id%, x%, y%, cx%, cy%, WS_HSCROLL)

Similarly, when creating the list box on the output window include the value in the final parameter of FN_listbox, as follows:

        WS_HSCROLL = &100000
        hlb% = FN_listbox("", x%, y%, cx%, cy%, id%, WS_HSCROLL)

The WS_HSCROLL style may be combined with any others required, but the code listed here is not compatible with the LBS_USETABSTOPS or LBS_MULTICOLUMN styles.

Once created (and, in the case of a dialogue box, displayed) the listbox may be populated with string items. Instead of sending the usual LB_ADDSTRING message, call the PROC_addstring routine, which enables correct behaviour of the horizontal scroll bar. In the case of a dialogue box it is first necessary to discover the handle of the list box as follows:

        SYS "GetDlgItem", !dlg%, id% TO hlb%

Where dlg% is the value returned from FN_newdialog and id% is the ID number of the list box. In the case of a list box on the main output window, the handle is returned from FN_listbox as shown above.

In either case, to populate the listbox use code similar to the following:

        PROC_addstring(hlb%, text1$)
        PROC_addstring(hlb%, text2$)
        REM etc.

You can, of course, add the items within a loop if more convenient.

To delete an item from a list box, call the PROC_delstring routine instead of sending the LB_DELETESTRING message:

        PROC_delstring(hlb%, index%)

where index% is the index number (starting at zero) of the item you wish to delete. If that item was longer than the others, the horizontal scroll bar will be adjusted (or removed) accordingly. Note that, by default, the items in a list box created using PROC_listbox are sorted into alphabetical order; therefore the index numbers of the items typically won't correspond to the order in which they were added. If necessary use the LB_FINDSTRING or LB_FINDSTRINGEXACT message to discover a string's index.

To empty the listbox of all its contents, call the PROC_resetlb routine below.

Finally, here are the routines which control the horizontal scroll bar:

        DEF PROC_addstring(hlb%, text$)
        LOCAL E%, I%, max%, nitems%
        LB_ADDSTRING = &180
        LB_GETCOUNT = &18B
        LB_GETITEMDATA = &199
        LB_SETHORIZONTALEXTENT = &194
        LB_SETITEMDATA = &19A
        SYS "SendMessage", hlb%, LB_GETCOUNT, 0, 0 TO nitems%
        IF nitems% THEN
          FOR I% = 0 TO nitems%-1
            SYS "SendMessage", hlb%, LB_GETITEMDATA, I%, 0 TO E%
            IF E%>max% THEN max% = E%
          NEXT
        ENDIF
        E% = FN_hextent(hlb%, text$+" ")
        IF E%>max% SYS "SendMessage", hlb%, LB_SETHORIZONTALEXTENT, E%, 0
        SYS "SendMessage", hlb%, LB_ADDSTRING, 0, text$ TO I%
        SYS "SendMessage", hlb%, LB_SETITEMDATA, I%, E%
        ENDPROC
 
        DEF PROC_delstring(hlb%, index%)
        LOCAL E%, I%, max%, nitems%
        LB_DELETESTRING = &182
        LB_GETCOUNT = &18B
        LB_GETITEMDATA = &199
        LB_SETHORIZONTALEXTENT = &194
        SB_TOP = 6
        WM_HSCROLL = &114
        SYS "SendMessage", hlb%, LB_GETCOUNT, 0, 0 TO nitems%
        IF nitems% THEN
          FOR I% = 0 TO nitems%-1
            SYS "SendMessage", hlb%, LB_GETITEMDATA, I%, 0 TO E%
            IF E%>max% IF I%<>index% THEN max% = E%
          NEXT
        ENDIF
        SYS "SendMessage", hlb%, WM_HSCROLL, SB_TOP, 0
        SYS "SendMessage", hlb%, LB_SETHORIZONTALEXTENT, max%, 0
        SYS "SendMessage", hlb%, LB_DELETESTRING, index%, 0
        ENDPROC
 
        DEF PROC_resetlb(hlb%)
        LB_DELETESTRING = &182
        LB_RESETCONTENT = &184
        LB_SETHORIZONTALEXTENT = &194
        SB_TOP = 6
        WM_HSCROLL = &114
        SYS "SendMessage", hlb%, WM_HSCROLL, SB_TOP, 0
        SYS "SendMessage", hlb%, LB_SETHORIZONTALEXTENT, 0, 0
        SYS "SendMessage", hlb%, LB_DELETESTRING, 0, 0
        SYS "SendMessage", hlb%, LB_RESETCONTENT, 0, 0
        ENDPROC
 
        DEF FN_hextent(hwnd%, text$)
        LOCAL hdc%, hfnew%, hfold%, size{}
        DIM size{x%,y%}
        WM_GETFONT = &31
        SYS "GetDC", hwnd% TO hdc%
        SYS "SendMessage", hwnd%, WM_GETFONT, 0, 0 TO hfnew%
        SYS "SelectObject", hdc%, hfnew% TO hfold%
        SYS "GetTextExtentPoint32", hdc%, text$, LEN(text$), size{}
        SYS "SelectObject", hdc%, hfold%
        SYS "ReleaseDC", hwnd%, hdc%
        = size.x%

Note that, for convenience, this code uses the 'user data' associated with each list box item to contain the length of the item in pixels. Therefore the 'user data' facility is not available for other purposes in your program.

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
scrollable_20list_20boxes.txt · Last modified: 2024/01/05 00:21 by 127.0.0.1