Я знаю, что должен быть способ встроить диалоговое окно (немодальное) в качестве дочернего элемента окна, созданного с помощью CreateWindow
. В моем случае я хочу встроить их в окно контейнера с возможностью прокрутки, в котором окна этого контейнера сами являются дочерними элементами главного окна (см. Рисунок).Внедрение немодальных диалогов в виде дочернего окна с Windows API
Первая проблема, с которой я сталкиваюсь в том, что я все еще хочу быть в состоянии использовать клавиши TAB и другие диалоговую конкретную навигацию. Но как?
Мой цикл сообщений:
while (GetMessage(&msg, NULL, 0, 0)) {
if (IsDialogMessage(msg.hwnd, &msg)) continue;
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Edit: Для целей тестирования я модифицировал цикл:
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);
}
}
Более подробная информация, как сделать это правильно, можно найти здесь: Using the TAB key to navigate in non-dialogs, 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);
}
}
'IsDialogMessage' необходимо передать« HWND »диалогового окна кандидата, а не окно, на которое нацелено сообщение. –
Ну, ему должно быть предоставлено 'HWND' окна, которое имеет стиль' WS_EX_CONTROLPARENT' и является родителем других диалогов. –
При создании вам необходимо вручную установить фокус ввода, иначе клавиатурная навигация не будет работать. Я не совсем уверен, что это можно сделать для надежной работы. Почему вы не создаете обычные окна? – IInspectable