Win32 SDK基礎(chǔ)(十)之詳解幾種常見的Windows消息處理的示例代碼

一 引言

? ? ? ? 本文主要介紹幾種windows常見的消息的處理,在《Win32 SDK基礎(chǔ)(8)—— Windows消息機制》中,我們介紹了WM_CREATE消息的處理,在窗口創(chuàng)建之前,我們利用消息處理函數(shù)彈出了一個MessageBox,本文在此基礎(chǔ)之上,介紹WM_DESTROY、WM_SYSCOMMAND、WM_QUIT、WM_SIZE等函數(shù)常見的Windows消息。首先,我們引入在《Win32 SDK基礎(chǔ)(8)—— Windows消息機制》文中的代碼,后續(xù)的實驗都在此代碼的基礎(chǔ)之上。

#include?"stdafx.h"  #include?"MessageTs.h"    HINSTANCE?g_hInstance?=?0;??  //窗口處理函數(shù)??  LRESULT?CALLBACK?WndProc(HWND?hWnd,?UINT?uMsg,?WPARAM?wParam,?LPARAM?lParam)??  {??  	switch?(uMsg)??  	{??  	case?WM_DESTROY:??  		PostQuitMessage(0);//可以使GetMessage返回0??  		break;?  	case??WM_CREATE:  		MessageBox(NULL,"WM_CREATE消息被處理了","消息處理",MB_OK);  	default:??  		break;??  	}??  	return?DefWindowProc(hWnd,?uMsg,?wParam,?lParam);??  }??  //注冊窗口類??  BOOL?Register(LPSTR?lpClassName,?WNDPROC?wndProc)??  {??  	WNDCLASSEX?wce?=?{?0?};??  	wce.cbSize?=?sizeof(wce);??  	wce.cbClsExtra?=?0;??  	wce.cbWndExtra?=?0;??  	wce.hbrBackground?=?(HBRUSH)(COLOR_WINDOW?+?1);??  	wce.hCursor?=?NULL;??  	wce.hIcon?=?NULL;??  	wce.hIconSm?=?NULL;??  	wce.hInstance?=?g_hInstance;??  	wce.lpfnWndProc?=?wndProc;??  	wce.lpszClassName?=?lpClassName;??  	wce.lpszMenuName?=?NULL;??  	wce.style?=?CS_HREDRAW?|?CS_VREDRAW;??  	ATOM?nAtom?=?RegisterClassEx(&wce);??  	if?(nAtom?==?0)??  		return?FALSE;??  	return?true;??    }??  //創(chuàng)建主窗口??  HWND?CreateMain(LPSTR?lpClassName,?LPSTR?lpWndName)??  {??  	HWND?hWnd?=?CreateWindowEx(0,?lpClassName,?lpWndName,??  		WS_OVERLAPPEDWINDOW,?CW_USEDEFAULT,?CW_USEDEFAULT,?CW_USEDEFAULT,?CW_USEDEFAULT,?NULL,?NULL,?g_hInstance,?NULL);??  	return?hWnd;??  }??  //顯示窗口??  void?Display(HWND?hWnd)??  {??  	ShowWindow(hWnd,?SW_SHOW);??  	UpdateWindow(hWnd);??  }??  //消息循環(huán)??  void?Message()??  {??  	MSG?nMsg?=?{?0?};??  	while?(GetMessage(&nMsg,?NULL,?0,?0))??  	{??  		TranslateMessage(&nMsg);??  		DispatchMessage(&nMsg);??  	}??  }??  int?APIENTRY?wWinMain(_In_?HINSTANCE?hInstance,??  	_In_opt_?HINSTANCE?hPrevInstance,??  	_In_?LPWSTR????lpCmdLine,??  	_In_?int???????nCmdShow)??  {??  	//?TODO:?Place?code?here.??    	g_hInstance?=?hInstance;??  	BOOL?nRet?=?Register("Main",?WndProc);??  	if?(!nRet)??  	{??  		MessageBox(NULL,?"注冊失敗",?"Infor",?MB_OK);??  		return?0;??  	}??  	HWND?hWnd?=?CreateMain("Main",?"window");??  	Display(hWnd);??  	Message();??  	return?0;??  }

?二、WM_CREATE消息

? ? ? ? 我們還是要再介紹下wm_create消息。因為在上一文中我們只通過彈出messagebox驗證了wm_create消息的產(chǎn)生時機,卻沒有介紹它另外一個很重要的構(gòu)成——wparam和lparam參數(shù)。我們在函數(shù)時,往往可以通過這兩個參數(shù)攜帶一些信息。wm_create消息是我們在創(chuàng)建窗口時由系統(tǒng)自動發(fā)送的消息,同樣也會利用這兩個參數(shù)攜帶信息。lparam攜帶了我們創(chuàng)建窗口的createwindowex的12個參數(shù)信息,wparam沒有被使用,下面我們在處理wm_create消息時,在彈出的對話框上顯示窗口類和窗口名稱。

//窗口處理函數(shù)??  LRESULT?CALLBACK?WndProc(HWND?hWnd,?UINT?uMsg,?WPARAM?wParam,?LPARAM?lParam)??  {??  	switch?(uMsg)??  	{??  	case?WM_DESTROY:??  		PostQuitMessage(0);//可以使GetMessage返回0??  		break;?  	case??WM_CREATE:  		{  			CREATESTRUCT?crt?=?*((CREATESTRUCT*)lParam);  			char?buf[256]?=?{0};  			sprintf(buf,"創(chuàng)建的窗口類名稱是%s,窗口名稱是%s",crt.lpszClass,crt.lpszName);  			MessageBox(NULL,?buf,?"消息處理",?MB_OK);  		}  		  	default:??  		break;??  	}??  	return?DefWindowProc(hWnd,?uMsg,?wParam,?lParam);??  }

? ? ? ? 運行程序,我們發(fā)現(xiàn)在窗口創(chuàng)建之前我們成功捕獲了窗口的注冊窗口類名稱和窗口名稱,并在對話框上顯示出來:

Win32 SDK基礎(chǔ)(十)之詳解幾種常見的Windows消息處理的示例代碼

三、WM_DESTROY消息

? ? ? ? 這個消息在之前的文章中我們其實早已經(jīng)解除過。他是Windows窗口關(guān)閉時發(fā)送的一個消息,簡單點說就是,當你點擊Windows窗口的關(guān)閉函數(shù)時,會發(fā)出這個消息。我們在之前的代碼中,處理這個消息的操作是PostQuitMessage(0),這其實是我們發(fā)送了一個接下來要介紹的WM_QUIT消息用來結(jié)束程序的進程。WM_DESTORY消息的LPARAM和WPARAM都沒被使用,它一般被用來做一些窗口關(guān)閉前資源的回收和內(nèi)存的釋放工作等等,我們調(diào)用的PostQuitMessage(0)就是一個很常見的用法。

四、WM_QUIT消息

? ? ? ? 前面我們已經(jīng)介紹過,這是我們使用PostQuitMessage(0)發(fā)送的一個消息,用來結(jié)束程序進程,它的WMPARAM是PostQuitMessage中傳遞的參數(shù),LPARAM參數(shù)未被使用。通常情況下我們發(fā)送了WM_QUIT后,會引起消息循環(huán)中的GetMessage函數(shù)返回,從而使得進程函數(shù)。WM_QUIT消息是無法傳遞到我們自己的窗口處理函數(shù)中的。但是我們可以從側(cè)面驗證有這么一個消息:我們先在代碼中增加對WM_QUIT消息的處理。

LRESULT?CALLBACK?WndProc(HWND?hWnd,?UINT?uMsg,?WPARAM?wParam,?LPARAM?lParam)??  {??  	switch?(uMsg)??  	{??  	case?WM_DESTROY:??  		PostQuitMessage(0);//可以使GetMessage返回0??  		break;?  	case??WM_CREATE:  	{  		CREATESTRUCT?crt?=?*((CREATESTRUCT*)lParam);  		char?buf[256]?=?{0};  		sprintf(buf,"創(chuàng)建的窗口類名稱是%s,窗口名稱是%s",crt.lpszClass,crt.lpszName);  		MessageBox(NULL,?buf,?"消息處理",?MB_OK);  	}  	case?WM_QUIT:  	{  		int?param?=?(int)wParam;  		char?buf[256];  		sprintf(buf,?"進程退出,退出碼:%d",?param);  		MessageBox(NULL,?buf,?"消息處理",?MB_OK);  	}  	default:??  		break;??  	}??  	return?DefWindowProc(hWnd,?uMsg,?wParam,?lParam);??  }

? ? ? ? 運行程序,在關(guān)閉處理WM_CREATE消息的對話框后,發(fā)現(xiàn)彈出了我們驗證WM_QUIT消息的對話框。

Win32 SDK基礎(chǔ)(十)之詳解幾種常見的Windows消息處理的示例代碼

? ? ? ?

? ? ? ? ?這是因為,彈出的處理WM_CREATE消息MessageBox也是一個窗口,但它屬于我們的進程。每個窗口都有一個消息循環(huán),但是消息函數(shù)一個進程卻只有一個,當MessageBox的窗口關(guān)閉時,它的窗口處理函數(shù)也調(diào)用PostQuitMessage(0)發(fā)送了一個WM_QUIT消息。它的消息循環(huán)中GetMessage接收到WM_QUIT消息后返回并退出。而這個消息又會被我們的消息循環(huán)捕獲到,但是由于它不是我們的窗口發(fā)出的消息,所以不會導(dǎo)致我們的GetMessage返回結(jié)束循環(huán),反而被傳給我們的窗口處理函數(shù)匯總進行處理,所以出現(xiàn)了上面截圖顯示的對話框。

五、WM_SYSCOMMAND消息

? ? ? ? 系統(tǒng)命令消息,當我們點擊最大化、最小化和關(guān)閉命令時會觸發(fā)這個消息(這么說來點擊關(guān)閉按鈕時會同時觸發(fā)WM_DESTROY和WM_SYSCOMMAND兩個消息哦)。它的wParam參數(shù)攜帶了具體的窗口操作:

關(guān)閉:SC_CLOSE

最大化:SC_MAXIMIZE

最小化:SC_MINIMIZE

? ? ? ? 這里只列舉了三種常見的WM_SYSCOMMAND攜帶的參數(shù)宏,其它的可以參照MSDN。WM_SYSCOMMAND的lParam攜帶的是產(chǎn)生該消息的鼠標的位置,位置的X和Y坐標分別被存放在lParam的低位和高位字中,我們用下面的代碼來驗證在窗口最大化時,我們鼠標的位置:

case?WM_SYSCOMMAND:  	{  		if?(wParam?==?SC_MAXIMIZE)  		{  			short?x?=?LOWORD(lParam);  			short?y?=?HIWORD(lParam);  			char?buf[256];  			sprintf(buf,?"窗口最大化,x坐標:%d,y坐標:%d",?x,y);  			MessageBox(NULL,?buf,?"消息處理",?MB_OK);  		}  	}

? ? ?

? ? ? ? 當我們點擊窗口的最大化按鈕時,出現(xiàn)下面的提示:

Win32 SDK基礎(chǔ)(十)之詳解幾種常見的Windows消息處理的示例代碼

六 WM_SIZE消息

? ? ? ? 每當我們調(diào)整窗口的大小時,都會觸發(fā)WM_SIZE消息。它的wParam參數(shù)攜帶的是該消息產(chǎn)生的原因:

? ? ? ??SIZE_RESTORED —— 重新調(diào)整窗口大小

? ? ? ??SIZE_MAXIMIZED —— 最大化顯示

? ? ? ? SIZE_ MINIMIZED —— 最小化顯示

? ? ? ? 其他參數(shù)宏詳見MSDN

? ? ? ? 它的lParam參數(shù)攜帶的是重新調(diào)整大小后的窗口的高和寬,其中低字節(jié)代表寬,高字節(jié)代表高,這里我們通過代碼驗證,當窗口最大化后窗口的高和寬:

case?WM_SIZE:  	{  		if?(wParam?==?SIZE_MAXIMIZED)  		{  			short?width?=?LOWORD(lParam);  			short?hight?=?HIWORD(lParam);  			char?buf[256];  			sprintf(buf,?"窗口最大化,高度:%d,寬度:%d",?hight,?width);  			MessageBox(NULL,?buf,?"消息處理",?MB_OK);  		}  	}

? ? ? ? 運行程序,最大化時可以顯示最大化后的窗口高度和寬度:

Win32 SDK基礎(chǔ)(十)之詳解幾種常見的Windows消息處理的示例代碼

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點贊7 分享