Windows Picture Button Control II
Philip J. Erdelsky, http://www.alumni.caltech.edu/~pje, pje@acm.org
Turbo C/C++ 4.5 for Windows, Borland C++ Builder for Windows 95
Windows 3.1, Windows 95
Other Windows C++ compilers, with slight changes
Public domain, no restrictions on use
May 1, 1997
windows, control, button
A windows custom control for a button with a bitmap picture on it. The focus rectangle is drawn around the picture. C++ source code only; no VBX file.
Source code:

(Version I was written only for 16-bit applications; version II supports both 16-bit and 32-bit applications.)

The standard Windows button control shows only text. With the BS_OWNERDRAW style, you can put a picture on it, but the required procedures are rather complicated.

The "PICTUREBUTTON" control lets you display two bitmaps on a button -- one when the button is enabled and the other when the bitmap is disabled. Just supply two bitmaps, and the control does the necessary drawing.

A "PICTUREBUTTON" control can be put into a dialog box by including a line of the following form in the appropriate place in the resource (.RC) file:

     CONTROL bitmap_name, control_id, "PICTUREBUTTON",
       WS_CHILD | WS_VISIBLE | WS_TABSTOP, x, y, width, height

The bitmap is specified by name, which must be enclosed in quotation marks. The bitmap should be included in the same resource (.RC) file. The file PBUTTEST.RC contains several examples. The bitmap name must not be more than 31 characters long.

The specified bitmap is used when the button is enabled. The name of the bitmap to be used when the button is disabled is obtained by appending the letter "X" to the specified bitmap name.

If either bitmap cannot be found, the control simply leaves its top blank when the unknown bitmap is to be displayed.

You may adjust the size of the button, but the bitmap will not be stretched or compressed to fit. It will simply be centered. If the bitmap is too large to fit onto the button top, it will spill over onto the bottom and right edges, and parts of it may be trimmed. The result is usually a workable but aesthetically displeasing button.

To put a "PICTUREBUTTON" control into a dialog box with the Borland Resource Workshop, select a custom control, enter the class name "PICTUREBUTTON" instead of choosing one of the predefined classes, and enter the name of the bitmap as the caption. Then edit the resulting .RC file as text and replace "BorCheck" with "PICTUREBUTTON" if necessary. The Resource Workshop can also be used to create and edit the bitmap.

The bitmap will blend into the button top if the area surrounding the picture is painted light gray, which matches the rest of the button top.

A "PICTUREBUTTON" control may also be created dynamically with an appropriate call on CreateWindow(). If you use a "PICTUREBUTTON" control on a toolbar, you may wish to omit the WS_TABSTOP style, which has meaning only for a dialog box control.

The accompanying code in PBUTTON.CPP must be compiled and linked with the application.

You may change the bitmaps dynamically by sending a somewhat nonstandard BM_SETSTYLE message:

   16-bit version:

   SendDlgItemMessage(window_handle, button_id, BM_SETSTYLE, 0,
     MAKELPARAM(enabled_bitmap_handle, disabled_bitmap_handle);

   32-bit version:

   SendDlgItemMessage(window_handle, button_id, BM_SETSTYLE,
     (WPARAM) enabled_bitmap_handle, (LPARAM) disabled_bitmap_handle);

The two bitmap handles need not be different, but they must both be valid.

The "PICTUREBUTTON" control sends a BN_CLICKED notification message to its parent when it is selected. Other notification messages are not supported.

The parent may enable, disable, show or hide a "PICTUREBUTTON" control in the same manner as a standard Windows button control.

The bitmap on a button control is often insufficient to identify its purpose. Therefore, you may cause a "PICTUREBUTTON" to display specified text in a status bar by sending it a nonstandard BM_SETSTATE message: SendDlgItemMessage(window_handle, control_id, BM_SETSTATE, (WPARAM) GetDlgItem(window_handle, status_bar_id), (LPARAM) (char far *) text);

The status bar should be a STATIC control and a sibling of the "PICTUREBUTTON" control. The "PICTUREBUTTON" control will then display the specified text in the specified status bar when it captures the mouse. That is, the text will appear in the status bar when you move the cursor over the button and depress the left mouse button, and will disappear when you release the left mouse button.

The files PBUTTEST.CPP and PBUTTEST.RC contain a simple test program that uses five "PICTUREBUTTON" controls of various sizes. Clicking the rightmost button enables or disables the button next to it. Clicking the leftmost button closes the window and terminates the test program. Clicking the button next to it causes the bitmap on the leftmost button to cycle through all available OBM bitmaps. The center button lacks the WS_TABSTOP property, but it is otherwise normal.

The test program can be compiled as a 16-bit application with Turbo C/C++ 4.5 for Windows 3.1, or as a 32-bit application with Borland C++ Builder for Windows, provided the identifier WIN32 is defined.

It is fairly difficult to compile applications as simple as this test program with Borland C++ Builder for Windows. To prevent the automatic inclusion of irrelevant material, the compiler has to be called up by command lines executed in a DOS window, perhaps as follows:

REM Compile and Link Picture Button Test Application
BCC32 -DWIN32 -I%BDIR%\INCLUDE -L%BDIR%\LIB -W pbuttest.cpp pbutton.cpp
BRC32 -32 pbuttest