日期:2014-05-17  浏览次数:20785 次

细说UI线程和Windows消息队列

Windows应用程序中,窗体是由一种称为“ UI线程( User Interface Thread)”的特殊类型的线程创建的。

?????? 首先, UI线程是一种“线程”,所以它具有一个线程应该具有的所有特征,比如有一个线程函数和一个线程 ID

?????? 其次,“ UI线程”又是“特殊”的,这是因为 UI线程的线程函数中会创建一种特殊的对象——窗体,同时,还一并负责创建窗体上的各种控件。

?????? 窗体和控件大家都很熟悉了,这些对象具有接收用户操作的功能,它们是用户使用整个应用程序的媒介,没有这样一个媒介,用户就无法控制整个应用程序的运行和停止,往往也无法直接看到程序的运行过程和最终结果。

?????? 那么,窗体和控件又是如何作到对用户操作进行响应的呢?这一响应是不是由窗体和控件自己“主动”完成的?

?????? 换句话说:

?????? 窗体和控件具不具备独立地响应用户操作(比如键盘和鼠标操作)的功能?

??????

?????? 答案是否定的。

?????? 那就奇怪了,比如我们用鼠标点击了一个按钮,并且看到它“陷”下去了,然后又还原,之后,我们确实看到了程序执行了此按钮所对应的任务。难道不是按钮来响应用户操作的吗?

?????? 这实际上是一个错觉。这个错觉产生的根源在于不了解 Windows内部的运作机理。

?????? 简单地说,窗体和控件之所以能响应用户操作,关键在于负责创建它们的 UI线程拥有一个“消息循环( Message Loop ”。这个消息循环由线程函数负责启动,通常具有以下的“模样”(以 C++代码表示):

?

?

??? MSG msg;?//代表一条消息

??? BOOL bRet;

??? // UI线程消息队列中取出一条消息

??? while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)

??? {

??? ??? if (bRet == -1)

??? ??? {

??????? ??? //错误处理代码,通常是直接退出程序

??? ??? }

??? ??? else

??? ??? {

??????? ??? TranslateMessage(&msg); //转换消息格式

??????? ??? DispatchMessage(&msg);?//分发消息给相应的窗体

??? ??? }

??? }

?

?

???? 可以看到, 所谓消息循环,其实就是一个While循环语句罢了。