Win32消息循环机制等【转载】http://blog.csdn.net/u013777351/article/details/49522219 (6)

WinMain()调用完ShowWindow后,还需要调用函数UpdateWindow,最终把窗口显示了出来。调用函数UpdateWindow将产生一个WM_PAINT消息,这个消息将使窗口重画,即使窗口得到更新.—这是程序第一次调用了这条消息。

为重新显示非法区域,Windows就发送WM_PAINT消息实现。要求Windows发送WM_PAINT的情况有改变窗口大小,对话框关闭,使用了UpdateWindows和ScrollWindow函数等。这里注意,Windows并非是消息WM_PAINT的唯一来源,使用InvalidateRect或InvalidateRgn函数也可以产生绘图窗口的WM_PAINT消息……

通常情况下用BeginPaint()来响应WM_PAINT消息。如果要在没有WM_PAINT的情况下重画窗口,必须使用GetDC函数得到显示缓冲区的句柄。这里面不再扩展。详细见MDSN。

这个BeginPaint函数会执行准备绘画所需的所有步骤,包括返回你用于输入的句柄。结束则是以EndPaint();

在调用完BeginPaint之后,WndProc接着调用GetClientRect:

GetClientRect(hwnd,&rect);

第一个参数是程序窗口的句柄。第二个参数是一个指针,指向一个RECT类型的结构。查MSDN,可看到这个结构有四个成员。

WndProc做了一件事,他把这个RECT结构的指针传送给了DrawText的第四个参数。函数DrawText的目的就是在窗口上显示一行字—-“你好,欢迎你来到VC之路!”,有关这个函数的具体用法这里也没必要说了吧。

关于WM_DESTROY

这个消息要比WM_PAINT消息容易处理得多:只要用户关闭窗口,就会发送WM_DESTROY消息(在窗口从屏幕上移去后)。

程序通过调用PostQuitMessage以标准方式响应WM_DESTROY消息:

PostQuitMessage (0) ;

这个函数在程序的消息队列中插入一个WM_QUIT消息。在(四)创建消息循环中我们曾有这么一段话:

消息循环以GetMessage调用开始,它从消息队列中取出一个消息:

在接收到除WM_QUIT之外的任何一个消息后,GetMessage()都返回TRUE。如果GetMessage收到一个WM_QUIT消息,则返回FALSE,如收到其他消息,则返回TRUE。因此,在接收到WM_QUIT之前,带有GetMessage()的消息循环可以一直循环下去。只有当收到的消息是WM_QUIT时,GetMessage才返回FALSE,结束消息循环,从而终止应用程序。

Win32 API主消息循环的两种处理方法

主要介绍了Win32 API主消息循环的两种处理方法:使用GetMessage方法构造主消息循环、使用PeekMessage方法构造主消息循环。

使用GetMessage方法构造主消息循环

一般应用程序都使用用GetMessage方法构造主消息循环,该方法是获得一条线程 的消息。对于VS2005自动生成的Win32 Windows程序上面有些不足。 
因为VS2005生成的主消息循环如下;

// Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } }

简单看看的确没有问题,但是当我们去查阅MSDN文档看到GetMessage消息时候可以看到这样一段

If there is an error, the return value is -1.

所以我们应该把上面这个主循环修改为下面这样的形式,增加一个临死变量。

// Main message loop: BOOL bRet;//临时变量,存储GetMessage方法返回值 // Main message loop: while ((bRet = GetMessage(&msg, NULL, 0, 0))!=0) { if(bRet==-1) { //表示GetMessage获得的信息有错误 } else { TranslateMessage(&msg); DispatchMessage(&msg); } }

(2)使用PeekMessage方法构造主消息循环 
PeekMessage常常用于Windows开发游戏中,PeekMessage在处理获得消息时候和GetMessage一样,关键不同的是PeekMessage在没有消息处理的时候还会继续保持循环激活状态,并且继续占用资源。

// Main message loop: while (true) { if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if(msg.message == WM_QUIT) { break; } else //表示GetMessage获得的信息有错误 { TranslateMessage(&msg); DispatchMessage(&msg); } } else { //循环处理的函数 } } Win32消息循环是一个死循环吗?如果是消息循环为什么不会耗尽CPU?

1:Win32是个多任务抢占式操作系统,每运行一个程序(可执行文件),操作系统就创建一个进程和主线程,把程序的代码和数据映射到该进程地址空间,并为每个线程分配了一个时间片,一个线程放弃CPU的处理权有、可以是时间片完了,I/O请求,还有就是程序自己要求放弃处理权,而GetMessage函数是一个阻塞函数,也就是你调用他就相当于主动放弃了CPU,引起线程上下文切换,从而其他线程可以得到CPU,但该函数会在有消息的时间激活而继续执行。如果你是获取消息用PeekMessage函数,那么你打开任务管理器,才知道什么叫做真正的浪费资源;

2:

while(1) { id=getMessage(...); if(id == quit) break; translateMessage(...); }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgzwff.html