在構造窗口應用程序前,先準備好如下變量:
HINSTANCE _hInst;
HWND _hWnd;
TCHAR szClassName[] = TEXT("Test Class");
TCHAR szTitleName[] = TEXT("Test Window");
ATOM MyRegisterClass(HINSTANCE hInstance); // 註冊窗口類別
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow); // 創建窗口
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); // 窗口消息處理程序
1. 註冊窗口類別
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_MENU);
wcex.lpszClassName = szClassName;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
RegisterClass(&wcex);
}
說明
1) WNDCLASS結構(以UNICODE版本爲例)
typedef struct tagWNDCLASSW {
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCWSTR lpszMenuName;
LPCWSTR lpszClassName;
} WNDCLASSW, *PWNDCLASSW, NEAR *NPWNDCLASSW, FAR *LPWNDCLASSW;
a)style: 窗口樣式
#define CS_VREDRAW 0x0001
#define CS_HREDRAW 0x0002
#define CS_DBLCLKS 0x0008
#define CS_OWNDC 0x0020
#define CS_CLASSDC 0x0040
#define CS_PARENTDC 0x0080
#define CS_NOCLOSE 0x0200
#define CS_SAVEBITS 0x0800
#define CS_BYTEALIGNCLIENT 0x1000
#define CS_BYTEALIGNWINDOW 0x2000
#define CS_GLOBALCLASS 0x4000
b)lpfnWndProc: 窗口類別的窗口消息處理程序,這是一個函數指針
typedef LRESULT (CALLBACK *lpfnWndProc)(HWND, UINT, WPARAM, LPARAM);
c)hInstance: 執行實體句柄
d)lpszMenuName: 指定窗口類別菜單
e)lpszClassName: 窗口類別名稱
f)處理RegisterClass()
if(!RegisterClass(wc))
{
MessageBox(...);
return 0;
}
2. 建立窗口
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
_hInst = hInstance;
hWnd = CreateWindow(
szClassName,
szTitleName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
if(hWnd==NULL)
return FALSE;
_hWnd = hWnd;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
}
1) 說明
#define CreateWindowW(
lpClassName, // 窗口類名稱
lpWindowName, // 窗口標題名稱
dwStyle, // 窗口樣式
x, // x座標
y, // y座標
nWidth, // width
nHeight, // height
hWndParent, // 父窗口
hMenu, // 菜單
hInstance, // 執行實體句柄
lpParam) // lParam
dwStyle: 窗口樣式
#define WS_OVERLAPPED 0x00000000L
#define WS_POPUP 0x80000000L
#define WS_CHILD 0x40000000L
#define WS_MINIMIZE 0x20000000L
#define WS_VISIBLE 0x10000000L
#define WS_DISABLED 0x08000000L
#define WS_CLIPSIBLINGS 0x04000000L
#define WS_CLIPCHILDREN 0x02000000L
#define WS_MAXIMIZE 0x01000000L
#define WS_CAPTION 0x00C00000L /* WS_BORDER | WS_DLGFRAME */
#define WS_BORDER 0x00800000L
#define WS_DLGFRAME 0x00400000L
#define WS_VSCROLL 0x00200000L
#define WS_HSCROLL 0x00100000L
#define WS_SYSMENU 0x00080000L
#define WS_THICKFRAME 0x00040000L
#define WS_GROUP 0x00020000L
#define WS_TABSTOP 0x00010000L
#define WS_MINIMIZEBOX 0x00020000L
#define WS_MAXIMIZEBOX 0x00010000L
#define WS_TILED WS_OVERLAPPED
#define WS_ICONIC WS_MINIMIZE
#define WS_SIZEBOX WS_THICKFRAME
#define WS_TILEDWINDOW WS_OVERLAPPEDWINDOW
/*
* Common Window Styles
*/
#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | /
WS_CAPTION | /
WS_SYSMENU | /
WS_THICKFRAME | /
WS_MINIMIZEBOX | /
WS_MAXIMIZEBOX)
#define WS_POPUPWINDOW (WS_POPUP | /
WS_BORDER | /
WS_SYSMENU)
#define WS_CHILDWINDOW (WS_CHILD)
3. 消息循環
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
1)MSG結構
typedef struct tagMSG {
HWND hwnd; // 窗口句柄
UINT message; // message,以WM_開頭的一系列消息
WPARAM wParam; // 消息參數
LPARAM lParam; // 消息參數
DWORD time; // 消息放入消息隊列時間
POINT pt; // 消息放入消息隊列時的鼠標座標
#ifdef _MAC
DWORD lPrivate;
#endif
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;
Windows負責爲每個應用程序維護一個消息隊列,當用戶觸發窗口事件時,windows將該事件轉換成相應的消息,放入消息隊列中;
GetMessage()從消息隊列中取出消息,經過TranslateMessage();
DispatchMessage()再將消息傳遞給windows,由windows調用相應窗口的窗口處理程序
2)窗口消息處理程序
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
int wmId, wmEvetn;
switch(message)
{
case WM_CREATE:
... ... ;
break;
case WM_SIZE:
// TODO
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
//DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
BeginPaint(hWnd, &ps);
// TODO ...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}