问题描述
在实验代码中,当创建三个具有分层所有权的顶级窗口时,我看到以相反顺序关闭它们时出现奇怪的行为.
代码:
#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:
- 创建一个顶层窗口
Main Window
- 创建另一个顶级窗口
Window 2
并将其所有者指定为Main Window
- 创建另一个顶级窗口
Window 3
并将其所有者指定为Window 2
- 如果您仔细观察,所有这些都是非模态的,但拥有正确的所有权
- 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
现在当这个应用程序运行时(Release build, run on Windows 10 x64
),我们以相反的顺序关闭窗口,在关闭 Window 2
后,激活消失现有的 Notepad
窗口.
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!
其次,在四处寻找时,我确实看到焦点有时会转到 Default IME
窗口(即 Windows 输入法编辑器).我认为每个带有 UI 的应用程序都为 IME 分配了一个默认窗口?如果是这样,也许我一创建 Main Window
,就会创建一个 IME 窗口,然后在我下次调用 CreateWindowW
时,会创建其他 2 个拥有的窗口,因此更改顶级窗口列表中的兄弟姐妹?这只是目前的推测.
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.
有人可以解释一下吗?对此的无黑客"解决方法是什么?
推荐答案
Adding additional WS_POPUP
style to Window 2 (or use WS_CAPTION
| WS_POPUPWINDOW
> 替换 WS_OVERLAPPEDWINDOW
.)为我解决了这个问题.
Adding additional WS_POPUP
style to Window 2 (Or use WS_CAPTION
| WS_POPUPWINDOW
replace WS_OVERLAPPEDWINDOW
.) solves the issue for me.
使用 WS_POPUP
,将选择所有权,您将看到您期望的行为.没有WS_POPUP
,系统会寻找下一个窗口激活,这是无证的.
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.
这篇关于所有者和拥有的窗口激活问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!