问题
In an experimental code, when creating three top level windows with hierarchical ownership I am seeing weird behavior when dismissing them in reverse order.
Code:
#include <Windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
MSG msg;
WNDCLASS wndClass;
WCHAR className[] = L"OwnedWindowsWeirdness";
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.lpszMenuName = NULL;
wndClass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndClass.hInstance = hInstance;
wndClass.lpfnWndProc = WndProc;
wndClass.lpszClassName = className;
wndClass.style = CS_HREDRAW | CS_VREDRAW;
if(!RegisterClassW(&wndClass))
{
MessageBoxW(0, L"Unable to register class...Exiting!", className, MB_OK);
return -1;
}
HWND hwnd1 = CreateWindowW(className, L"Main Window", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 500, 400,
NULL, 0, hInstance, 0);
HWND hwnd2 = CreateWindowW(className, L"Main Window > Window 2", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 400, 300,
hwnd1, 0, hInstance, 0);
HWND hwnd3 = CreateWindowW(className, L"Main Window > Window 2 > Window 3", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 300, 200,
hwnd2, 0, hInstance, 0);
ShowWindow(hwnd1, SW_SHOWNORMAL);
UpdateWindow(hwnd1);
ShowWindow(hwnd2, SW_SHOWNORMAL);
UpdateWindow(hwnd2);
ShowWindow(hwnd3, SW_SHOWNORMAL);
UpdateWindow(hwnd3);
while(GetMessage(&msg, 0,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
// Subdeveloper: Purposefully not complicating the code by calling PostQuitMessage/etc!
// In absence of which, this test application will need to be closed using
// task manager
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
The code above does this:
- Creates a top level window
Main Window
- Creates another top level window
Window 2
and assigns its owner asMain Window
- Creates yet another top level window
Window 3
and assigns its owner asWindow 2
- All are non-modal if you observe closely, but with correct ownership
Now when this application is run (Release built, run on Windows 10 x64
) and we close the windows in reverse order, after closing Window 2
activation goes away to existing Notepad
window.
The behavior could be seen in following screen capture:
I am wondering what is going on. Generally this kind of behavior occurs when we miss setting correct ownership!
Secondly, when hunting around I did see that focus goes to Default IME
window sometimes (i.e. Windows Input Method Editor). I think a default window is assigned for IME to every application with UI? If so maybe as soon as I create the Main Window
, an IME window is created, and then on my next calls to CreateWindowW
, the other 2 owned windows are created, thus changing the siblings in top level windows list? This is just a speculation for now.
Can someone explain this, and whats the "no-hack" workaround for this?
回答1:
Adding additional WS_POPUP
style to Window 2 (Or use WS_CAPTION
| WS_POPUPWINDOW
replace WS_OVERLAPPEDWINDOW
.) solves the issue for me.
With WS_POPUP
, the ownership will be picked, you will see the behavior you expected. Without WS_POPUP
, system will find the next window to activate, this is undocumented.
来源:https://stackoverflow.com/questions/60377627/owner-and-owned-window-activation-issue