【发布时间】:2020-06-08 04:25:06
【问题描述】:
在实验代码中,当创建三个具有分层所有权的顶级窗口时,我看到以相反顺序关闭它们时出现奇怪的行为。
代码:
#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);
}
上面的代码是这样做的:
- 创建一个顶级窗口
Main Window - 创建另一个顶级窗口
Window 2,并将其所有者指定为Main Window - 创建另一个顶级窗口
Window 3并将其所有者指定为Window 2 - 如果您仔细观察,所有这些都是非模态的,但所有权正确
现在,当这个应用程序运行 (Release built, run on Windows 10 x64) 并且我们以相反的顺序关闭窗口时,在关闭 Window 2 后激活会转到现有的 Notepad 窗口。
可以在以下屏幕截图中看到该行为:
我想知道发生了什么。通常,当我们错过设置正确的所有权时,就会发生这种行为!
其次,当我四处寻找时,我确实看到焦点有时会转到Default IME 窗口(即 Windows 输入法编辑器)。我认为每个带有 UI 的应用程序都为 IME 分配了一个默认窗口?如果是这样,也许我一创建Main Window,就会创建一个IME 窗口,然后在我下次调用CreateWindowW 时,会创建另外两个拥有的窗口,从而更改顶级窗口列表中的兄弟姐妹?这只是暂时的猜测。
有人可以解释一下吗?对此有什么“无破解”的解决方法?
【问题讨论】:
-
对此没什么好说的,窗口管理器是互惠互利的。只需使用 if (hwnd == hwnd2 && iMsg == WM_CLOSE) SetForegroundWindow(hwnd1); 解决问题在窗口过程中,现在它不再需要猜测接下来应该激活哪个窗口。
-
在出现另外两个窗口后,
Main Window处于非活动状态。您可以单击任何窗口将其激活,即使该窗口与其他窗口重叠。与子窗口和父窗口不同,这三个顶级窗口之间没有依赖的活动关系。如果您在所有三个窗口出现后通过单击激活Main Window,然后关闭Window 2,Main Window将成为活动窗口。 -
虽然应用程序可以随时激活不同的顶级窗口,但为了避免混淆用户,它应该只在响应用户操作时这样做。因此,用户是决定应该激活哪个窗口的最佳角色。您的问题是系统根据您的实验激活不同的顶级窗口属于不同的应用程序,系统如何决定激活哪个,对吗?
-
@RitaHan-MSFT 和 HansPassant 即使我们暂时搁置关系,三个顶级窗口也会快速连续创建,这不足以决定下一个/上一个顺序Windows 内部簿记?这本身并不是一个表演障碍,但这种行为让我感到惊讶。有没有这方面的资料/文件?
-
@rit:几十年来,用户一直被教导如何在 Z 方向上形成一个顺序。当顶级窗口被关闭时,用户期望窗口以反向 Z 顺序激活。系统从不需要猜测。但显然它确实如此,而且弄错了。