全球拦截窗口移动

时间:2009-08-25 11:32:55

标签: c++ winapi

我无法使全局系统挂钩工作。我想尽可能早地在窗口移动时收到通知,并更改窗口大小。这意味着CBT钩子HCBT_MOVESIZE不会剪切它,它只会在窗口移动后发生。我想挂钩窗口的实际移动,并能够在移动过程中更改窗口大小。

钩子是从DLL设置的,回调函数在该DLL中。这就是我尝试过的。

  • WH_CALLWNDPROC。移动窗口时会发出警报(从其他应用程序收到窗口WM_MOVING),但我无法更改消息内容。
  • WH_CALLWNDPROCRETWH_CALLWNDPROC相同。
  • CBT hook HCBT_MOVESIZE。事件发生得很晚。
  • WH_GETMESSAGE。永远不会收到WM_MOVEWM_MOVINGWM_WINDOWPOSCHANGING。这个钩子可以让我改变消息。

更新:Windows事件挂钩似乎允许我捕获它:

hWinEventHook = SetWinEventHook(EVENT_SYSTEM_MOVESIZESTART,    
    EVENT_SYSTEM_MOVESIZEEND, NULL, WinEventProc, 
    0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);

然而,这会产生一个不同的问题:使用SetWindowPos()更改窗口大小不起作用(它会改变大小,但会立即更改回以前的大小),即使我使用{{1} }。想法?

更新2 :子类似乎可行,但Visual Studio在每个程序运行后崩溃(许多其他窗口也是如此)。如果我放置断点并遍历“unsubclassing”,它会很好用,但是当我让程序自行运行时却不行。想法?

我有一个CBT钩子(它来自前面),每当SWP_NOSENDCHANGING被发送到一个新窗口时,我使用HCBT_ACTIVATE删除任何先前的子类(这必须在64位上运行) ()),然后子类新窗口。如果我在任何地方放置断点,并在断开时立即恢复会话,一切正常。但是,当我没有任何断点时,Visual Studio会在程序退出时崩溃。

2 个答案:

答案 0 :(得分:1)

嗯,我认为HCBT_MOVESIZE正是你想要的,因为MSDN对CBT钩子说了这个:

The system calls this function before activating, creating, destroying,
minimizing, maximizing, moving, or sizing a window.

,特别是:

HCBT_MOVESIZE
    A window is about to be moved or sized.

(这些引用取自 http://msdn.microsoft.com/en-us/library/ms644977%28VS.85%29.aspx

...所以我想你会及时得到HCBT_MOVESIZE电话。处理HCBT_MOVESIZE的钩子函数也允许返回一个整数,以便系统可以确定是允许还是应该阻止操作。因此,假设HCBT_MOVESIZE挂钩应该有一个阻止操作的选项,我会说在移动事件发生之前调用它。

你真的确定在移动事件后,钩子函数被称为吗?如果对钩子函数中的特定句柄执行GetWindowRect调用,返回的rect是否等于传递给钩子函数的矩形?

答案 1 :(得分:1)

钩子很重。你只想在必要的时候使用它们。

也就是说,您可以使用其中一个基本钩子作为进入流程的方法。一旦进入该过程,您可以子类化您感兴趣的窗口并处理子类proc中的大小调整消息,而不是尝试捕获钩子级别的所有内容。

根据您为响应调整大小而想要做的事情,您可能需要进行一些进程间通信。