如何在引擎盖下实现Win32事件驱动编程?

Fre*_*ool 11 windows winapi message-queue event-driven

在Win32 C++应用程序中,我们启动一个消息循环,从队列中获取消息,转换它们然后调度它们.最终,每条消息都到达我们的WndProc,在那里可以处理相关的事件.

我明白那一部分.我不明白的是介于两者之间.特别:

  1. 不同类型的OS中断处理程序必须将消息放入所述"消息队列"中,但该队列驻留在进程地址空间中的哪个位置?它是如何暴露给中断处理程序代码的?
  2. "翻译"消息意味着什么?TranslateMessage()真正的呼吁是什么?
  3. 一旦被调度DispatchMessage(),在到达我的WndProc之前,消息会在什么地方摆动(即操作系统用它做什么)?

如果有人知道上述的答案,请满足我的好奇心.谢谢.

Ste*_*fan 6

OS维护消息队列,在其中放置事件(例如,来自中断或其他源).然后,它将来自该队列的消息发送到所有窗口,具体取决于消息(例如,它不会将密钥消息发送到没有焦点的窗口).

应用程序可以拥有自己的队列来处理消息.这些队列是根据请求创建的(仅在需要时).

翻译消息用于创建不是"真实"事件的消息.例如,WM_CONTEXTMENU消息是通过鼠标右键单击或上下文菜单键或shift-F10进行"翻译"的.WM_CHAR是从WM_KEYDOWN消息转换而来的.当然,许多其他消息都是"翻译"的.

消息将发布到应该接收它的每个窗口.操作系统根据消息的类型决定窗口是否应该接收该消息.大多数消息都由系统等待,即,在窗口处理消息之前,消息不会发布到另一个窗口.这对广播消息有很大影响:如果在处理该消息时一个窗口没有返回,则队列被阻止,其他窗口将不再接收该消息.

  • 这都错了.正确的部分是正确的,只有当问题是关于Win16时,整个操作系统和应用程序在一个线程上合作安排. (3认同)

Rei*_*man 6

这取决于您的邮件的发送方式以及邮件的处理方式.

当您调用SendMessage时,如果目标窗口由当前线程拥有,则该调用将绕过该窗口的消息队列,并且窗口管理器直接调用目标窗口上的windowproc.如果目标窗口由另一个线程拥有,则窗口管理器有效地调用PostMessage并泵送窗口消息,直到目标窗口从窗口proc返回.

当您调用PostMessage时,窗口管理器会封送消息参数并将相应的对象插入到目标窗口的消息队列中.当它下次调用GetMessage时,消息将从消息队列中删除.

窗口管理器还从输入设备(键盘和/或鼠标)注册原始输入事件,并为这些输入事件生成消息.然后它会根据需要在队列中插入这些消息(输入事件的处理很复杂,因为它取决于窗口的消息队列中已有的消息).

正如Stefan指出的那样,TranslateMessage只是转换加速键 - 例如它将键序列转换为WM_COMMAND消息.