Using Owner-Drawn Buttons

The parent window of an owner-drawn button typically responds to at least three messages for the button: WM_INITDIALOG, WM_COMMAND, and WM_DRAWITEM. It is not necessary to process the WM_MEASUREITEM message for owner-drawn buttons.

When you must paint an owner-drawn button, Windows sends the parent window a WM_DRAWITEM message whose lParam points to a DRAWITEMSTRUCT structure. Use this structure with all owner-drawn controls to provide the application with the information it requires to paint the control. The itemAction and itemState members of the DRAWITEMSTRUCT structure define how to paint an owner-drawn button.

The following example shows how to process WM_INITDIALOG, WM_DRAWITEM, and WM_COMMAND messages for owner-drawn buttons. This example demonstrates how to draw one of two bitmaps for a control, depending on whether the control is selected. You would typically use the wParam parameter of the WM_DRAWITEM message to identify the control; in this example, only one control is assumed.

LRESULT APIENTRY OwnDrawProc(hDlg, message, wParam, lParam)

HWND hDlg; // window handle of dialog box

UINT message; // type of message

UINT wParam; // message-specific information

LONG lParam;

{

HDC hdcMem;

LPDRAWITEMSTRUCT lpdis;

switch (message) {

case WM_INITDIALOG:

// hinst, hbm1 and hbm2 are defined globally.

hbm1 = LoadBitmap((HANDLE) hinst, "OwnBit1");

hbm2 = LoadBitmap((HANDLE) hinst, "OwnBit2");

return TRUE;

case WM_DRAWITEM:

lpdis = (LPDRAWITEMSTRUCT) lParam;

hdcMem = CreateCompatibleDC(lpdis->hDC);

if (lpdis->itemState & ODS_SELECTED) // if selected

SelectObject(hdcMem, hbm2);

else

SelectObject(hdcMem, hbm1);

// Destination

StretchBlt(

lpdis->hDC, // destination DC

lpdis->rcItem.left, // x upper left

lpdis->rcItem.top, // y upper left

// The next two lines specify the width and

// height.

lpdis->rcItem.right - lpdis->rcItem.left,

lpdis->rcItem.bottom - lpdis->rcItem.top,

hdcMem, // source device context

0, 0, // x and y upper left

32, // source bitmap width

32, // source bitmap height

SRCCOPY); // raster operation

DeleteDC(hdcMem);

return TRUE;

case WM_COMMAND:

if (wParam == IDOK

|| wParam == IDCANCEL) {

EndDialog(hDlg, TRUE);

return TRUE;

}

if (HIWORD(wParam) == BN_CLICKED) {

switch (LOWORD(wParam)) {

case IDB_OWNERDRAW:

.

. // application-defined processing

.

break;

}

}

break;

case WM_DESTROY:

DeleteObject(hbm1); // delete bitmaps

DeleteObject(hbm2);

break;

}

return FALSE;

UNREFERENCED_PARAMETER(lParam);

}