Я добавил IsDialogMessage()
в свой основной цикл, клавиша табуляции работала, но она застряла в верхней части элемента управления вкладкой и не переходила к элементам управления внутри диалогового окна. Как я могу это исправить? Я пробовал WS_GROUP
в первом элементе управления и WS_TABSTOP
во всех последующих созданных элементах управления, но это не сработало.
Элемент управления вкладками создается следующим образом:
hTabControl =
CreateWindowW(WC_TABCONTROLW, NULL,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_TABSTOP | WS_GROUP | WS_EX_CONTROLPARENT,
10, 30, 400, 250,
hwnd,
(HMENU) ID_MAIN_TABCONTROL,
NULL,
NULL);
и диалоговое окно:
CreateWindowExW(WS_EX_TOOLWINDOW | WS_EX_CONTROLPARENT,
"DialogBox",
L"Dialog Box",
WS_SYSMENU | WS_CHILD | WS_GROUP | WS_TABSTOP | WS_VISIBLE,
10, 30, 350, 150,
hTabControl, NULL, ghInstance, NULL
);
// ...
WNDCLASSEXW wc = {0};
wc.cbSize = sizeof(WNDCLASSEXW);
wc.lpfnWndProc = DialogProc;
wc.hInstance = ghInstance;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpszClassName = "DialogClass";
RegisterClassExW(&wc);
затем процедура DialogProc:
LRESULT CALLBACK DialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
CreateWindowW(L"button", L"A",
WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_GROUP,
50, 50, 80, 25, hwnd, (HMENU) ID_TAB1_BUTTONA, NULL, NULL);
CreateWindowW(L"button", L"B",
WS_VISIBLE | WS_CHILD | WS_TABSTOP,
150, 50, 80, 25, hwnd, (HMENU) ID_TAB1_BUTTONB, NULL, NULL);
CreateWindowW(L"button", L"C",
WS_VISIBLE | WS_CHILD | WS_TABSTOP,
250, 50, 80, 25, hwnd, (HMENU) ID_TAB1_BUTTONC, NULL, NULL);
CreateWindowW(L"button", L"D",
WS_VISIBLE | WS_CHILD | WS_TABSTOP,
50, 100, 80, 25, hwnd, (HMENU) ID_TAB1_BUTTOND, NULL, NULL);
CreateWindow(L"Edit", NULL,
WS_VISIBLE | WS_CHILD | WS_BORDER | ES_AUTOHSCROLL | WS_TABSTOP,
150, 100, 80, 20, hwnd, (HMENU) ID_TAB1_EDIT1, NULL, NULL);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
// didn't do anything
default:
break;
case ID_TAB1_BUTTONA:
{
MessageBox(NULL, L"Click on A button", L"Welcome to the jungle!", MB_OK);
}
break;
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
И основной цикл:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!IsDialogMessage(hwnd, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Я предполагаю, что это было упущено при моей попытке скрыть элемент управления вкладкой от ALT + TAB.
Обычно вы не создаете интерактивные окна/элементы управления как дочерние элементы управления вкладками, что странно, но факт. Создайте внутренний диалог как дочерний элемент внешнего диалога, а не элемента управления вкладками.
Этот пример MSDN создает внутренние диалоги как дочерние элементы основного диалога.
Как объясняется в этом сообщении в блоге, WS_EX_CONTROLPARENT
выводит окно/элемент управления из порядка табуляции.
Это чистая вещь Win32, Delphi/C++Builder и другие среды с пользовательскими инструментами пользовательского интерфейса часто реализуют элемент управления вкладками как настоящий контейнер.
Это действительно странно, я пришел из мира С#, поэтому я пытался подражать тому, что я считал правильным поведением, делая эти вкладки окна дочерними элементами. Но, читая сообщение в блоге Рэймонда, я понимаю, почему это так и насколько распространена эта ошибка. Чтобы сделать эти вкладки элементами управления братьями и сестрами, я изменил на CreateWindowExW(WS_EX_CONTROLPARENT,... , hwnd)
в процедуре Windows LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ... }
. Это правильно сейчас? Я не знал о WS_EX_CONTROLPARENT
принять вкладку заказа, удалил это
С помощью этого диалога я пытался эмулировать контейнер с WINAPI, так как ничего подобного в WINAPI не нашел. А вот как это обычно делается с WINAPI это тема другого вопроса. Клавиши табуляции теперь работают нормально, я объединил их с WS_GROUP
в первом элементе управления, а затем WS_TABSTOP
во всех последующих окнах, созданных в процедуре. Это способ табуляции делается с WINAPI?
Обычно вы используете групповой стиль только с переключателями, это единственное место, где они требуются. Другие места предназначены только для поддержки навигации с помощью клавиш со стрелками, если вы используете групповой стиль. Для обычных элементов управления вы обычно просто используете вкладки вверху каждого.
Я вижу, тогда удалил WS_GROUP. То, что я читаю, вводит в заблуждение.
но то, как я создаю эти элементы управления, правильно ли это?
Не используйте WS_EX_CONTROLPARENT для элементов управления, только WS_TABSTOP. WS_EX_CONTROLPARENT для внутреннего диалога.
Я удалил это, спасибо. Я спрашивал об использовании диалогового окна в качестве вкладки для элемента управления вкладкой. Это не так, как управление вкладками создается с помощью WINAPI? Это хорошая практика?
Да, использование одного дочернего диалогового окна на странице вкладки является обычной практикой.
Почему ваш (внутренний) диалог имеет стиль WS_EX_TOOLWINDOW?