我知道,必须有一种方法可以将(无模式)对话框嵌入为使用CreateWindow
. 在我的情况下,我想将它们嵌入到一个可滚动的容器窗口中,而这个容器窗口本身就是主窗口的子窗口(见图)。
我遇到的第一个问题是,我仍然希望能够使用 TAB 键和其他特定于对话框的导航。但是怎么做?
我的消息循环:
while (GetMessage(&msg, NULL, 0, 0)) {
if (IsDialogMessage(msg.hwnd, &msg)) continue;
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
编辑:出于测试目的,我修改了循环:
while (GetMessage(&msg, NULL, 0, 0)) {
if (IsEmbeddedDialogWindow(msg.hwnd)) {
if (IsDialogMessage(msg.hwnd, &msg)) continue;
}
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
while (GetMessage(&msg, NULL, 0, 0)) {
if (IsScrollableContainerWindow(msg.hwnd)) {
if (IsDialogMessage(msg.hwnd, &msg)) continue;
}
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
可以在此处找到如何使其正确的更多信息:使用 TAB 键在非对话框中导航,redux
使用此消息循环,如果我想输入一些对话框文本,就好像没有处理消息一样,什么都不会发生。如果IsDialogMessage
被删除,我可以在其中一个嵌入对话框的编辑控件中输入一些文本,但是对话框导航无法按预期工作。当然,WS_TABSTOP
样式是为对话框子控件设置的。
可滚动容器是CreateWindowEx
使用样式
创建的WS_CHILD, WS_VISIBLE, WS_VSCROLL, WS_TABSTOP, WS_EX_CONTROLPARENT
,对话框是作为该容器的子级创建的。
HWND hWndContainer = GroupBarPanelCreate(WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, WS_EX_CONTROLPARENT, hWndMain, 0, 0, 400, 400);
GROUPBAR_PANEL* GroupBarPanel = (GROUPBAR_PANEL*) GetWindowLongPtr(hWndContainer, 0);
// Test embedding dialogs
for (unsigned int i = 0; i < 10; i++) {
HWND hWndDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWndContainer, About, 0);
GroupBarPanelInternalAddLast(GroupBarPanel, hWndChild, hWndDlg, nullptr);
}
我GroupBarPanelInternalAddLast
通过删除标题和边框来修改无模式对话框样式,并确保设置了WS_CHILD
,WS_VISIBLE
和WS_TABSTOP
( SetWindowLong(hWndDlg, GWL_STYLE, ...)
)。(也经过测试WS_EX_CONTROLPARENT
的样式)使用SetParent(hWndDlg, hWndContainer)
无模式对话框更改父级。
那么我在这里错过了什么?正如我发现的那样,容器窗口过程和嵌入式(用于测试目的的子类化)对话框过程几乎都不会得到消息WM_SETFOCUS
或WM_KILLFOCUS
消息,但为什么呢?
解决方案:为顶层窗口调用 IsDialogMessage。
while (GetMessage(&msg, NULL, 0, 0)) {
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
if (IsDialogMessage(hWndTopLevel, &msg)) {
continue;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}