【问题标题】:WindowProc Invocation TimingWindowProc 调用时序
【发布时间】:2015-10-01 15:18:07
【问题描述】:

我是 win32 消息的新手。我想知道,当 WindowProc 正在处理一条消息时,它是否可能被中断以处理另一条消息?以下面的例子为例,如果 [A] 和 [B] 都被执行,WindowProc 是否有可能被中断来处理 [A] 和[乙]?如果可以的话,有什么特殊情况可以做到吗?

LRESULT CALLBACK WindowProc(
  _In_ HWND   hwnd,
  _In_ UINT   uMsg,
  _In_ WPARAM wParam,
  _In_ LPARAM lParam
{
    ...
    case WM_ACTIVATEAPP:

            if (wParam == FALSE)
            {
                // [A] Do something that would trigger a WM_ACTIVATE or WM_ACTIVATEAPP message to be queued to the message queue
                ShowWindow(hwnd, SW_MINIMIZE);

                // [B] Modify Window Styles
                SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_CLIENTEDGE);
            }

            break;
    ...
}

感谢任何cmets!

【问题讨论】:

  • 你喜欢快乐的答案。但是,是的,绝对是在 sn-p 中。 ShowWindow() 导致将 WM_SHOWWINDOW 消息发送到窗口。因此,您的 WM_ACTIVATEAPP 消息处理程序不可避免地会被“中断”,并且您的 WindowProc() 函数会递归执行。这种重新进入会带来很多麻烦,包括但不限于此网站的名称。打破重入的通用技术是使用 PostMessage 向自己发送消息。稍后,当您的 UI 线程处于安全位置时,您会得到它。
  • 嗯。那么您是说处理程序有可能被中断以执行[A],去处理不同的消息,然后返回执行[B]?这似乎与其他 cmet 形成对比,后者表明新消息在 [A] 和 [B] 都被执行之前不会触发处理程序的调用。
  • 我不只是说它是可能的,我是说它必须以这种方式工作。您接受的答案非常不准确,SendMessage() 生成的消息永远不会放入队列中,而是直接发送到窗口过程。像 WM_SHOWWINDOW 和 WM_ACTIVATEAPP。只有 PostMessage() 产生的消息进入队列。顺便说一句,调试器很容易自己发现。只需在 ShowWindow 调用上设置一个断点,当它命中时在 WindowProc 上设置一个断点。完成此测试后,您可能会写出更好的答案。
  • 谢谢,我试试看。是否有任何 Windows API 可以在其上产生窗口消息的资源,如果是,它是使用直接调用(即 SendMessage)还是排队调用(即 PostMessage)?例如,如何找出 ShowWindow 可以直接生成 Window 消息?希望这不是反复试验......
  • Hans 有点意思:如果你递归调用一个 WindowProc(甚至是间接调用),那么你确实有一个可重入的 WindowProc。但是 Windows 不能也不会在任意点暂停您的 `WindowProc`。 Windows 怎么会知道什么是安全时刻?可能有各种互斥锁被锁定。当您实际上调用 ShowWindow 时,Windows 可以假定它是安全的,因为它是单线程的:在 ShowWindow 返回之前,您的代码不会运行。

标签: c++ windows message-queue


【解决方案1】:

没有。这就是 GUI 线程 的意义所在——它是一个线程一次做一件事。如果您正在处理消息,则不会调用 GetMessage

【讨论】:

  • 但是如果您在消息处理期间发送消息,那实际上会递归调用您的消息过程,不是吗? (根据 Hans 的问题。)
【解决方案2】:

系统将从不在处理另一条消息时调用此回调函数,这仅仅是因为所有消息都被放入队列中并且(您的代码或您使用的框架,例如MFC ) 一个一个地出队,没有重叠。除非处理完一条消息,否则控件不会返回到出队块。
事实上,您可以安全地将window 代码视为单线程。如果您有多个窗口在单个应用程序中运行,它们都序列化并且仍在单个线程中运行。

事实上,如果您希望彼此并行运行窗口(或工作程序),则需要创建单独的线程。

【讨论】:

  • 对于“并行运行你的窗口”这一点,这并没有改变这样一个事实,即对于任何给定的窗口,它的所有消息仍然是连续处理的,没有任何重叠,对吗?
  • 正确。除非您显式创建多个线程,否则您的 Windows 程序将始终作为单线程应用程序运行。这里的“显式”是指您自己创建线程或使用为您执行此操作的框架(例如 - 从网络摄像头等捕获设备检索帧样本可以异步完成,并且在这种情况下,回调将由系统调用而不考虑在你的主线程中执行任何其他代码)
猜你喜欢
  • 2013-01-16
  • 1970-01-01
  • 1970-01-01
  • 2010-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-26
  • 1970-01-01
相关资源
最近更新 更多