gpt4 book ai didi

c++ - 安全删除窗口子类化?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:21:20 24 4
gpt4 key购买 nike

我正在尝试使用全局 CBT Hook 子类化 Windows 系统上当前聚焦的窗口。这与 this question 中发生的事情有关。 , 但错误是不同的。

当这个子类化生效时,会阻止 Opera(10.50 版)的主窗口显示。 Opera 有一个“启动画面”,您需要单击主窗口的“开始”才能显示在 Opera 未正常关闭后出现的画面。每当弹出此窗口时,Opera 的主窗口将不会显示。如果 Opera 正常关闭,并且没有显示启动画面,主窗口会正常显示。

HHOOK hHook;
HWND hWndSubclass = 0;

void SubclassWindow(HWND hWnd)
{
Unsubclass();
FARPROC lpfnOldWndProc = (FARPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LPARAM)SubClassFunc);
SetProp(hWnd, L"PROP_OLDWNDPROC", lpfnOldWndProc);
hWndSubclass = hWnd;
}

void Unsubclass()
{
if (hWndSubclass != 0 && IsWindow(hWndSubclass))
{
FARPROC lpfnOldWndProc = (FARPROC)GetProp(hWndSubclass, L"PROP_OLDWNDPROC");
RemoveProp(hWndSubclass, L"PROP_OLDWNDPROC");
SetWindowLongPtr(hWndSubclass, GWLP_WNDPROC, (LPARAM)lpfnOldWndProc);
hWndSubclass = 0;
}
}

static LRESULT CALLBACK SubClassFunc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_MOVING)
{
// do something irrelevant
}
else if (message == WM_DESTROY)
{
Unsubclass();
}
FARPROC lpfnOldWndProc = (FARPROC)GetProp(hWndSubclass, L"PROP_OLDWNDPROC");
return CallWindowProc((WNDPROC)lpfnOldWndProc, hWndSubclass, message, wParam, lParam);
}

static LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HCBT_SETFOCUS && hWndServer != NULL)
{
SubclassWindow((HWND)wParam);
}
if (nCode < 0)
{
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
return 0;
}

BOOL APIENTRY DllMain( HINSTANCE hInstance,
DWORD Reason,
LPVOID Reserved
)
{
switch(Reason)
{
case DLL_PROCESS_ATTACH:
hInst = hInstance;
return TRUE;
case DLL_PROCESS_DETACH:
Unsubclass();
return TRUE;
}
return TRUE;
}

我怀疑 Opera 的主窗口不知何故已经被子类化了。我想象发生了以下情况:

  1. 窗口使用它自己的基本 WndProc 创建,并获得焦点
  2. 我的应用程序将窗口子类化,存储原始的 WndProc
  3. Opera 子类化它自己的窗口
  4. 当窗口失去焦点时,我恢复原来的 WndProc,从而忽略第二个 WndProc

真的可以吗?还有其他解释吗?

最佳答案

这可能会发生,因为 Raymond Chen writes :

Consider what would happen if somebody else had subclassed the window during the "... do stuff ..." section. When we unsubclassed the window, we would have removed two subclasses, the one we installed, and the one that was installed after us. If the other subclass allocated memory (which is very common), then that memory got leaked, in addition to the subclass failing to do whatever it was trying to do.

他继续给出解决方案:

This is quite a cumbersome process, so the shell team wrote some helper functions to do all this for you. The SetWindowSubclass function does all the grunt work of installing a subclass procedure, remembering the previous one, and passing reference data to the subclass procedure you provide. You use the DefSubclassProc function to forward the message to the previous subclass procedure, and when you're done, you use the RemoveWindowSubclass function to remove yourself from the chain. RemoveWindowSubclass does all the work to do the right thing if you are not the window procerure at the top of the chain.

关于c++ - 安全删除窗口子类化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2446273/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com