Qt和Windows消息通信机制
Qt
Qt是以事件驱动的UI工具集。 大家熟知Signals/Slots在多线程的实现也依赖于Qt的事件处理机制。
在Qt中,事件被封装成一个个对象,所有的事件均继承自抽象类QEvent. 接下来依次谈谈Qt中有谁来产生、分发、接受和处理事件:
1、谁来产生事件: 最容易想到的是我们的输入设备,比如键盘、鼠标产生的
keyPressEvent,keyReleaseEvent,mousePressEvent,mouseReleaseEvent事件(他们被封装成QMouseEvent和QKeyEvent),这些事件来自于底层的操作系统,它们以异步的形式通知Qt事件处理系统,后文会仔细道来。当然Qt自己也会产生很多事件,比如QObject::startTimer()会触发QTimerEvent. 用户的程序可还以自己定制事件。
2、谁来接受和处理事件:答案是QObject。在Qt的内省机制剖析一文已经介绍QObject 类是整个Qt对象模型的心脏,事件处理机制是QObject三大职责(内存管理、内省(intropection)与事件处理制)之一。任何一个想要接受并处理事件的对象均须继承自QObject,可以选择重载QObject::event()函数或事件的处理权转给父类。
3、谁来负责分发事件:对于non-GUI的Qt程序,是由QCoreApplication负责将QEvent分发给QObject的子类-Receiver. 对于Qt GUI程序,由QApplication来负责。
Qt进入QApplication的event loop,经过层层委任,最终QEventloop的processEvent将通过与平台相关的QAbstractEventDispatcher的子类QEventDispatcherWin32获得用户的用户输入事件,并将其打包成message后,通过标准Windows API ,把消息传递给了Windows OS,Windows OS得到通知后回调QtWndProc,
Windows
https://www.jianshu.com/p/5fd5bdaac69c---MFC消息机制

Windows:是事件驱动(event-driven),应用程序不是通过显示的函数调用来获取输入,而是等待系统将输入传递给它们。
系统将属于某个应用程序的输入传递给这个应用程序窗口。每一个窗口都有一个叫“窗口过程(window proceduce)”的函数,当窗口有输入的时候系统便会自动调用窗口函数,窗口函数处理结束后将控制权返回给系统。如果一个顶层窗口几秒内没有消息响应,系统默认无响应。
Windows消息(Windows Messages)
系统通过消息(message)的方式将输入传递给“窗口过程”,应用程序和系统都可以产生消息。系统会在每个输入事件产生消息(例如,用户敲击键盘,移动鼠标,点击控件)。系统也会为由应用程序引起的系统改变(像应用程序改变了系统的字体资源池或者调整了窗口大小)而产生消息。应用程序产生的消息,可以传递给自己的窗口以执行一些任务,也可以用来与其他应用程序的窗口通信。
系统发送给“窗口过程”的消息包含4个参数:一个窗口句柄,一个消息标识,以及两个称为消息参数(message parameters)的参数值。
- 窗口句柄标识了这个消息是要传递给哪个窗口的,系统通过它来决定调用哪个“窗口过程”。
- 消息标识是一个用来表示消息的用途的常量。“窗口过程”收到消息后,通过消息标识来决定如何处理消息。例如,消息标识WM_PAINT告诉“窗口过程”窗口客户区改变了,窗口需要重绘。
- 消息参数指出“窗口过程”处理消息使用的数据或数据地址,参数值的意义决定于消息标识。参数值可以是整数,位掩码,指向结构体的指针等。当消息不需要参数值时,参数值通常设置为NULL。“窗口过程”必须通过消息标识来确定如何解析消息参数。
-
从消息队列中取出一个消息之后,应用程序可以调用DispatchMessage来引导系统将消息传递给“窗口过程”。
一个简单的消息循环函数需要调用GetMessage, TranslateMessage, and DispatchMessage。注意,GetMessage如果发生错误会返回-1,因此需要特别判断。
MSG msg;
BOOL bRet;
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
“窗口过程”(Window Procedure)
“窗口过程”是接收并处理所有传递给窗口的消息的函数。每个窗口类(Windows Class)都有一个“窗口过程”,每个用窗口类创建的窗口都使用相同的“窗口过程”来处理消息。
系统通过把消息数据以参数的形式传给“窗口过程”来传递消息给“窗口过程”,接着“窗口过程”根据消息执行相应的操作。“窗口过程”检查消息标识,在处理消息时使用消息参数指示的信息。
“窗口过程”一般不会忽略消息,如果它不处理消息,则必须把消息返回给系统以进行默认处理,这是通过调用DefWindowProc来实现的。DefWindowProc进行默认处理并返回结果,“窗口过程”必须把这个结果返回。大部分“窗口过程”只处理一些消息,通过调用DefWindowProc把其它的消息都交给系统处理。
因为一个“窗口过程”是被所有由同一个窗口类创建的窗口共用的,所以它能够处理几种不同窗口的消息。“窗口过程”可以通过检查消息中的窗口句柄来识别消息所影响的窗口。更多信息见Window Procedures主题。