“跨进程子类化”的问题
两个问题。
1)我知道这一定是预期的结果,但也许有人可以告诉我我做错了什么;我试图在全局钩子中对所有窗口类进行子类化,它可以工作,只是我无法像我应该的那样关闭商店,并且当程序最初注册钩子取消注册钩子并退出时,子类化的应用程序开始崩溃。
这是我尝试执行的方法。
// stores original wndprocs. In the hook dll, outside the shared memory.
map<HWND, WNDPROC> origWndProcs;
// in an EnumWindows callback, executed for all HWND's, also in the hook dll (UWM_REMOVE_HOOK is a registered unique message)
SendMessageTimeout(hWnd, UWM_REMOVE_HOOK, 0, 0, SMTO_ABORTIFHUNG | SMTO_NORMAL, 15000, res);
// Still in the same hook, in the subclassing wndproc..
if (msg == UWM_REMOVE_HOOK) {
if (origWndProcs.find(hwnd) != origWndProcs.end()) {
SetWindowLongPtr(hwnd, GWL_WNDPROC, (LONG_PTR)origWndProcs[hwnd]);
}
}
// clears the hook..
__declspec(dllexport) BOOL ClearHooks(HWND hWnd) {
BOOL unhooked = UnhookWindowsHookEx(hook) &&
UnhookWindowsHookEx(kb_hook) &&
UnhookWindowsHookEx(mouse_hook) &&
UnhookWindowsHookEx(cbt_hook);
if(unhooked)
hWndServer = NULL;
return unhooked;
}
在 DllMain 中,我不对 DLL_PROCESS_DETACH 执行任何操作。相反,ClearHooks() 是从最初注册钩子的程序中调用的,并且仅在钩子发送一条消息表明它已执行 EnumWindows 操作(恢复原始 wndprocs,见上文)之后才调用。
我在 WndProc 挂钩中对窗口进行子类化;所有接收消息且其当前 wndproc 不是 dll 中的窗口的可见窗口都会被子类化。
基本上所有(据我所知)应用程序在退出时都会崩溃,尽管 Windows 似乎确实将 wndproc 设置回了被替换时的状态。有人知道我可能做错了什么吗?
2)我需要它来拦截WM_MINMAXINFO并在窗口最大化时修改窗口最大大小。不幸的是,我无法在 dll 中执行此操作,但我必须与程序通信才能获取大小信息。那么,与该窗口对话的最佳方式是什么?我需要它传回一些信息,以便我可以修改原始 WM_MINMAXINFO 消息附带的结构。 WM_COPYDATA 中的结构会保留其数据直到对 SendMessageTimeout 的调用返回吗?
谢谢
Two questions.
1) I understand this must be an expected outcome but maybe someone can tell me what I'm doing wrong; I'm trying to subclass all window classes in a global hook and it works except that I'm not able to close shop as I should and when the program initially registering the hook unregisters the hook and exits, subclassed applications start crashing.
Here's how I'm trying to do it..
// stores original wndprocs. In the hook dll, outside the shared memory.
map<HWND, WNDPROC> origWndProcs;
// in an EnumWindows callback, executed for all HWND's, also in the hook dll (UWM_REMOVE_HOOK is a registered unique message)
SendMessageTimeout(hWnd, UWM_REMOVE_HOOK, 0, 0, SMTO_ABORTIFHUNG | SMTO_NORMAL, 15000, res);
// Still in the same hook, in the subclassing wndproc..
if (msg == UWM_REMOVE_HOOK) {
if (origWndProcs.find(hwnd) != origWndProcs.end()) {
SetWindowLongPtr(hwnd, GWL_WNDPROC, (LONG_PTR)origWndProcs[hwnd]);
}
}
// clears the hook..
__declspec(dllexport) BOOL ClearHooks(HWND hWnd) {
BOOL unhooked = UnhookWindowsHookEx(hook) &&
UnhookWindowsHookEx(kb_hook) &&
UnhookWindowsHookEx(mouse_hook) &&
UnhookWindowsHookEx(cbt_hook);
if(unhooked)
hWndServer = NULL;
return unhooked;
}
In DllMain I don't do anything on DLL_PROCESS_DETACH. Instead, ClearHooks() is called from the program originally registering the hooks and there only after the hook has sent a message signalling that it has executed the EnumWindows operation (restores original wndprocs, see above).
I subclass windows in a WndProc hook; all visible windows that receive a message and whose current wndproc is not the one in the dll, are subclassed.
Basically all (as far as I can tell) applications crash on exit despite the fact that windows do seem to get the wndproc set back to what it was when it was replaced. Anyone have a clue what I might be doing wrong?
2) I need this to intercept WM_MINMAXINFO and modify window maxsize whenever a window is maximized. Unfortunately I can't do this in the dll but I have to talk with a program to get the size info. So, what's the best way to talk to that window; I need it to pass back some info so I can modify the structure that came with the original WM_MINMAXINFO message. Will a structure in WM_COPYDATA preserve it's data until the call to SendMessageTimeout returns?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这里有很多痛点。您假设没有其他代码会对该窗口进行子类化。并且这样的代码将以正确的顺序取消子类化。没有正确的顺序,您的挂钩与程序的执行完全异步。
但是,解决方法很简单。您已经开始使用 SetWindowsHookEx,不妨再做一次。 WH_CALLWNDPROC 或 WH_CALLWNDPROCRET,具体取决于您想要执行的操作。
There are plenty of pain points here. You assume that no other code will subclass the window. And that such code will un-subclass it in the right order. There is no right order, your hooking is quite asynchronous from the program's execution.
But, the workaround is simple enough. You are already hooking with SetWindowsHookEx, might as well do one more. WH_CALLWNDPROC or WH_CALLWNDPROCRET, depending on what you want to do.