The+extended+combobox

//by Richard Russell, January 2007//

Ordinary comboboxes can be created using the routines provided in the [|WINLIB2] (for use in a dialogue box) and [|WINLIB5] (for use on the main output window) libraries. However there is a different kind, the **extended combobox**, which allows for the inclusion of a **bitmap image** as well as a text string in each of the selections:



This article explains how to incorporate extended comboboxes in your BBC BASIC programs.

Initialisation
To start off with we need to include this initialisation code:

code format="bb4w" DIM icex{dwSize%, dwICC%} ICC_USEREX_CLASSES = &200 icex.dwSize% = DIM(icex{}) icex.dwICC% = ICC_USEREX_CLASSES SYS "InitCommonControlsEx", icex{} code

Image lists
The set of images to be used in the extended combobox must be supplied as an //image list//. The first step is to create an empty image list as follows:

code format="bb4w" dx% = 16 dy% = 16 maximages% = 8 SYS "ImageList_Create", dx%, dy%, 0, maximages%, 0 TO himglist% IF himglist% = 0 ERROR 100, "Couldn't create image list" code Here **dx%** and **dy%** are the width and height, respectively, of each image in pixels and **maximages%** is the maximum number of images that the image list will ever need to hold.

The next step is to //populate// the image list with images. You can do that either from a set of individual bitmaps or from one or more image //strips// (or a mixture of the two). An image strip is a bitmap containing several identical-sized images side-by-side.

For the purposes of this example I will use the bitmap file **WIDGETS.BMP** supplied with BBC BASIC for Windows; this contains five 24x24 images in a strip 120 pixels wide by 24 pixels high. Since these images are a little on the large size for use in a combobox the bitmap can be resized when it is loaded, thus:

code format="bb4w" nimages% = 5 bmpfile$ = @lib$+"..\examples\windows\widgets.bmp" LR_LOADFROMFILE = 16 SYS "LoadImage", 0, bmpfile$, 0, dx%*nimages%, dy%, LR_LOADFROMFILE TO hbitmap% IF hbitmap% = 0 ERROR 100, "Couldn't load bitmap file" code Now it is straightforward to populate the first five images in the image list from the bitmap:

code format="bb4w" SYS "ImageList_Add", himglist%, hbitmap%, 0 SYS "DeleteObject", hbitmap% code More images (or strips) can be added, up to the limit specified when the image list was created, using further calls to **ImageList_Add**.

Now the image list is ready we can concentrate on creating the extended combobox itself. The process depends on whether you want to display the combobox in a dialogue box or directly on your program's main window.

Dialogue box
As usual, we must install the appropriate library for working with dialogue boxes:

code format="bb4w" INSTALL @lib$+"WINLIB2" code (alternatively install **WINLIB2A** or **WINLIB2B** if you need the facilities they provide).

Now we will create a simple dialogue box containing just a cancel button and the extended combobox:

code format="bb4w" dlg% = FN_newdialog("Extended combobox", 250, 20, 150, 140, 8, 1000) PROC_pushbutton(dlg%, "Cancel", 2, 20, 120, 56, 14, 0)

WS_VISIBLE = &10000000 WS_CHILD = &40000000 WS_VSCROLL = &200000 CBS_AUTOHSCROLL = &40 CBS_DROPDOWN = 2 cbid% = 101 PROC_dlgctrl(dlg%, "", cbid%, 20, 20, 90, 150, WS_VISIBLE OR WS_CHILD OR \      \            WS_VSCROLL OR CBS_AUTOHSCROLL OR CBS_DROPDOWN, \       \            "ComboBoxEx32") code Note that the combobox has been allocated the ID number **101**. Refer to the documentation for [|PROC_dlgitem] for the meaning of the other parameters.

The dialogue box is displayed in the usual way:

code format="bb4w" PROC_showdialog(dlg%) code We've now created the dialogue box and the extended combobox, but the combobox is still empty. The next step is to tell the combobox which image list to use:

code format="bb4w" CBEM_SETIMAGELIST = &402 SYS "SendDlgItemMessage", !dlg%, cbid%, CBEM_SETIMAGELIST, 0, himglist% code Note the use of the combobox's ID number **cbid%**.

To add items to the combobox we first have to declare some constants and a data structure:

code format="bb4w" CBEIF_TEXT = 1 CBEIF_IMAGE = 2 CBEIF_SELECTEDIMAGE = 4 CBEM_INSERTITEMA = &401 DIM cbxi{mask%, iItem%, pszText%, cchTextMax%, iImage%, iSelectedImage%, \ \       iOverlay%, iIndent%, lParam} code Now we can define each item as follows:

code format="bb4w" text$ = "Combobox item"+CHR$0 cbxi.mask% = CBEIF_TEXT OR CBEIF_IMAGE OR CBEIF_SELECTEDIMAGE cbxi.iItem% = itemno% cbxi.pszText% = !^text$ cbxi.iImage% = imageno% cbxi.iSelectedImage% = imageno% SYS "SendDlgItemMessage", !dlg%, cbid%, CBEM_INSERTITEMA, 0, cbxi{} code Here **itemno%** is the item to define (starting at zero for the first item), **imageno%** is the image to display alongside the text (zero for the first image in the image list) and **text$** is the text for this item. Note particularly the **CHR$0** termination for the text string. You can set **itemno%** to the special value **-1**, which adds it at the end of the list.

Note that is possible to use a different image for the currently selected item from that shown against the item in the drop-down list. If it's not convenient to define the text and image(s) at the same time, you can set the value of **cbxi.mask%** according to which you want to set.

To test which item in the extended combobox is selected you can use exactly the same code as for a regular combobox:

code format="bb4w" CB_GETCURSEL = &147 SYS "SendDlgItemMessage", !dlg%, cbid%, CB_GETCURSEL, 0, 0 TO selected% code

Main output window
The process for creating an extended combobox on the main output window is very similar to that for creating one in a dialogue box. As usual, we must install the appropriate library for working with boxes and buttons:

code format="bb4w" INSTALL @lib$+"WINLIB5" code (alternatively install **WINLIB5A**, and remember to pass the parent window handle **@hwnd%** as the first parameter of **FN_createwindow**).

The extended combobox is created as follows:

code format="bb4w" WS_VSCROLL = &200000 CBS_AUTOHSCROLL = &40 CBS_DROPDOWN = 2 hcbex% = FN_createwindow("ComboBoxEx32", "", 200, 50, 140, 200, 0, \      \        WS_VSCROLL OR CBS_AUTOHSCROLL OR CBS_DROPDOWN, 0) code Refer to the documentation for [|FN_createwindow] for the meaning of the parameters.

The next step is to tell the combobox which image list to use:

code format="bb4w" CBEM_SETIMAGELIST = &402 SYS "SendMessage", hcbex%, CBEM_SETIMAGELIST, 0, himglist% code Note the use of the combobox's window handle **hcbex%**.

We declare some constants and a data structure exactly as before:

code format="bb4w" CBEIF_TEXT = 1 CBEIF_IMAGE = 2 CBEIF_SELECTEDIMAGE = 4 CBEM_INSERTITEMA = &401 DIM cbxi{mask%, iItem%, pszText%, cchTextMax%, iImage%, iSelectedImage%, \ \       iOverlay%, iIndent%, lParam} code Now we can define each item as follows:

code format="bb4w" text$ = "Combobox item"+CHR$0 cbxi.mask% = CBEIF_TEXT OR CBEIF_IMAGE OR CBEIF_SELECTEDIMAGE cbxi.iItem% = itemno% cbxi.pszText% = !^text$ cbxi.iImage% = imageno% cbxi.iSelectedImage% = imageno% SYS "SendMessage", hcbex%, CBEM_INSERTITEMA, 0, cbxi{} TO res% code Here **itemno%** is the item to define (starting at zero for the first item), **imageno%** is the image to display alongside the text (zero for the first image in the image list) and **text$** is the text for this item. Note particularly the **CHR$0** termination for the text string. You can set **itemno%** to the special value **-1**, which adds it at the end of the list.

Note that is possible to use a different image for the currently selected item from that shown against the item in the drop-down list. If it's not convenient to define the text and image(s) at the same time, you can set the value of **cbxi.mask%** according to which you want to set.

To test which item in the extended combobox is selected you can use exactly the same code as for a regular combobox:

code format="bb4w" CB_GETCURSEL = &147 SYS "SendMessage", hcbex%, CB_GETCURSEL, 0, 0 TO selected% code