グローバルCBTフックを使用して、現在フォーカスされているウィンドウをWindowsシステムでサブクラス化しようとしています。これはこの質問で何が起こるかに関連していますが、バグは異なります。
このサブクラス化が有効な場合は、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のメインウィンドウがどういうわけかすでにサブクラス化されているということです。私は次のことが起こっていると想像します:
- ウィンドウは独自の基本的なWndProcで作成され、フォーカスが与えられます
- 私のアプリケーションはウィンドウをサブクラス化し、元のWndProcを保存します
- Operaは独自のウィンドウをサブクラス化します
- ウィンドウのフォーカスが失われると、元のWndProcを復元し、2番目のWndProcを無視します。
これは本当にそうなのだろうか?他に説明はありますか?