一、消息驅動
創建窗口後,要對窗口的行爲負責。操作系統不斷的嚮應用程序發送消息,通知它發生了什麼事情。
當Widnows向程序發送消息時,它調用程序中的一個函數,這個函數的參數精確地描述了Windows發送的消息。
在程序中稱其爲窗口函數或消息處理函數。它是一個自定義的回調函數。原型如下:
LRESULT CALLBACK WindowProc(HWND hwnd,UINT hMsg,WPARAM wParam,LPARAM lParam);
二、顯示一個窗口的具體步驟
1、註冊窗口類RegisterClassEx
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
char szClassName[] = "MainWClass";
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = MainWndProc;
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 = szClassName;
wndclass.hIconSm = NULL;
::RegisterClassEx(&wndclass);
......
}
2、創建窗口CreateWindowEx
//創建主窗口
HWND hWnd = ::CreateWindowEx(0,
szClassName,//類名
"我的第一個GUI程序",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
if (NULL == hWnd) {
::MessageBox(NULL, "創建窗口失敗", "錯誤", MB_OK);
return -1;
}
3、在桌面顯示窗口ShowWindow
//顯示窗口
::ShowWindow(hWnd, nCmdShow);
4、更新窗口客戶區UpdateWindow
::UpdateWindow(hWnd);
5、進入消息獲取和處理的循環。
首先是獲取消息GetMessage,如果有消息到達,則將消息分派到回調函數處理DispatchMessage,如果是WM_QUIT,則GetMessage返回FALSE,則整個消息循環結束。消息的具體處理過程在MainWndProc函數中進行。
//從操作系統的消息隊列中不斷的撿取消息
MSG msg;
while (::GetMessage(&msg, NULL, 0, 0))
{
//轉化鍵盤消息
::TranslateMessage(&msg);
// 將消息發送到相應的窗口函數
::DispatchMessage(&msg);
}
// 當GetMessage返回0時,程序結束
return msg.wParam;
6、回調函數
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam)
{
switch (message)
{
case WM_DESTROY: // 正在銷燬窗口
// 向消息隊列投遞一個WM_QUIT消息,促使GetMessage函數返回0,結束消息循環
::PostQuitMessage(0);
return 0;
}
// 將我們不處理的消息交給操作系統默認處理。
return ::DefWindowProc(hWnd, message, wparam, lparam);
}
三、實例
1、實例
#include <stdio.h>
#include <windows.h>
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow) {
char szClassName[] = "MainWClass";
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = MainWndProc;
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 = szClassName;
wndclass.hIconSm = NULL;
::RegisterClassEx(&wndclass);
//創建主窗口
HWND hWnd = ::CreateWindowEx(0,
szClassName,//類名
"我的第一個GUI程序",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
if (NULL == hWnd) {
::MessageBox(NULL, "創建窗口失敗", "錯誤", MB_OK);
return -1;
}
//顯示窗口
::ShowWindow(hWnd, nCmdShow);
::UpdateWindow(hWnd);
//從操作系統的消息隊列中不斷的撿取消息
MSG msg;
while (::GetMessage(&msg, NULL, 0, 0)) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam) {
switch (message) {
case WM_DESTROY:
::PostQuitMessage(0);
return 0;
}
return ::DefWindowProc(hWnd, message, wparam, lparam);
}
2、運行結果