Experimenting with tab control I found this differences between MSDN and actual implementation: - TCS_OWNERDRAWFIXED style has nothing to do with fixed with tabs. It should me named TCS_OWNERDRAW instead. Unless there is some apps that think otherwise, this should work (tested on eMule and test program). In other words, this quote from MSDN is not true: "Because all tabs in an owner-drawn tab control are the same size..." - It looks like there is not such thing as not set tab width. According to this: "To give all tabs the same width, you can specify the TCS_FIXEDWIDTH style. The control sizes all the tabs to fit the widest label, or you can assign a specific width and height by using the TCM_SETITEMSIZE message." one can assume that if tab width is not explicitly set with TCM_SETITEMSIZE message "The control sizes all the tabs to fit the widest label". Not true. Native uses default tab size of 96. - The minimum size of a tab is at least icon width + 3 if icon is present. - Prior observation that "under Windows, there seems to be a minimum width of 2x the height for button style tabs" is not true. At least not in Win98. Vitaliy Margolen changelog: - Fix tab size for TCS_OWNERDRAWFIXED style - Correct size recalculation after setting tab width - Fix button sizes to match native. to-do (I'm working on): - Correct text & icon position within each tab/button to match native - Fix hot-track
Index: tab.c =================================================================== RCS file: /home/wine/wine/dlls/comctl32/tab.c,v retrieving revision 1.86 diff -u -r1.86 tab.c --- tab.c 14 Oct 2003 20:12:05 -0000 1.86 +++ tab.c 19 Oct 2003 23:16:51 -0000 @@ -93,7 +93,7 @@ #define DISPLAY_AREA_PADDINGY 2 #define CONTROL_BORDER_SIZEX 2 #define CONTROL_BORDER_SIZEY 2 -#define BUTTON_SPACINGX 4 +#define BUTTON_SPACINGX 3 #define BUTTON_SPACINGY 4 #define FLAT_BTN_SPACINGX 8 #define DEFAULT_TAB_WIDTH 96 @@ -1072,6 +1072,7 @@ INT iTemp; RECT* rcItem; INT iIndex; + INT icon_width = 0; /* * We need to get text information so we need a DC and we need to select @@ -1134,37 +1135,31 @@ TRACE("client right=%ld\n", clientRect.right); + /* Get the icon width */ + if (infoPtr->himl) + ImageList_GetIconSize(infoPtr->himl, &icon_width, 0); + for (curItem = 0; curItem < infoPtr->uNumItem; curItem++) { /* Set the leftmost position of the tab. */ infoPtr->items[curItem].rect.left = curItemLeftPos; - if ( lStyle & (TCS_FIXEDWIDTH | TCS_OWNERDRAWFIXED) ) + if (lStyle & TCS_FIXEDWIDTH) { infoPtr->items[curItem].rect.right = infoPtr->items[curItem].rect.left + - infoPtr->tabWidth + - 2 * infoPtr->uHItemPadding; + max(infoPtr->tabWidth, icon_width + 4); } else { - int icon_width = 0; int num = 2; /* Calculate how wide the tab is depending on the text it contains */ GetTextExtentPoint32W(hdc, infoPtr->items[curItem].pszText, lstrlenW(infoPtr->items[curItem].pszText), &size); - /* under Windows, there seems to be a minimum width of 2x the height - * for button style tabs */ - if (lStyle & TCS_BUTTONS) - size.cx = max(size.cx, 2 * (infoPtr->tabHeight - 2)); - - /* Add the icon width */ - if (infoPtr->himl) - { - ImageList_GetIconSize(infoPtr->himl, &icon_width, 0); + /* Add padding if icon is present */ + if (icon_width) num++; - } infoPtr->items[curItem].rect.right = infoPtr->items[curItem].rect.left + size.cx + icon_width + @@ -1215,7 +1210,7 @@ */ if (lStyle & TCS_BUTTONS) { - curItemLeftPos = infoPtr->items[curItem].rect.right + 1; + curItemLeftPos = infoPtr->items[curItem].rect.right + BUTTON_SPACINGX; if (lStyle & TCS_FLATBUTTONS) curItemLeftPos += FLAT_BTN_SPACINGX; } @@ -2572,8 +2567,7 @@ lResult = MAKELONG(infoPtr->tabWidth, infoPtr->tabHeight); /* UNDOCUMENTED: If requested Width or Height is 0 this means that program wants to use auto size. */ - if ((lStyle & (TCS_FIXEDWIDTH | TCS_OWNERDRAWFIXED)) && - (infoPtr->tabWidth != (INT)LOWORD(lParam))) + if (lStyle & TCS_FIXEDWIDTH && (infoPtr->tabWidth != (INT)LOWORD(lParam))) { infoPtr->tabWidth = max((INT)LOWORD(lParam), infoPtr->tabMinWidth); bNeedPaint = TRUE; @@ -2583,8 +2577,6 @@ { if ((infoPtr->fHeightSet = ((INT)HIWORD(lParam) != 0))) infoPtr->tabHeight = (INT)HIWORD(lParam); - else - TAB_SetItemBounds(hwnd); bNeedPaint = TRUE; } @@ -2593,7 +2585,10 @@ infoPtr->tabHeight, infoPtr->tabWidth); if (bNeedPaint) + { + TAB_SetItemBounds(hwnd); RedrawWindow(hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW); + } return lResult; } @@ -2990,7 +2985,7 @@ infoPtr->needsScrolling = FALSE; infoPtr->hwndUpDown = 0; infoPtr->leftmostVisible = 0; - infoPtr->fHeightSet = FALSE; + infoPtr->fHeightSet = FALSE; infoPtr->bUnicode = IsWindowUnicode (hwnd); TRACE("Created tab control, hwnd [%p]\n", hwnd); @@ -3043,8 +3038,7 @@ /* Initialize the width of a tab. */ infoPtr->tabWidth = DEFAULT_TAB_WIDTH; - /* The minimum width is the default width at creation */ - infoPtr->tabMinWidth = DEFAULT_TAB_WIDTH; + infoPtr->tabMinWidth = 0; TRACE("tabH=%d, tabW=%d\n", infoPtr->tabHeight, infoPtr->tabWidth);