【发布时间】:2010-11-23 17:06:16
【问题描述】:
我正在尝试对当前具有焦点的窗口进行子类化。为此,我使用 CBT 挂钩监视 HCBT_ACTIVATE 事件,并设置和取消设置焦点窗口和先前焦点窗口的 WndProc。
问题在于,它仅在我在代码中的某处设置断点时才有效。
如果没有断点,一旦我的应用程序退出,我子类化的所有窗口都会按顺序崩溃,即使我已经删除了子类化并恢复了原始 WndProc。
我已验证每当我的应用程序关闭时都会调用 Unsubclass()。
// code extracts
HINSTANCE hInst;
HHOOK hHook;
#pragma data_seg(".shared")
HWND hWndSubclass = 0;
FARPROC lpfnOldWndProc = NULL;
#pragma data_seg()
#pragma comment(linker, "/section:.shared,rws")
void Unsubclass()
{
// if the window still exists
if (hWndSubclass != 0 && IsWindow(hWndSubclass))
{
SetWindowLongPtr(hWndSubclass, GWLP_WNDPROC, (LPARAM)lpfnOldWndProc);
hWndSubclass = 0;
}
}
static LRESULT CALLBACK SubClassFunc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_MOVING)
{
// this is just test code so I can see it works (it does)
RECT* r = (RECT*)lParam;
r->right = r->left + 500;
r->bottom = r->top + 500;
return TRUE;
}
else if (message == WM_DESTROY)
{
Unsubclass();
}
return CallWindowProc((WNDPROC)lpfnOldWndProc, hWndSubclass, message, wParam, lParam);
}
void SubclassWindow(HWND hWnd)
{
// remove the subclassing for the old window
Unsubclass();
// subclass the new window
lpfnOldWndProc = (FARPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LPARAM)SubClassFunc);
hWndSubclass = hWnd;
}
static LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HCBT_ACTIVATE)
{
SubclassWindow((HWND)wParam);
}
return 0;
}
// ... code that initializes the CBT proc
__declspec(dllexport) BOOL Setup()
{
hHook = SetWindowsHookEx(WH_CBT, CBTProc, hInst, 0);
}
__declspec(dllexport) BOOL Teardown()
{
UnhookWindowsHookEx(hHook);
Unsubclass();
}
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;
}
【问题讨论】:
-
hWndServer 无关紧要(它是设置 CBT 挂钩的进程)。我已经删除了对它的引用。
-
是否有可能在最后的 Unsubclass 之后钩子仍然处于活动状态并且在关闭期间仍然子类窗口?
-
@DR:这也是我的恐惧。但据我所知,它应该是即时的:msdn.microsoft.com/en-us/library/ms997565.aspx
标签: winapi visual-c++ dll