BtnWnd.cpp
//======================================================================
// BtnWnd - Button window code
//
// Written for the book Programming Windows CE
// Copyright (C) 2003 Douglas Boling
//======================================================================
#include <windows.h> // For all that Windows stuff
#include "Ctlview.h" // Program-specific stuff
extern HINSTANCE hInst;
LRESULT DrawButton (HWND hWnd, LPDRAWITEMSTRUCT pdi);
//----------------------------------------------------------------------
// Global data
//
// Message dispatch table for BtnWndWindowProc
const struct decodeUINT BtnWndMessages[] = {
WM_CREATE, DoCreateBtnWnd,
WM_CTLCOLORSTATIC, DoCtlColorBtnWnd,
WM_COMMAND, DoCommandBtnWnd,
WM_DRAWITEM, DoDrawItemBtnWnd,
};
// Structure defining the controls in the window
CTLWNDSTRUCT Btns [] = {
{TEXT ("BUTTON"), IDC_PUSHBTN, TEXT ("Button"),
10, 10, 120, 23, BS_PUSHBUTTON | BS_NOTIFY},
{TEXT ("BUTTON"), IDC_CHKBOX, TEXT ("Check box"),
10, 35, 120, 23, BS_CHECKBOX},
{TEXT ("BUTTON"), IDC_ACHKBOX, TEXT ("Auto check box"),
10, 60, 110, 23, BS_AUTOCHECKBOX},
{TEXT ("BUTTON"), IDC_A3STBOX, TEXT ("Multiline auto 3-state box"),
140, 60, 90, 52, BS_AUTO3STATE | BS_MULTILINE},
{TEXT ("BUTTON"), IDC_RADIO1, TEXT ("Auto radio button 1"),
10, 85, 120, 23, BS_AUTORADIOBUTTON},
{TEXT ("BUTTON"), IDC_RADIO2, TEXT ("Auto radio button 2"),
10, 110, 120, 23, BS_AUTORADIOBUTTON},
{TEXT ("BUTTON"), IDC_OWNRDRAW, TEXT ("OwnerDraw"),
150, 10, 44, 44, BS_PUSHBUTTON | BS_OWNERDRAW},
};
// Structure labeling the button control WM_COMMAND notifications
NOTELABELS nlBtn[] = {{TEXT ("BN_CLICKED "), 0},
{TEXT ("BN_PAINT "), 1},
{TEXT ("BN_HILITE "), 2},
{TEXT ("BN_UNHILITE"), 3},
{TEXT ("BN_DISABLE "), 4},
{TEXT ("BN_DOUBLECLICKED"), 5},
{TEXT ("BN_SETFOCUS "), 6},
{TEXT ("BN_KILLFOCUS"), 7}
};
// Handle for icon used in owner-draw icon
HICON hIcon = 0;
//----------------------------------------------------------------------
// InitBtnWnd - BtnWnd window initialization
//
int InitBtnWnd (HINSTANCE hInstance) {
WNDCLASS wc;
// Register application BtnWnd window class.
wc.style = 0; // Window style
wc.lpfnWndProc = BtnWndProc; // Callback function
wc.cbClsExtra = 0; // Extra class data
wc.cbWndExtra = 0; // Extra window data
wc.hInstance = hInstance; // Owner handle
wc.hIcon = NULL, // Application icon
wc.hCursor = LoadCursor (NULL, IDC_ARROW);// Default cursor
wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
wc.lpszMenuName = NULL; // Menu name
wc.lpszClassName = BTNWND; // Window class name
if (RegisterClass (&wc) == 0) return 1;
return 0;
}
//======================================================================
// Message handling procedures for BtnWindow
//----------------------------------------------------------------------
// BtnWndWndProc - Callback function for application window
//
LRESULT CALLBACK BtnWndProc (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
int i;
//
// Search message list to see if we need to handle this
// message. If in list, call procedure.
//
for (i = 0; i < dim(BtnWndMessages); i++) {
if (wMsg == BtnWndMessages[i].Code)
return (*BtnWndMessages[i].Fxn)(hWnd, wMsg, wParam, lParam);
}
return DefWindowProc (hWnd, wMsg, wParam, lParam);
}
//----------------------------------------------------------------------
// DoCreateBtnWnd - Process WM_CREATE message for window.
//
LRESULT DoCreateBtnWnd (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
int i;
for (i = 0; i < dim(Btns); i++) {
CreateWindow (Btns[i].szClass, Btns[i].szTitle,
Btns[i].lStyle | WS_VISIBLE | WS_CHILD,
Btns[i].x, Btns[i].y, Btns[i].cx, Btns[i].cy,
hWnd, (HMENU) Btns[i].nID, hInst, NULL);
}
hIcon = LoadIcon (hInst, TEXT ("TEXTICON"));
// We need to set the initial state of the radio buttons.
CheckRadioButton (hWnd, IDC_RADIO1, IDC_RADIO2, IDC_RADIO1);
return 0;
}
//----------------------------------------------------------------------
// DoCtlColorBtnWnd - process WM_CTLCOLORxx messages for window.
//
LRESULT DoCtlColorBtnWnd (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
return (LRESULT)GetStockObject (WHITE_BRUSH);
}
//----------------------------------------------------------------------
// DoCommandBtnWnd - Process WM_COMMAND message for window.
//
LRESULT DoCommandBtnWnd (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
TCHAR szOut[128];
int i;
// Since the Check Box button is not an auto check box, it
// must be set manually.
if ((LOWORD (wParam) == IDC_CHKBOX) &&
(HIWORD (wParam) == BN_CLICKED)) {
// Get the current state, complement, and set.
i = SendDlgItemMessage (hWnd, IDC_CHKBOX, BM_GETCHECK, 0, 0);
if (i == 0)
SendDlgItemMessage (hWnd, IDC_CHKBOX, BM_SETCHECK, 1, 0);
else
SendDlgItemMessage (hWnd, IDC_CHKBOX, BM_SETCHECK, 0, 0);
}
// Report WM_COMMAND messages to main window.
for (i = 0; i < dim(nlBtn); i++) {
if (HIWORD (wParam) == nlBtn[i].wNotification) {
lstrcpy (szOut, nlBtn[i].pszLabel);
break;
}
}
if (i == dim(nlBtn))
wsprintf (szOut, TEXT ("notification: %x"), HIWORD (wParam));
SendMessage (GetParent (hWnd), MYMSG_ADDLINE, wParam,
(LPARAM)szOut);
return 0;
}
//----------------------------------------------------------------------
// DoDrawItemBtnWnd - Process WM_DRAWITEM message for window.
//
LRESULT DoDrawItemBtnWnd (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
return DrawButton (hWnd, (LPDRAWITEMSTRUCT)lParam);
}
//---------------------------------------------------------------------
// DrawButton - Draws an owner-draw button
//
LRESULT DrawButton (HWND hWnd, LPDRAWITEMSTRUCT pdi) {
HPEN hPenShadow, hPenLight, hPenDkShadow, hRedPen, hOldPen;
HBRUSH hBr, hOldBr;
LOGPEN lpen;
TCHAR szOut[128];
POINT ptOut[3], ptIn[3];
// Reflect the messages to the report window.
wsprintf (szOut, TEXT ("WM_DRAWITEM Act:%x State:%x"),
pdi->itemAction, pdi->itemState);
SendMessage (GetParent (hWnd), MYMSG_ADDLINE, pdi->CtlID,
(LPARAM)szOut);
// Create pens for drawing.
lpen.lopnStyle = PS_SOLID;
lpen.lopnWidth.x = 3;
lpen.lopnWidth.y = 3;
lpen.lopnColor = GetSysColor (COLOR_3DSHADOW);
hPenShadow = CreatePenIndirect (&lpen);
lpen.lopnColor = RGB (255, 0, 0);
hRedPen = CreatePenIndirect (&lpen);
lpen.lopnWidth.x = 1;
lpen.lopnWidth.y = 1;
lpen.lopnColor = GetSysColor (COLOR_3DLIGHT);
hPenLight = CreatePenIndirect (&lpen);
lpen.lopnColor = GetSysColor (COLOR_3DDKSHADOW);
hPenDkShadow = CreatePenIndirect (&lpen);
// Create a brush for the face of the button.
hBr = CreateSolidBrush (GetSysColor (COLOR_3DFACE));
// Draw a rectangle with a thick outside border to start the
// frame drawing.
hOldPen = (HPEN_SelectObject (pdi->hDC, hPenShadow);
hOldBr = (HBRUSH)SelectObject (pdi->hDC, hBr);
Rectangle (pdi->hDC, pdi->rcItem.left, pdi->rcItem.top,
pdi->rcItem.right, pdi->rcItem.bottom);
// Draw the upper left inside line.
ptIn[0].x = pdi->rcItem.left + 1;
ptIn[0].y = pdi->rcItem.bottom - 2;
ptIn[1].x = pdi->rcItem.left + 1;
ptIn[1].y = pdi->rcItem.top + 1;
ptIn[2].x = pdi->rcItem.right - 2;
ptIn[2].y = pdi->rcItem.top + 1;
// Select a pen to draw shadow or light side of button.
if (pdi->itemState & ODS_SELECTED) {
SelectObject (pdi->hDC, hPenDkShadow);
} else {
SelectObject (pdi->hDC, hPenLight);
}
Polyline (pdi->hDC, ptIn, 3);
// If selected, also draw a bright line inside the lower
// right corner.
if (pdi->itemState & ODS_SELECTED) {
SelectObject (pdi->hDC, hPenLight);
ptIn[1].x = pdi->rcItem.right - 2;
ptIn[1].y = pdi->rcItem.bottom - 2;
Polyline (pdi->hDC, ptIn, 3);
}
// Now draw the black outside line on either the upper left or lower
// right corner.
ptOut[0].x = pdi->rcItem.left;
ptOut[0].y = pdi->rcItem.bottom - 1;
ptOut[2].x = pdi->rcItem.right - 1;
ptOut[2].y = pdi->rcItem.top;
SelectObject (pdi->hDC, hPenDkShadow);
if (pdi->itemState & ODS_SELECTED) {
ptOut[1].x = pdi->rcItem.left;
ptOut[1].y = pdi->rcItem.top;
} else {
ptOut[1].x = pdi->rcItem.right - 1;
ptOut[1].y = pdi->rcItem.bottom - 1;
}
Polyline (pdi->hDC, ptOut, 3);
// Draw the triangle.
ptOut[0].x = (pdi->rcItem.right - pdi->rcItem.left)/2;
ptOut[0].y = pdi->rcItem.top + 4;
ptOut[1].x = pdi->rcItem.left + 3;
ptOut[1].y = pdi->rcItem.bottom - 6;
ptOut[2].x = pdi->rcItem.right - 6;
ptOut[2].y = pdi->rcItem.bottom - 6;
SelectObject (pdi->hDC, hRedPen);
Polygon (pdi->hDC, ptOut, 3);
// If button has the focus, draw the dotted rect inside the button.
if (pdi->itemState & ODS_FOCUS) {
pdi->rcItem.left += 3;
pdi->rcItem.top += 3;
pdi->rcItem.right -= 4;
pdi->rcItem.bottom -= 4;
DrawFocusRect (pdi->hDC, &pdi->rcItem);
}
// Clean up. First select the original brush and pen into the DC.
SelectObject (pdi->hDC, hOldBr);
SelectObject (pdi->hDC, hOldPen);
// Now delete the brushes and pens created.
DeleteObject (hBr);
DeleteObject (hPenShadow);
DeleteObject (hPenDkShadow);
DeleteObject (hPenLight);
return 0;
}
EditWnd.cpp