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