正文

Windows程序设计[3]-消息与消息循环2006-03-25 14:48:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/rickone/11378.html

分享到:

今天有朋友提的意见让我感触很深,说写BLOG要多一些‘有趣’多一些funny,回头看看我写的东西,大部分都给人严肃、枯燥的感觉,我在这里免费拿了一个BLOG,而这个BLOG却不完全属于我,他属于千千万万在使用网络的学者!所以,我有责任,而这个责任就是不浪费读者的时间。

不说废话了,同样今天继续写的将是Win32程序设计中的Windows消息机制。

消息就是一个用户对电脑的‘请求’。我想放点音乐,我就对电脑大声喊:“Hey!伙计,放点音乐吧!”,结果显然是我将被冷落。我不能这样发‘请求’,我应该用电脑懂的语言,再用‘友好’的方式请求。我只能选择按鼠标或者敲键盘,于是消息便从这里产生了。

消息的原来形式是你手指的‘动能’,结果导致了某些特定电信号,电信号再到达计算机电路系统,系统再将信号反应到操作系统,操作系统再将信号变成消息形式发到线程,到线程的消息再进入消息队列排队,最终到达消息处理函数,此时电脑就明白你的请求是什么意思了,再通过消息处理函数工作。

与其说消息是发到电脑,还不如说是发到了线程,如果没有线程在那里‘听’,你发再多的消息,也不会有反应。

线程要怎么‘听’,还得从GUI入口函数说起。

一个GUI用户程序的入口函数将不是main(),而是WinMain(),原形是:
int APIENTRY WinMain(
   HINSTANCE hInstance,
   HINSTANCE hPrevInstance,
   LPSTR lpCmdLine,
   int nCmdShow)
{
}
APIENTRY是__stdcall的宏,意思是用Windows标准调用方式,hInstance是本身的实例句柄,lpCmdLine是命令行参数。

光一个WinMain()是不会等待消息的(‘听’),我可以加入一个::MessageBox();简单的弹一个窗口出来,然后默默的结束。

问题是我们需要先建一个窗体出来,建主窗体的过程比较复杂,详细的情况参看书本。过程大致是,先设置窗体句柄的参数,然后建立窗体,然后注册窗体,最后更新窗体。

完了之后这个窗体就会‘挂’在桌面上,‘等待’用户发消息。

事实上,‘等待’还需要‘消息循环’,如果WinMain()进程一旦结束,那窗体挂着也没用,消息还没到达就自己退出了。

所以必须让主线程‘挂’起来,同时‘等待’消息的到达。

接下来就进入‘无限’的‘消息循环’:
代码像这样:
MSG msg;
while(::GetMessage(&msg,NULL,0,0))
{
  ::TranslateMessage(&msg);
  ::DispatchMessage(&msg);
}

这里的无限循环,不是说这段代码将一直运行,事实上::GetMessage()将使这个线程挂起,只有当消息到来时再被再次激活。

::DispatchMessage()将把消息发送到消息处理函数,或者叫窗口函数,它是窗口建立的时候指定的,形如:
LRESULT CALLBACK MainWndProc(HWND,UINT,WPARAM,LPARAM);
第二个参数就是消息,可以理解为大的消息,后面两个参数是附带的消息参数,而第一个是所属的窗口句柄。

无限的消息循环使主线程一直在等待消息的到达,然后再通知消息处理函数,直到得到一个WM_QUIT消息返回0才结束程序。

另外有两个发送消息的API函数:
::SendMessage();参数同消息处理函数的参数。
::PostMessage();
前者是直接的调用消息处理函数,同时自己挂起,等待消息处理的结束,再继续运行。
而后者是直接向句柄所在消息队列中发一个消息,同时继续运行。

阅读(6155) | 评论(5)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册