Jack
Jack

Reputation: 16724

How do I make tab key work within this dialog control?

I added IsDialogMessage() to my main loop, the tab key did work but it stuck at the top of the tab control and didn't go down to the controls inside the dialog box. How can I fix that? I've tried WS_GROUP in the first control and WS_TABSTOP all the next created controls but it didn't work.

The tab control is created like this:

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);

and the dialog box:

      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);

then the DialogProc procedure:

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);
}

And the main loop:

  while (GetMessage(&msg, NULL, 0, 0))
  {
      if (!IsDialogMessage(hwnd, &msg)) {
          TranslateMessage(&msg);
          DispatchMessage(&msg);
      }
  

}

Upvotes: 0

Views: 210

Answers (1)

Anders
Anders

Reputation: 101666

You usually don't create interactive windows/controls as children of the tab control, strange but true. Create the inner dialog as a child of the outer dialog, not the tab control.

This MSDN example creates the inner dialogs as children of the main dialog.

As explained in this blog post, WS_EX_CONTROL­PARENT takes the window/control out of the tab order.

This is a pure Win32 thing, Delphi/C++Builder and other environments with custom UI toolkits often implement the tab control as a real container.

Upvotes: 2

Related Questions