//---
注意 在创建子窗口时CreateWindow中的有个参数是用的
((LPCREATESTRUCT) lParam)->hInstance,
The instance handle parameter of the CreateWindow call looks a little strange,
but we're taking advantage of the fact that during a WM_CREATE message lParam is
actually a pointer to a structure of type CREATESTRUCT ("creation structure")
that has a member hInstance. So we cast lParam into a pointer to a CREATESTRUCT structure and get hInstance out.
(Some Windows programs use a global variable named hInst to give window procedures access
to the instance handle available in WinMain. In WinMain, you need to simply set
hInst = hInstance ;
before creating the main window. In the CHECKER3 program in Chapter 7,
we used GetWindowLong to obtain this instance handle:
GetWindowLong (hwnd, GWL_HINSTANCE)
Any of these methods is fine.)
在WM_CREATE消息中,lparam实际是 LPCREATESTRUCT指针.
该结构体的成员中就包含了应用程序的hInstance,以及常用的坐标(cy,cx,y,x)
typedef struct tagCREATESTRUCTW {
LPVOID lpCreateParams;
HINSTANCE hInstance;
HMENU hMenu;
HWND hwndParent;
int cy;
int cx;
int y;
int x;
LONG style;
LPCWSTR lpszName;
LPCWSTR lpszClass;
DWORD dwExStyle;
} CREATESTRUCTW, *LPCREATESTRUCTW;
#ifdef UNICODE
typedef CREATESTRUCTW CREATESTRUCT;
typedef LPCREATESTRUCTW LPCREATESTRUCT;
#else
typedef CREATESTRUCTA CREATESTRUCT;
typedef LPCREATESTRUCTA LPCREATESTRUCT;
#endif // UNICODE
*/
//---
/*----------------------------------------BTNLOOK.C -- Button Look Program(c) Charles Petzold, 1998----------------------------------------*/#include <windows.h>//button window styles and descriptive text strings for each of the 10 types of buttons.
// After the CreateWindow call, we needn't do anything more with these child windows.
//The button window procedure within Windows maintains the buttons for us and handles all repainting jobs.
//(The exception is the button with the BS_OWNERDRAW style; as I'll discuss later,
//this button style requires the program to draw the button.)
struct
{int iStyle ;TCHAR * szText ;
}
button[] =
{BS_PUSHBUTTON, TEXT ("PUSHBUTTON"),BS_DEFPUSHBUTTON, TEXT ("DEFPUSHBUTTON"),BS_CHECKBOX, TEXT ("CHECKBOX"), BS_AUTOCHECKBOX, TEXT ("AUTOCHECKBOX"),BS_RADIOBUTTON, TEXT ("RADIOBUTTON"),BS_3STATE, TEXT ("3STATE"),BS_AUTO3STATE, TEXT ("AUTO3STATE"),BS_GROUPBOX, TEXT ("GROUPBOX"),BS_AUTORADIOBUTTON, TEXT ("AUTORADIOBUTTON"),BS_OWNERDRAW, TEXT ("OWNERDRAW") // 这个button style 特别,它
} ;#define NUM (sizeof button / sizeof button[0])LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow)
{static TCHAR szAppName[] = TEXT ("BtnLook") ;HWND hwnd ;MSG msg ;WNDCLASS wndclass ;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 = NULL ;wndclass.lpszClassName = szAppName ;if (!RegisterClass (&wndclass)){MessageBox (NULL, TEXT ("This program requires Windows NT!"),szAppName, MB_ICONERROR) ;return 0 ;}hwnd = CreateWindow (szAppName, TEXT ("Button Look"),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 ;
}LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{static HWND hwndButton[NUM] ;static RECT rect ;static TCHAR szTop[] = TEXT ("message wParam lParam"),szUnd[] = TEXT ("_______ ______ ______"),szFormat[] = TEXT ("%-16s%04X-%04X %04X-%04X"),szBuffer[50] ;static int cxChar, cyChar ;HDC hdc ;PAINTSTRUCT ps ;int i ;switch (message){case WM_CREATE :// a function named GetDialogBaseUnits to obtain the width and height of the characters in the default font. //The function returns a 32-bit value comprising a width in the low word and a height in the high word. // GetTextMetrics function 也可以.cxChar = LOWORD (GetDialogBaseUnits ()) ; // width cyChar = HIWORD (GetDialogBaseUnits ()) ; // heightfor (i = 0 ; i < NUM ; i++)hwndButton[i] = CreateWindow ( TEXT("button"), button[i].szText,WS_CHILD | WS_VISIBLE | button[i].iStyle,cxChar, cyChar * (1 + 2 * i),20 * cxChar, 7 * cyChar / 4,hwnd, (HMENU) i, // 强制转换为菜单ID((LPCREATESTRUCT) lParam)->hInstance, NULL) ;return 0 ;case WM_SIZE :rect.left = 24 * cxChar ; // 24个cxChar的宽度的位置rect.top = 2 * cyChar ; // 高rect.right = LOWORD (lParam) ;rect.bottom = HIWORD (lParam) ;return 0 ;case WM_PAINT :InvalidateRect (hwnd, &rect, TRUE) ;hdc = BeginPaint (hwnd, &ps) ;SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;SetBkMode (hdc, TRANSPARENT) ;TextOut (hdc, 24 * cxChar, cyChar, szTop, lstrlen (szTop)) ;TextOut (hdc, 24 * cxChar, cyChar, szUnd, lstrlen (szUnd)) ;EndPaint (hwnd, &ps) ;return 0 ;case WM_DRAWITEM :case WM_COMMAND :/*在WM_COMMAND消息中, wParam,lParam中包含的数据如下LOWORD (wParam) : Child window ID HIWORD (wParam): Notification code lParam: Child window handle Button Notification Code Identifier ---- Value BN_CLICKED: 0 BN_PAINT: 1 BN_HILITE or BN_PUSHED: 2 BN_UNHILITE or BN_UNPUSHED: 3 BN_DISABLE:4 BN_DOUBLECLICKED or BN_DBLCLK: 5 BN_SETFOCUS: 6 BN_KILLFOCUS: 7 */// 滚动窗口ScrollWindow (hwnd, 0, -cyChar, &rect, &rect) ;hdc = GetDC (hwnd) ;SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;TextOut (hdc, 24 * cxChar, cyChar * (rect.bottom / cyChar - 1),szBuffer,wsprintf (szBuffer, szFormat,message == WM_DRAWITEM ? TEXT ("WM_DRAWITEM") : TEXT ("WM_COMMAND"),HIWORD (wParam), LOWORD (wParam),HIWORD (lParam), LOWORD (lParam))) ;ReleaseDC (hwnd, hdc) ;ValidateRect (hwnd, &rect) ;break ;case WM_DESTROY :PostQuitMessage (0) ;return 0 ;}return DefWindowProc (hwnd, message, wParam, lParam) ;
}