0

我想“保护”某个窗口不被关闭。所以我想挂钩 WM_CLOSE、WM_DESTOY 或 WM_QUIT。这就是我试图这样做的:

LRESULT CALLBACK WindowHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode >= 0)
    {
        MSG* msg = (MSG*)lParam;
        //if (msg->hwnd == GetForegroundWindow())
        {
            if (msg->message == WM_CLOSE || msg->message == WM_QUIT || msg->message == WM_DESTROY)
            {
                //MessageBox(0, "TEST", "", 0);
                msg->message = 0;
                CallNextHookEx(hMsg, nCode, (WPARAM)NULL, (LPARAM)NULL);
                return TRUE;
            }
        }
    }

    CallNextHookEx(hMsg, nCode, wParam, lParam);
}

我试过:

  • 返回 TRUE 或 FALSE
  • 使用 NULL 作为 LPARAM 调用 CallNextHookEx 或将 msg->message 编辑为 0

另外我注意到,如果我挂钩 WH_GETMESSAGE 它不会“阻止”消息循环。但它通过挂钩 WH_CALLWNDPROC 来实现。当 msg->message 等于 WM_CLOSE 时,我通过提示消息框发现了这一点。

预先感谢,问候。

4

2 回答 2

1

与其尝试安装挂钩,不如将窗口子类化并让您的子类 WndProcWM_CLOSE在转发所有其他消息时忽略。

你不能也不应该试图停止WM_QUIT。正如罗德里戈指出的那样,你无能为力WM_DESTROY。那时,DestroyWindow已经调用了,无论您喜欢与否,您的窗口都会消失。

于 2012-12-17T14:18:35.163 回答
1

WH_GETMESSAGE 为从消息队列中检索到的消息安装挂钩。它确实允许您修改消息。但问题是 WM_CLOSE 不是用 PostMessage() 发送到消息队列,而是用 SendMessage() 发送的。这个钩子看不到。

WH_CALLWNDPROC 安装一个在窗口过程被调用之前运行的钩子。这将允许您查看 WM_CLOSE。但是,您不能修改消息或使其消失。

没有钩子可以让你做你想做的事。相反,您必须对窗口过程进行子类化。以便在窗口自己的过程之前调用您自己的自定义窗口过程。现在您可以通过不调用旧的窗口过程来简单地过滤 WM_CLOSE。

请注意,您仍然需要与 SetWindowsHookEx() 提供的相同类型的管道,您仍然需要将带有窗口过程的 DLL 注入进程中。最好的方法是仍然使用 SetWindowsHookEx 来使用一个不会做任何事情的虚拟钩子来完成它。

于 2012-12-17T15:03:32.090 回答