windows消息机制的有趣发现(二)

3.一个有窗口和窗口过程函数但没有消息循环的程序

一个程序,如果我们创建了窗口,也定义了窗口过程函数,但是没有建立消息循环会怎样呢?我们在win32控制台项目下编写如下代码:

#include <windows.h>

#define WM_TEST 10000



LRESULT 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函数中创建完窗口后也没有建立消息循环,运行程序后会发生什么呢?

windows消息机制的有趣发现(二)

运行发现,窗口确实被创建出来了。但是鼠标移动上去就会发现该窗体如图假死一样没有了响应。这是因为包括自绘消息WM_PAINT在内的所有消息都被放入了线程的消息队列里,但是我们没有消息循环!没有取出消息队列中的消息,更没有处理这些消息,我们连窗口过程中对应WM_PAINT的消息处理函数都没有。界面自然就假死了。

4.SendMessage和PostMessage消息的另一个区别

之前我写过一篇博文说过SendMessage和PostMessage的却别在于SendMessage要等消息被处理完成后才返回,如果调用SendMessage后该消息一直未处理完,SendMessage会一直阻塞到处理完为止。而PostMessage不会阻塞,不等处理结果直接返回。实际上他们还有一个区别:PostMessage发送的消息会进入消息队列等待提取,而SendMessage发送的消息不进消息队列,直接交给窗口过程函数处理。为了验证这个说法,我们编写如下代码:

#include <windows.h>

#define WM_TEST 10000



LRESULT 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。

windows消息机制的有趣发现(二)windows消息机制的有趣发现(二)

运行后发现,纵使我们创建的窗体依然是假死状态,仍然弹出了MessageBox,并且SendMessage的返回值i为50。说明我们在窗口过程函数WndProc中定义的对WM_TEST消息的处理代码成功执行!注意,我们这个程序中是没有消息循环的,但是我们用SendMessage发送的消息还是被窗口过程函数WndProc处理了。

我们把SendMessage改为PostMessage再试。运行后发现没有弹出MessageBox。为什么呢?因为PostMessage发送的消息要进消息队列,但我们没有消息循环,没有用GetMessage之类的函数从消息队列中取消息,更没有用DispatchMessage分发消息,所以我们用PostMessage发送的WM_TEST还在消息队列里待着呢。窗口过程函数WndProc中的代码没有执行。

这就证明了SendMessage和PostMessage的另一个不同之处:SendMessage发送的消息直接交给对应的窗口过程函数处理,不进消息队列,而PostMessage发送的消息要进消息队列等待分发、处理。

 

你可能感兴趣的:(windows)