Windows視窗程式從建立到關閉產生的訊息
阿新 • • 發佈:2019-01-29
Windows是訊息驅動的,理解訊息機制及訊息迴圈是特別重要。知道在什麼情況下產生什麼訊息會讓我們對程式有更好的控制。Windows給應用程式發訊息,有些會加入應用程式的訊息佇列,也是就是佇列訊息。有些直接呼叫視窗訊息處理程式,不會加入到訊息佇列,這部分為非佇列訊息。
下面分析一下一個應用程式從建立到結束產生的訊息。
先給出測試用的程式,當然是一個非常經典的結構:
啟動這個程式到關閉他都會產生什麼訊息呢?#include <windows.h> #include <tchar.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { MSG msg; TCHAR szClassName[] = _T("MainWClass"); WNDCLASSEX wndclass; wndclass.cbClsExtra = 0; wndclass.cbSize = sizeof(wndclass); wndclass.cbWndExtra = 0; wndclass.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH); wndclass.hCursor = ::LoadCursor(NULL, IDI_APPLICATION); wndclass.hIcon = ::LoadIcon(NULL, IDC_ARROW); wndclass.hIconSm = NULL; wndclass.hInstance = hInstance; wndclass.lpfnWndProc = WndProc; wndclass.lpszClassName = szClassName; wndclass.lpszMenuName = NULL; wndclass.style = CS_HREDRAW | CS_VREDRAW; if (::RegisterClassEx(&wndclass) == 0) { ::MessageBox(NULL, _T("RegisterClassEx Failed"), _T("Error"), MB_OK | MB_ICONHAND); return 0; } HWND hwnd = ::CreateWindow( szClassName, // lpClassName _T("My Window"), // lpWindowName WS_OVERLAPPEDWINDOW, // dwStyle CW_USEDEFAULT, // X CW_USEDEFAULT, // Y CW_USEDEFAULT, // nWidth CW_USEDEFAULT, // nHeight NULL, // hWndParent, NULL, // hMenu hInstance, // hInstance NULL // lpParam ); ::ShowWindow(hwnd, nShowCmd); ::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) { TCHAR szText[] = _T("Simple Window!"); switch (message) { case WM_PAINT: { HDC hdc; PAINTSTRUCT ps; hdc = ::BeginPaint(hwnd, &ps); ::TextOut(hdc, 10, 10, szText, _tcslen(szText)); ::EndPaint(hwnd, &ps); } return 0; case WM_DESTROY: ::PostQuitMessage(0); return 0; } return ::DefWindowProc(hwnd, message, wParam, lParam); }
// 呼叫CreateWindow後產生第一條訊息: CreateWindow() 0X0024 WM_GETMINMAXINFO "當視窗將要改變大小或位置時,由系統傳送本訊息給視窗,使用者拖動一個可重置大小的視窗時便會發出本訊息" 0X0081 WM_NCCREATE "當某視窗首次被建立時,本訊息在WM_CREATE訊息傳送前傳送" 0X0083 WM_NCCALCSIZE "當某視窗的客戶區的大小和位置須被計算時傳送本訊息" 0X0001 WM_CREATE "新建一個視窗" CreateWindow() 返回 ShowWindow() 0X0018 WM_SHOWWINDOW "傳送本訊息給一個視窗,以便隱藏或顯示該視窗" 0X0046 WM_WINDOWPOSCHANGING "本訊息會發送給那些大小和位置(Z_Order)將被改變的視窗,以呼叫SetWindowPos函式或其它視窗管理函式" 0X001C WM_ACTIVATEAPP "視窗程序啟用狀態改動,正被啟用的視窗屬於不同的應用程式 " 0X0086 WM_NCACTIVATE "本訊息傳送給某視窗,在視窗的非客戶區被啟用時重繪視窗" 0X007F WM_GETICON "本訊息傳送給某個視窗,用於返回與某視窗有關聯的大圖示或小圖示的控制代碼(一般收到多個,用於獲取不同大小的圖示)" 0X0006 WM_ACTIVATE "一個視窗被啟用或失去啟用狀態" 0X0281 WM_IME_SETCONTEXT "應用程式的視窗啟用時,系統將嚮應用程式傳送WM_IME_SETCONTEXT訊息,輸入焦點轉移到了某個視窗上,注:輸入法相關" 0X0282 WM_IME_NOTIFY "可使用WM_IME_NOTIFY訊息來通知關於IME視窗狀態的常規改變,注:輸入法相關,IME視窗發生了改變" 0X0007 WM_SETFOCUS "將焦點轉向一個視窗" 0X0085 WM_NCPAINT "當視窗框架(非客戶區)必須被被重繪時,應用程式傳送本訊息給該視窗" 0X0014 WM_ERASEBKGND "當一個視窗的背景必須被擦除時本訊息會被觸發(如:視窗大小改變時)" 0X0047 WM_WINDOWPOSCHANGED "本訊息會發送給那些大小和位置(Z_Order)已被改變的視窗,以呼叫SetWindowPos函式或其它視窗管理函式" 0X0005 WM_SIZE "改變一個視窗的大小" 0X0003 WM_MOVE "移動一個視窗" ShowWindow() 返回 UpdateWindow() 0X000F WM_PAINT "視窗重繪" UpdateWindow() 返回 0X007F WM_GETICON "本訊息傳送給某個視窗,用於返回與某視窗有關聯的大圖示或小圖示的控制代碼(一般收到多個,用於獲取不同大小的圖示)" // 進入訊息迴圈 0X0113 WM_TIMER "發生了定時器事件" 0X0101 WM_KEYUP "當一個非系統按鍵被釋放彈起時(<ALT>鍵沒有被按下),會發送本訊息給擁有鍵盤焦點的視窗" 0X0113 WM_TIMER "發生了定時器事件" 0X0104 WM_SYSKEYDOWN "當用戶按住<ALT>鍵的同時又按下其它鍵時,傳送本訊息給擁有焦點的視窗", 0X0112 WM_SYSCOMMAND "當用戶選擇一條系統選單命令、使用者最大化或最小化或還原或關閉時,視窗會收到本訊息" 0X0010 WM_CLOSE "使用者關閉視窗時會發送本訊息,緊接著會發送WM_DESTROY訊息" 0X0046 WM_WINDOWPOSCHANGING "本訊息會發送給那些大小和位置(Z_Order)將被改變的視窗,以呼叫SetWindowPos函式或其它視窗管理函式" 0X0047 WM_WINDOWPOSCHANGED "本訊息會發送給那些大小和位置(Z_Order)已被改變的視窗,以呼叫SetWindowPos函式或其它視窗管理函式" 0X0086 WM_NCACTIVATE "本訊息傳送給某視窗,在視窗的非客戶區被啟用時重繪視窗" 0X0006 WM_ACTIVATE "一個視窗被啟用或失去啟用狀態" 0X001C WM_ACTIVATEAPP "視窗程序啟用狀態改動,正被啟用的視窗屬於不同的應用程式 " 0X0008 WM_KILLFOCUS "使一個視窗失去焦點" 0X0281 WM_IME_SETCONTEXT "應用程式的視窗啟用時,系統將嚮應用程式傳送WM_IME_SETCONTEXT訊息,輸入焦點轉移到了某個視窗上,注:輸入法相關" 0X0282 WM_IME_NOTIFY "可使用WM_IME_NOTIFY訊息來通知關於IME視窗狀態的常規改變,注:輸入法相關,IME視窗發生了改變" 0X0002 WM_DESTROY "銷燬一個視窗" 0X0082 WM_NCDESTROY "本訊息通知某視窗,非客戶區正在銷燬"
就是以上這些,可以看出上面的訊息是使用系統快捷鍵來關閉的程式。