spacer spacer spacer spacer spacer spacer spacer spacer
Luigi Bianchi Web Site spacer
spacer Home Software Programming Others About spacer spacer
spacer spacer
spacer spacer

(Un)Common Controls

separator images

Uncommon controls are Windows controls that are used in an uncommon way to solve problems that are not those for which they were created. Did you know, for example, that a ListView could be used as an Image control that can display JPEG, PNG and GIF format too?
Here there are some of them that Iíd like to share with you. But please, do the same: if you have a cool Uncommon Control, send it to me, and if it fits in this section, Iíll publish it with your name and your description.

A Short History

Many years ago, in the Windows 3.0 age, I remember a guy that, because there was no direct support for images in Dialog Boxes but there was for icons, proposed to divide images into 16*16 pixels icons and then align them in order to reconstruct the original image. This is what I call an Uncommon Control, and this was the first one that I encountered in my programmer life.
I increased my interests in Uncommon Controls when I was developing the Dfm2API utility. For those who still does not know what this utility is for, this is a tool that converts Borland Delphi and C++ Builder VCL Forms into a Resource Script file (.RC) and a .CPP and .HPP file with a lot of code automatically generated to replicate original VCL behavior, such as control initialization, etcÖ. The major difficulties in achieving a satisfactory result, were that there are a lot of commonly used VCL controls that are not easily available in plain API programming because they are not directly supported by the OS. For example, the so widely used TGlyphButton (that is a button with a text) has no direct Windows support. Or maybe it has?
There are many reasons to use Uncommon Controls:

1) Impossibility to use a control under certain circumstances: as mentioned above, GlyphButtons are not directly supported by OS, so it seems quite difficult to use them, unless you donít write all the required code.

2) Necessity to reduce code size: why should I use a DLL if it is not *REALLY* necessary? Why should I write some code if it is already available? In the example mentioned above, why use an Image Control or link an Image Library just to display a JPEG file?

3) To reduce the needs for external (and maybe expensive) packages:< and this seems to be self-explanatoryÖ

4) To reduce the effort of upgrading the software and the risk of incompatibilities between different libraries: if you use a standard component, you donít need to upgrade anything, at least until the OS will support that component. Moreover, you have released a program that requires VCL 4.0 and a plug-in that requires VCL 5.0. Are you sure that no problems will arise?

5) To demonstrate your skill and lateral thinking capabilities... ;-)

It is also my desire to publish them on a Journal when there is enough material, and with the consent (and acknowledgments) of those of you that will contribute to this page.

Language Independent Simple Data Transfer Mechanism


Sometimes, you need to transfer simple data types from an Executable written in a language to a DLL written in another one. For example you can have a list of strings that need to be transferred from a Visual Basic EXE to a Delphi DLL.


You can use invisible Windows controls to store data and then "send" the handle of that control instead of the whole structure: in the example above you can use an invisible ListBox, fill it from the VB side and call the DLL by simply giving the ListBox handle. You can then do whatever you want to that List of Strings (see also the "Language Independent String List With Sorting Capabilities, and a Little "bit" More" topic).


You can use this trick in whatever language you want, and for every structure and datatype supported by Windows. This includes strings, stringlists, numbers, datetimes, currencies, etc... Did you think you needed OLE to do this?

28 October 2000,
Luigi Bianchi

Glyph Button 2


Windows does not seem to have a standard control for displaying buttons with text and glyph. It is easy to have a button with text or a button with images, but not both.


The common control SysTabControl32 has the TCS_BUTTONS style, for which Tabs appear as buttons. Moreover, each Tab has an Image and a Text property that can be shown simultaneously.

Images must be handled by an ImageList control that can be initialized at runtime using bitmaps or icons.

What happens if I use a TabControl with just a tab? Here there is an example:

Uncommon button with text and glyphs

During the WM_INITDIALOG message, an ImageList is created to store the glyph, then it is bind to the TabControl, and the TCITEM structure is initialized and passed to the TabControl. Thatís all. Now we have to catch the WM_NOTIFY message to see when the Tab is pressed and then we have to bring it up again, because by default Tab Buttons stay pressed.


† {†
†††† hCtlTabControl1 = GetDlgItem(hWnd, IDC_TABCONTROL1);
†††† HIMAGELIST himlImages = ImageList_LoadImage(GetModuleHandle(NULL),
†††† TabCtrl_SetImageList(hCtlTabControl1, himlImages);
†††† TabCtrl_SetItemSize(hCtlTabControl1, 160, 68);
†††† TCITEM item;
†††† ZeroMemory(&item, sizeof(item));
†††† item.mask = TCIF_IMAGE | TCIF_TEXT;
†††† item.pszText = "Look ma, it's me!";
†††† TabCtrl_InsertItem(hCtlTabControl1, 0, &item);
†††† TabCtrl_SetCurSel(hCtlTabControl1, -1); //to bring it up again
† }
† break; //WM_INITDIALOG
† case WM_NOTIFY:
† {† LPNMHDR pnmh = (LPNMHDR) lParam;
†††† switch (pnmh->code)
†††† {† case TCN_SELCHANGE:
†††††††††† if (pnmh->idFrom == IDC_TABCONTROL1)
†††††††††† {† //do something here
††††††††††††† TabCtrl_SetCurSel(hCtlTabControl1, -1); //to bring it up again
†††††††††† }
††††††† break;
†††† }
† }
† break;


Possibility to have nicer buttons using plain API programming, with no needs for additional libraries.

OS support, requires comctl32 4.71 and above, works with all the Win32 OS family.

22 June 2000, Luigi Bianchi

Glyph Button 1


Windows does not seem to have a standard control for displaying buttons with text and glyph. It is easy to have a button with text or a button with images, but not both.


The simplest and most used method is to write the text directly into the bitmap. This however has some limitations, because it is not guaranteed that it has the standard fonts, color and appearance for that kind of control.


Really simple solution, but with some limitations

1 January 1990,


Language Independent String List With Sorting Capabilities, and a Little "bit" More


Sometimes, a list of strings is necessary to perform various operations, including sorting. If you program in C++, you can use STL list<string> with sort, while if you're using C you can use qsort. C++ Builder and Delphi programmers can use TStringList class, that is widely used by VCL.


You can also use an invisible ListBox and use the classic StringList capabilities in order to add items (LB_ADDSTRING), remove items(LB_DELETESTRING), get the list size (LB_GETCOUNT), clear the list (LB_RESETCONTENT) find an item (LB_FINDSTRING) and so on. You can also specify that the list must be sorted (through the LBS_SORT style). You can also, however, have more things, such as associate a bit value to each item: this can be done selecting and unselecting each item of a multiselect ListBox (there are many message for doing that).


You can save some bytes of code, because you just need a call to CreateWindow and some SendMessages, you can associate a boolean value to each item, you can have search for strings in the list.

28 October 2000,

Luigi Bianchi

GIF / PNG / JPEG lightweight Image Control


Windows does not seems to have a standard control for displaying JPEG, PNG and GIF images


ListView controls have the capability to display JPEG, PNG, GIF, BMP, WMF and EMF images.

To use them as simple image controls, it is sufficient to send them a message as in the following example (where hCtlListView1 is the handle of the ListView control and where szFileName is the FULL path of the image file to be displayed).

ZeroMemory(&lv, sizeof(lv));
lv.pszImage = szFileName;
//full path required
lv.cchImageMax = lstrlen(szFileName); //unnecessary?
ListView_SetBkImage(hCtlListView1, &lv);

This requires comctl32.dll 4.71 and above. Note that animated GIF are displayed as normal GIF, and only the first frame is displayed. Note also that they cannot be stretched and that the images must be loaded from external files.


No need for extra DLL; Code size minimal increase; OS support;

13 June 2000, Luigi Bianchi, but I must confess that Dino Esposito partially published this before!!!

© Copyright (2000), Luigi Bianchi
Last Update:
June 25, 2002