【发布时间】: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