Как мне заставить клавишу табуляции работать в этом диалоговом элементе управления?

#c #windows #winapi

#c #Windows #winapi

Вопрос:

Я добавил IsDialogMessage() в свой основной цикл клавишу tab, но она застряла в верхней части элемента управления tab и не переходила к элементам управления внутри диалогового окна. Как я могу это исправить? Я пробовал 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(amp;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(amp;msg, NULL, 0, 0))
  {
      if (!IsDialogMessage(hwnd, amp;msg)) {
          TranslateMessage(amp;msg);
          DispatchMessage(amp;msg);
      }
  
 

}

Комментарии:

1. Почему ваш (внутренний) диалог имеет стиль WS_EX_TOOLWINDOW?

2. Я предполагаю, что это было упущено при моей попытке скрыть элемент управления tab из ALT TAB

Ответ №1:

Обычно вы не создаете интерактивные окна / элементы управления как дочерние элементы элемента управления tab, странно, но это правда. Создайте внутренний диалог как дочерний элемент внешнего диалога, а не элемент управления табуляцией.

Этот пример MSDN создает внутренние диалоги как дочерние элементы основного диалога.

Как объясняется в этом сообщении в блоге, WS_EX_CONTROL­PARENT выводит окно / элемент управления из порядка табуляции.

Это чисто Win32, Delphi / C Builder и другие среды с пользовательскими наборами инструментов пользовательского интерфейса часто реализуют элемент управления tab как реальный контейнер.

Комментарии:

1. Это действительно странно, я пришел из мира C #, поэтому я пытался имитировать то, что, по моему мнению, было правильным поведением, делая дочерние элементы управления вкладками Windows. Но, читая сообщение в блоге Рэймонда, я понимаю, почему это так и насколько распространена эта ошибка. Для того, чтобы сделать эти элементы управления tab control родными, я изменил CreateWindowExW(WS_EX_CONTROLPARENT,... , hwnd) в процедуре Windows LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ... } . Правильно ли это сейчас? Я не знал о WS_EX_CONTROL­PARENT take tab of order, удалил это

2. С помощью этого диалогового окна я пытался эмулировать контейнер с помощью WINAPI, поскольку я не нашел ничего подобного в WINAPI. Но как это обычно делается с WINAPI, это тема для другого вопроса. Клавиши табуляции работают нормально, теперь я объединил их с WS_GROUP первым элементом управления, за которым следуют WS_TABSTOP все последующие окна, созданные в процедуре. Так ли выполняется табуляция с помощью WINAPI?

3. Обычно вы используете стиль группы только с переключателями, это единственное место, где они требуются. Другие места предназначены только для поддержки навигации по клавишам со стрелками, если вы используете стиль группы. Для обычных элементов управления вы обычно просто используете вкладки сверху на каждом.

4. Я вижу, тогда удалили WS_GROUP. То, что я прочитал, вводит в заблуждение.

5. но то, как я создаю эти элементы управления, это правильный путь?