Search code examples
cwinapiwindowheightwidth

How do I get the width and height from a tab control?


I have a tab control where I'd like to get its width and height to create a window that fills this area. But I don't quite get how to get this width and height. From what I found, the value get from TabCtrl_GetItemRect() is in dialog-unit, so I need to convert to pixels, the I would do for example int width = tr.right - tr.left but that value is wrong, if I pass that value to the CreateWindowExW() it creates a tiny control, that's not even 1/4 of the target width and height. The routine I'm using to convert from dialog-unit to pixel is:

void DlgUnitsToPxs(RECT *rect)
{
  long units = GetDialogBaseUnits();
  int xBaseUnit = LOWORD(units);
  int yBaseUnit = HIWORD(units);

  rect->left   = MulDiv(rect->left,   xBaseUnit, 4);
  rect->right  = MulDiv(rect->right,  xBaseUnit, 4);
  rect->top    = MulDiv(rect->top,    yBaseUnit, 8);
  rect->bottom = MulDiv(rect->bottom, yBaseUnit, 8);
}

getting the values like this:

RECT tr = {0};
TabCtrl_GetItemRect(hTabControl, 0, &tr);
DlgUnitsToPxs(&tr);
int width = tr.right - tr.left;
int height = tr.bottom - tr.top;

What am I missing?


Solution

  • You would use the GetClientRect function and the TCM_ADJUSTRECT message (with wParam set to TRUE and an lParam being a pointer to the RECT to adjust). I generally create the windows that are going to be shown as tab children with the tab as the actual parent window just so that I then do not need to use MapWindowPoints on that RECT.

    For example (although I would generally actually use C++ style initialization):

    ...
    case WM_SIZE:
     {
      RECT rc;
      TCITEM item;
      HWND hWndChild;
      HWND hWndTab = GetDlgItem(hWnd, ID_TAB);
      _ASSERT(hWndTab);
    
      item.mask = TCIF_PARAM;
      SendMessage(hWndTab, TCM_GETITEM, SendMessage(hWndTab, TCM_GETCURFOCUS, 0, 0), &item);
    
      _ASSERT(item.lParam);
      hWndChild = (HWND)item.lParam;
    
      GetClientRect(hWndTab, &rc);
      SendMessage(hWndTab, TCM_ADJUSTRECT, TRUE, (LPARAM)&rc);
    
      SetWindowPos(hWndChild, nullptr, rc.left, rc.top, rc.right, rc.bottom, SWP_NOACTIVATE|SWP_NOMOVE);
     }
     return 0;