/*---------------------------------------------
OWNDRAW.C -- Owner-Draw Button Demo Program
(c) Charles Petzold, 1998
---------------------------------------------*/
#include
#define ID_SMALLER 1 //子控件1,缩小窗口
#define ID_LARGER 2 //子控件2,放大窗口功能
#define BTN_WIDTH (8 * cxChar)
#define BTN_HEIGHT (4 * cyChar)
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
HINSTANCE hInst ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("OwnDraw") ;
MSG msg ;
HWND hwnd ;
WNDCLASS wndclass ;
hInst = hInstance ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = szAppName ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("Owner-Draw Button Demo"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
//该函数画一个三角形
void Triangle (HDC hdc, POINT pt[])
{
SelectObject (hdc, GetStockObject (BLACK_BRUSH)) ;
Polygon (hdc, pt, 3) ;
SelectObject (hdc, GetStockObject (WHITE_BRUSH)) ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hwndSmaller, hwndLarger ;
static int cxClient, cyClient, cxChar, cyChar ;
int cx, cy ;
LPDRAWITEMSTRUCT pdis ;
POINT pt[3] ;
RECT rc ;
switch (message)
{
case WM_CREATE :
//主窗口客户区的大小
cxChar = LOWORD (GetDialogBaseUnits ()) ;
cyChar = HIWORD (GetDialogBaseUnits ()) ;
// 创建两个子窗口控件 ,这个子窗口过程会受到两个wm_create消息,没们不需要写出这个子窗口过程,系统会自动处理
//BS_OWNERDRAW样式要再wm_create,wm_size,wm_drawitem后子窗口才会出现,即使指定了WS_VISIBLE样式
hwndSmaller = CreateWindow (TEXT ("button"), TEXT (""),
WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
0, 0, BTN_WIDTH, BTN_HEIGHT,
hwnd, (HMENU) ID_SMALLER, hInst, NULL) ;
hwndLarger = CreateWindow (TEXT ("button"), TEXT (""),
WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
0, 0, BTN_WIDTH, BTN_HEIGHT,
hwnd, (HMENU) ID_LARGER, hInst, NULL) ;
return 0 ;
case WM_SIZE :
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
//移动两个按钮到指定的位置
MoveWindow (hwndSmaller, cxClient / 2 - 3 * BTN_WIDTH / 2,
cyClient / 2 - BTN_HEIGHT / 2,
BTN_WIDTH, BTN_HEIGHT, TRUE) ;
MoveWindow (hwndLarger, cxClient / 2 + BTN_WIDTH / 2,
cyClient / 2 - BTN_HEIGHT / 2,
BTN_WIDTH, BTN_HEIGHT, TRUE) ;
return 0 ;
case WM_COMMAND ://当有子控件被按下,产生这个消息
//获取主窗口的大小
GetWindowRect (hwnd, &rc) ;
// Make the window 10% smaller or larger
switch (wParam)
{
case ID_SMALLER : //缩小按钮被按下,主窗口缩小10%
rc.left += cxClient / 20 ;
rc.right -= cxClient / 20 ;
rc.top += cyClient / 20 ;
rc.bottom -= cyClient / 20 ;
break ;
case ID_LARGER ://放到按钮被按下,主窗口放到10%
rc.left -= cxClient / 20 ;
rc.right += cxClient / 20 ;
rc.top -= cyClient / 20 ;
rc.bottom += cyClient / 20 ;
break ;
}
MoveWindow (hwnd, rc.left, rc.top, rc.right - rc.left,
rc.bottom - rc.top, TRUE) ;//主窗口改变了,会产生wm_size消息,使得子控件重新定位到相对屏幕的位置
return 0 ;
case WM_DRAWITEM : //子控件改变时
pdis = (LPDRAWITEMSTRUCT) lParam ;//指向drawitemstruct结构体的指针,保存着按钮大小,控件id等信息
// 填充矩形
FillRect (pdis->hDC, &pdis->rcItem,
(HBRUSH) GetStockObject (WHITE_BRUSH)) ;
//填充边框
FrameRect (pdis->hDC, &pdis->rcItem,
(HBRUSH) GetStockObject (BLACK_BRUSH)) ;
// Draw inward and outward black triangles
cx = pdis->rcItem.right - pdis->rcItem.left ;
cy = pdis->rcItem.bottom - pdis->rcItem.top ;
switch (pdis->CtlID)
{
case ID_SMALLER : //若为缩小按钮
//确定三角形三个点的位置
pt[0].x = 3 * cx / 8 ; pt[0].y = 1 * cy / 8 ;
pt[1].x = 5 * cx / 8 ; pt[1].y = 1 * cy / 8 ;
pt[2].x = 4 * cx / 8 ; pt[2].y = 3 * cy / 8 ;
//画三角形
Triangle (pdis->hDC, pt) ;
pt[0].x = 7 * cx / 8 ; pt[0].y = 3 * cy / 8 ;
pt[1].x = 7 * cx / 8 ; pt[1].y = 5 * cy / 8 ;
pt[2].x = 5 * cx / 8 ; pt[2].y = 4 * cy / 8 ;
Triangle (pdis->hDC, pt) ;
pt[0].x = 5 * cx / 8 ; pt[0].y = 7 * cy / 8 ;
pt[1].x = 3 * cx / 8 ; pt[1].y = 7 * cy / 8 ;
pt[2].x = 4 * cx / 8 ; pt[2].y = 5 * cy / 8 ;
Triangle (pdis->hDC, pt) ;
pt[0].x = 1 * cx / 8 ; pt[0].y = 5 * cy / 8 ;
pt[1].x = 1 * cx / 8 ; pt[1].y = 3 * cy / 8 ;
pt[2].x = 3 * cx / 8 ; pt[2].y = 4 * cy / 8 ;
Triangle (pdis->hDC, pt) ;
break ;
case ID_LARGER : //若为放到按钮
pt[0].x = 5 * cx / 8 ; pt[0].y = 3 * cy / 8 ;
pt[1].x = 3 * cx / 8 ; pt[1].y = 3 * cy / 8 ;
pt[2].x = 4 * cx / 8 ; pt[2].y = 1 * cy / 8 ;
Triangle (pdis->hDC, pt) ;
pt[0].x = 5 * cx / 8 ; pt[0].y = 5 * cy / 8 ;
pt[1].x = 5 * cx / 8 ; pt[1].y = 3 * cy / 8 ;
pt[2].x = 7 * cx / 8 ; pt[2].y = 4 * cy / 8 ;
Triangle (pdis->hDC, pt) ;
pt[0].x = 3 * cx / 8 ; pt[0].y = 5 * cy / 8 ;
pt[1].x = 5 * cx / 8 ; pt[1].y = 5 * cy / 8 ;
pt[2].x = 4 * cx / 8 ; pt[2].y = 7 * cy / 8 ;
Triangle (pdis->hDC, pt) ;
pt[0].x = 3 * cx / 8 ; pt[0].y = 3 * cy / 8 ;
pt[1].x = 3 * cx / 8 ; pt[1].y = 5 * cy / 8 ;
pt[2].x = 1 * cx / 8 ; pt[2].y = 4 * cy / 8 ;
Triangle (pdis->hDC, pt) ;
break ;
}
// Invert the rectangle if the button is selected
if (pdis->itemState & ODS_SELECTED) //按钮时被选中
InvertRect (pdis->hDC, &pdis->rcItem) ; //选中后颜色反转
// Draw a focus rectangle if the button has the focus
if (pdis->itemState & ODS_FOCUS) //按钮有焦点后,画一个矩形
{
pdis->rcItem.left += cx / 16 ;
pdis->rcItem.top += cy / 16 ;
pdis->rcItem.right -= cx / 16 ;
pdis->rcItem.bottom -= cy / 16 ;
DrawFocusRect (pdis->hDC, &pdis->rcItem) ;
}
return 0 ;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}