windows訊息機制的有趣發現(二)

來源:互聯網
上載者:User

3.一個有視窗和視窗過程函數但沒有訊息迴圈的程式

一個程式,如果我們建立了視窗,也定義了視窗過程函數,但是沒有建立訊息迴圈會怎樣呢?我們在win32控制台項目下編寫如下代碼:

#include <windows.h>#define WM_TEST 10000LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void main(){static TCHAR szAppName[]=TEXT("Test!");HWND hwnd;WNDCLASS wndclass = {NULL};wndclass.lpfnWndProc = WndProc;wndclass.style = CS_HREDRAW|CS_VREDRAW;wndclass.lpszClassName= szAppName;RegisterClass(&wndclass);hwnd=CreateWindow(szAppName,TEXT("The Test Program"),WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,NULL,NULL);ShowWindow(hwnd,SW_SHOW);UpdateWindow(hwnd);system("pause");}LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM IParam) {switch(message){case WM_TEST:MessageBox(NULL,TEXT("訊息響應!"),TEXT("訊息響應!"),MB_OK);return 50;}return DefWindowProc(hwnd,message,wParam,IParam);}

這是一個簡單的win32視窗程序,但是我們在視窗過程函數WndProc中沒有定義對WN_PAINT訊息的處理,在main函數中建立完視窗後也沒有建立訊息迴圈,運行程式後會發生什麼呢?

運行發現,視窗確實被建立出來了。但是滑鼠移動上去就會發現該表單假死一樣沒有了響應。這是因為包括自繪訊息WM_PAINT在內的所有訊息都被放入了線程的訊息佇列裡,但是我們沒有訊息迴圈!沒有取出訊息佇列中的訊息,更沒有處理這些訊息,我們連視窗過程中對應WM_PAINT的訊息處理函數都沒有。介面自然就假死了。

4.SendMessage和PostMessage訊息的另一個區別

之前我寫過一篇博文說過SendMessage和PostMessage的卻別在於SendMessage要等訊息被處理完成後才返回,如果調用SendMessage後該訊息一直未處理完,SendMessage會一直阻塞到處理完為止。而PostMessage不會阻塞,不等處理結果直接返回。實際上他們還有一個區別:PostMessage發送的訊息會進入訊息佇列等待提取,而SendMessage發送的訊息不進訊息佇列,直接交給視窗過程函數處理。為了驗證這個說法,我們編寫如下代碼:

#include <windows.h>#define WM_TEST 10000LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void main(){static TCHAR szAppName[]=TEXT("Test!");HWND hwnd;WNDCLASS wndclass = {NULL};wndclass.lpfnWndProc = WndProc;wndclass.style = CS_HREDRAW|CS_VREDRAW;wndclass.lpszClassName= szAppName;RegisterClass(&wndclass);hwnd=CreateWindow(szAppName,TEXT("The Test Program"),WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,NULL,NULL);ShowWindow(hwnd,SW_SHOW);UpdateWindow(hwnd);int i = SendMessage(hwnd,WM_TEST,NULL,NULL);system("pause");}LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM IParam) {switch(message){case WM_TEST:MessageBox(NULL,TEXT("訊息響應!"),TEXT("訊息響應!"),MB_OK);return 50;}return DefWindowProc(hwnd,message,wParam,IParam);}

我們在建立完視窗後用SendMessage發送了一條WM_TEST的自訂訊息,在視窗過程函數WndProc中我們定義對WM_TEST的處理方式為彈出一個MessageBox並返回50。

運行後發現,縱使我們建立的表單依然是假死狀態,仍然彈出了MessageBox,並且SendMessage的傳回值i為50。說明我們在視窗過程函數WndProc中定義的對WM_TEST訊息的處理代碼成功執行!注意,我們這個程式中是沒有訊息迴圈的,但是我們用SendMessage發送的訊息還是被視窗過程函數WndProc處理了。

我們把SendMessage改為PostMessage再試。運行後發現沒有彈出MessageBox。為什麼呢?因為PostMessage發送的訊息要進訊息佇列,但我們沒有訊息迴圈,沒有用GetMessage之類的函數從訊息佇列中取訊息,更沒有用DispatchMessage分發訊息,所以我們用PostMessage發送的WM_TEST還在訊息佇列裡待著呢。視窗過程函數WndProc中的代碼沒有執行。

這就證明了SendMessage和PostMessage的另一個不同之處:SendMessage發送的訊息直接交給對應的視窗過程函數處理,不進訊息佇列,而PostMessage發送的訊息要進訊息佇列等待分發、處理。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.