This fixes the layout of the tabcontrol when a font other than the system font is used.
-- v9: comctl32/tests: Modify test_width to try different fonts comctl32/tests: Check size initially and after changing padding only comctl32/tests: Fix tabcontrol tests to work with different fonts comctl32: Use selected font to determine default min tab width
From: Brendan McGrath bmcgrath@codeweavers.com
--- dlls/comctl32/tests/tab.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
diff --git a/dlls/comctl32/tests/tab.c b/dlls/comctl32/tests/tab.c index a5c51690689..b0a882e6e26 100644 --- a/dlls/comctl32/tests/tab.c +++ b/dlls/comctl32/tests/tab.c @@ -674,6 +674,30 @@ static void test_width(void) test_tab(94); }
+static void test_setitemsize(void) +{ + HWND hwTab; + LRESULT result; + HDC hdc; + INT dpi; + + hwTab = create_tabcontrol(0, TCIF_TEXT); + SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, -1); + + hdc = GetDC(hwTab); + dpi = GetDeviceCaps(hdc, LOGPIXELSX); + ReleaseDC(hwTab, hdc); + + result = SendMessageA(hwTab, TCM_SETITEMSIZE, 0, MAKELPARAM(50, 20)); + todo_wine ok (LOWORD(result) == dpi, "Excepted width to be %d, got %d\n", dpi, LOWORD(result)); + + result = SendMessageA(hwTab, TCM_SETITEMSIZE, 0, MAKELPARAM(0, 1)); + todo_wine ok (LOWORD(result) == 50, "Excepted width to be 50, got %d\n", LOWORD(result)); + ok (HIWORD(result) == 20, "Excepted height to be 20, got %d\n", HIWORD(result)); + + DestroyWindow (hwTab); +} + static void test_curfocus(void) { const INT nTabs = 5; @@ -1581,6 +1605,7 @@ START_TEST(tab) ok(parent_wnd != NULL, "Failed to create parent window!\n");
test_width(); + test_setitemsize(); test_curfocus(); test_cursel(); test_extendedstyle();
From: Brendan McGrath bmcgrath@codeweavers.com
Windows sets the default width to LOGPIXELSX regardless of the style.
It will also always return the previous cx value provided. --- dlls/comctl32/tab.c | 14 +++++++------- dlls/comctl32/tests/tab.c | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/dlls/comctl32/tab.c b/dlls/comctl32/tab.c index 13abbd8078d..73b3f313086 100644 --- a/dlls/comctl32/tab.c +++ b/dlls/comctl32/tab.c @@ -2662,19 +2662,20 @@ TAB_SetItemSize (TAB_INFO *infoPtr, INT cx, INT cy) lResult = MAKELONG(infoPtr->tabWidth, infoPtr->tabHeight);
/* UNDOCUMENTED: If requested Width or Height is 0 this means that program wants to use auto size. */ - if (infoPtr->dwStyle & TCS_FIXEDWIDTH && (infoPtr->tabWidth != cx)) + if (infoPtr->tabWidth != cx) { infoPtr->tabWidth = cx; bNeedPaint = TRUE; }
- if (infoPtr->tabHeight != cy) + if (infoPtr->tabHeight != cy && cy != 0) { - if ((infoPtr->fHeightSet = (cy != 0))) - infoPtr->tabHeight = cy; - + infoPtr->tabHeight = cy; bNeedPaint = TRUE; } + + infoPtr->fHeightSet = (cy != 0); + TRACE("was h=%d,w=%d, now h=%d,w=%d\n", HIWORD(lResult), LOWORD(lResult), infoPtr->tabHeight, infoPtr->tabWidth); @@ -3063,8 +3064,7 @@ static LRESULT TAB_Create (HWND hwnd, LPARAM lParam) infoPtr->uVItemPadding;
/* Initialize the width of a tab. */ - if (infoPtr->dwStyle & TCS_FIXEDWIDTH) - infoPtr->tabWidth = GetDeviceCaps(hdc, LOGPIXELSX); + infoPtr->tabWidth = GetDeviceCaps(hdc, LOGPIXELSX);
infoPtr->tabMinWidth = -1;
diff --git a/dlls/comctl32/tests/tab.c b/dlls/comctl32/tests/tab.c index b0a882e6e26..0704dce940c 100644 --- a/dlls/comctl32/tests/tab.c +++ b/dlls/comctl32/tests/tab.c @@ -689,10 +689,10 @@ static void test_setitemsize(void) ReleaseDC(hwTab, hdc);
result = SendMessageA(hwTab, TCM_SETITEMSIZE, 0, MAKELPARAM(50, 20)); - todo_wine ok (LOWORD(result) == dpi, "Excepted width to be %d, got %d\n", dpi, LOWORD(result)); + ok (LOWORD(result) == dpi, "Excepted width to be %d, got %d\n", dpi, LOWORD(result));
result = SendMessageA(hwTab, TCM_SETITEMSIZE, 0, MAKELPARAM(0, 1)); - todo_wine ok (LOWORD(result) == 50, "Excepted width to be 50, got %d\n", LOWORD(result)); + ok (LOWORD(result) == 50, "Excepted width to be 50, got %d\n", LOWORD(result)); ok (HIWORD(result) == 20, "Excepted height to be 20, got %d\n", HIWORD(result));
DestroyWindow (hwTab);
From: Brendan McGrath bmcgrath@codeweavers.com
This fixes the layout of the tabcontrol when a font other than the system font is used. --- dlls/comctl32/tab.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-)
diff --git a/dlls/comctl32/tab.c b/dlls/comctl32/tab.c index 73b3f313086..b0d645bddd4 100644 --- a/dlls/comctl32/tab.c +++ b/dlls/comctl32/tab.c @@ -138,14 +138,12 @@ typedef struct #define BUTTON_SPACINGX 3 #define BUTTON_SPACINGY 3 #define FLAT_BTN_SPACINGX 8 -#define DEFAULT_MIN_TAB_WIDTH 54 #define DEFAULT_PADDING_X 6 #define EXTRA_ICON_PADDING 3 +#define MIN_CHAR_LENGTH 6
#define TAB_GetInfoPtr(hwnd) ((TAB_INFO *)GetWindowLongPtrW(hwnd,0))
-#define GET_DEFAULT_MIN_TAB_WIDTH(infoPtr) (DEFAULT_MIN_TAB_WIDTH - (DEFAULT_PADDING_X - (infoPtr)->uHItemPadding) * 2) - /****************************************************************************** * Hot-tracking timer constants */ @@ -1101,8 +1099,10 @@ static void TAB_SetupScrolling( * It also uses the current font to determine the height of the tab row and * it checks if all the tabs fit in the client area of the window. If they * don't, a scrolling control is added. + * + * Returns the default minimum tab width */ -static void TAB_SetItemBounds (TAB_INFO *infoPtr) +static INT TAB_SetItemBounds (TAB_INFO *infoPtr) { TEXTMETRICW fontMetrics; UINT curItem; @@ -1115,6 +1115,8 @@ static void TAB_SetItemBounds (TAB_INFO *infoPtr) RECT* rcItem; INT iIndex; INT icon_width = 0; + INT default_min_tab_width; + TEXTMETRICW text_metrics;
/* * We need to get text information so we need a DC and we need to select @@ -1144,6 +1146,9 @@ static void TAB_SetItemBounds (TAB_INFO *infoPtr) /* Now use hPadding and vPadding */ infoPtr->uHItemPadding = infoPtr->uHItemPadding_s; infoPtr->uVItemPadding = infoPtr->uVItemPadding_s; + + GetTextMetricsW(hdc, &text_metrics); + default_min_tab_width = text_metrics.tmAveCharWidth * MIN_CHAR_LENGTH + infoPtr->uHItemPadding * 2;
/* The leftmost item will be "0" aligned */ curItemLeftPos = 0; @@ -1210,13 +1215,13 @@ static void TAB_SetItemBounds (TAB_INFO *infoPtr) { /* If no text use minimum tab width including padding. */ if (infoPtr->tabMinWidth < 0) - curr->rect.right = curr->rect.left + GET_DEFAULT_MIN_TAB_WIDTH(infoPtr); + curr->rect.right = curr->rect.left + default_min_tab_width; else { curr->rect.right = curr->rect.left + infoPtr->tabMinWidth;
/* Add extra padding if icon is present */ - if (infoPtr->himl && infoPtr->tabMinWidth > 0 && infoPtr->tabMinWidth < DEFAULT_MIN_TAB_WIDTH + if (infoPtr->himl && infoPtr->tabMinWidth > 0 && infoPtr->tabMinWidth < MIN_CHAR_LENGTH * text_metrics.tmAveCharWidth + DEFAULT_PADDING_X * 2 && infoPtr->uHItemPadding > 1) curr->rect.right += EXTRA_ICON_PADDING * (infoPtr->uHItemPadding-1); } @@ -1232,7 +1237,7 @@ static void TAB_SetItemBounds (TAB_INFO *infoPtr) tabwidth = size.cx + icon_width + 2 * infoPtr->uHItemPadding;
if (infoPtr->tabMinWidth < 0) - tabwidth = max(tabwidth, GET_DEFAULT_MIN_TAB_WIDTH(infoPtr)); + tabwidth = max(tabwidth, default_min_tab_width); else tabwidth = max(tabwidth, infoPtr->tabMinWidth);
@@ -1461,6 +1466,8 @@ static void TAB_SetItemBounds (TAB_INFO *infoPtr) /* Cleanup */ SelectObject (hdc, hOldFont); ReleaseDC (infoPtr->hwnd, hdc); + + return default_min_tab_width; }
@@ -2691,17 +2698,14 @@ TAB_SetItemSize (TAB_INFO *infoPtr, INT cx, INT cy)
static inline LRESULT TAB_SetMinTabWidth (TAB_INFO *infoPtr, INT cx) { - INT oldcx = 0; + INT default_min_tab_width; + INT prevMinWidth = infoPtr->tabMinWidth; + infoPtr->tabMinWidth = cx;
TRACE("(%p,%d)\n", infoPtr, cx);
- if (infoPtr->tabMinWidth < 0) - oldcx = DEFAULT_MIN_TAB_WIDTH; - else - oldcx = infoPtr->tabMinWidth; - infoPtr->tabMinWidth = cx; - TAB_SetItemBounds(infoPtr); - return oldcx; + default_min_tab_width = TAB_SetItemBounds(infoPtr); + return (prevMinWidth < 0) ? default_min_tab_width : prevMinWidth; }
static inline LRESULT
From: Brendan McGrath bmcgrath@codeweavers.com
The WM_SETFONT was previously passing the hFont as the LPARAM (when it should be the WPARAM). --- dlls/comctl32/tests/tab.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-)
diff --git a/dlls/comctl32/tests/tab.c b/dlls/comctl32/tests/tab.c index 0704dce940c..91f2d4a7490 100644 --- a/dlls/comctl32/tests/tab.c +++ b/dlls/comctl32/tests/tab.c @@ -25,10 +25,10 @@ #include "wine/test.h" #include "msg.h"
-#define DEFAULT_MIN_TAB_WIDTH 54 #define TAB_PADDING_X 6 #define EXTRA_ICON_PADDING 3 #define MAX_TABLEN 32 +#define MIN_CHAR_LENGTH 6
#define NUM_MSG_SEQUENCES 2 #define PARENT_SEQ_INDEX 0 @@ -43,7 +43,7 @@ static inline void expect_(unsigned line, DWORD expected, DWORD got) #define expect_str(expected, got)\ ok ( strcmp(expected, got) == 0, "Expected '%s', got '%s'\n", expected, got)
-#define TabWidthPadded(padd_x, num) (DEFAULT_MIN_TAB_WIDTH - (TAB_PADDING_X - (padd_x)) * num) +#define TabWidthPadded(default_min_tab_width, padd_x, num) ((default_min_tab_width) - (TAB_PADDING_X - (padd_x)) * num)
static HIMAGELIST (WINAPI *pImageList_Create)(INT,INT,UINT,INT,INT); static BOOL (WINAPI *pImageList_Destroy)(HIMAGELIST); @@ -313,7 +313,7 @@ create_tabcontrol (DWORD style, DWORD mask) ok(handle != NULL, "failed to create tab wnd\n");
SetWindowLongA(handle, GWL_STYLE, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style); - SendMessageA(handle, WM_SETFONT, 0, (LPARAM)hFont); + SendMessageA(handle, WM_SETFONT, (WPARAM)hFont, (LPARAM)0);
tcNewTab.mask = mask; tcNewTab.pszText = text1; @@ -524,18 +524,19 @@ static void test_tab(INT nMinTabWidth) HDC hdc; HFONT hOldFont; INT i, dpi, exp; + INT default_min_tab_width; + TEXTMETRICW text_metrics;
hwTab = create_tabcontrol(TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE); SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth); - /* Get System default MinTabWidth */ - if (nMinTabWidth < 0) - nMinTabWidth = SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
hdc = GetDC(hwTab); dpi = GetDeviceCaps(hdc, LOGPIXELSX); hOldFont = SelectObject(hdc, (HFONT)SendMessageA(hwTab, WM_GETFONT, 0, 0)); GetTextExtentPoint32A(hdc, "Tab 1", strlen("Tab 1"), &size); trace("Tab1 text size: size.cx=%ld size.cy=%ld\n", size.cx, size.cy); + GetTextMetricsW(hdc, &text_metrics); + default_min_tab_width = text_metrics.tmAveCharWidth * MIN_CHAR_LENGTH + TAB_PADDING_X * 2; SelectObject(hdc, hOldFont); ReleaseDC(hwTab, hdc);
@@ -603,14 +604,14 @@ static void test_tab(INT nMinTabWidth) SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
trace (" non fixed width, with text...\n"); - exp = max(size.cx +TAB_PADDING_X*2, (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth); + exp = max(size.cx +TAB_PADDING_X*2, (nMinTabWidth < 0) ? default_min_tab_width : nMinTabWidth); SendMessageA( hwTab, TCM_GETITEMRECT, 0, (LPARAM)&rTab ); - ok( rTab.right - rTab.left == exp || broken(rTab.right - rTab.left == DEFAULT_MIN_TAB_WIDTH), + ok( rTab.right - rTab.left == exp || broken(rTab.right - rTab.left == default_min_tab_width), "no icon, default width: Expected width [%d] got [%ld]\n", exp, rTab.right - rTab.left );
for (i=0; i<8; i++) { - INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth; + INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(default_min_tab_width, i, 2) : nMinTabWidth;
SendMessageA(hwTab, TCM_SETIMAGELIST, 0, 0); SendMessageA(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i, i)); @@ -619,7 +620,7 @@ static void test_tab(INT nMinTabWidth) TABCHECKSETSIZE(hwTab, 0, 1, max(size.cx + i*2, nTabWidth), 1, "no icon, min size");
SendMessageA(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl); - nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 3) : nMinTabWidth; + nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(default_min_tab_width, i, 3) : nMinTabWidth;
TABCHECKSETSIZE(hwTab, 50, 30, max(size.cx + 21 + i*3, nTabWidth), 30, "with icon, set size > icon"); TABCHECKSETSIZE(hwTab, 20, 20, max(size.cx + 21 + i*3, nTabWidth), 20, "with icon, set size < icon"); @@ -631,14 +632,14 @@ static void test_tab(INT nMinTabWidth) SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
trace (" non fixed width, no text...\n"); - exp = (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth; + exp = (nMinTabWidth < 0) ? default_min_tab_width : nMinTabWidth; SendMessageA( hwTab, TCM_GETITEMRECT, 0, (LPARAM)&rTab ); - ok( rTab.right - rTab.left == exp || broken(rTab.right - rTab.left == DEFAULT_MIN_TAB_WIDTH), + ok( rTab.right - rTab.left == exp || broken(rTab.right - rTab.left == default_min_tab_width), "no icon, default width: Expected width [%d] got [%ld]\n", exp, rTab.right - rTab.left );
for (i=0; i<8; i++) { - INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth; + INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(default_min_tab_width, i, 2) : nMinTabWidth;
SendMessageA(hwTab, TCM_SETIMAGELIST, 0, 0); SendMessageA(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i, i)); @@ -647,7 +648,7 @@ static void test_tab(INT nMinTabWidth) TABCHECKSETSIZE(hwTab, 0, 1, nTabWidth, 1, "no icon, min size");
SendMessageA(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl); - if (i > 1 && nMinTabWidth > 0 && nMinTabWidth < DEFAULT_MIN_TAB_WIDTH) + if (i > 1 && nMinTabWidth > 0 && nMinTabWidth < default_min_tab_width) nTabWidth += EXTRA_ICON_PADDING *(i-1);
TABCHECKSETSIZE(hwTab, 50, 30, nTabWidth, 30, "with icon, set size > icon");
From: Brendan McGrath bmcgrath@codeweavers.com
--- dlls/comctl32/tests/tab.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/dlls/comctl32/tests/tab.c b/dlls/comctl32/tests/tab.c index 91f2d4a7490..7fc9c83a67d 100644 --- a/dlls/comctl32/tests/tab.c +++ b/dlls/comctl32/tests/tab.c @@ -540,6 +540,7 @@ static void test_tab(INT nMinTabWidth) SelectObject(hdc, hOldFont); ReleaseDC(hwTab, hdc);
+ trace ("default_min_tab_width: %d\n", default_min_tab_width); trace (" TCS_FIXEDWIDTH tabs no icon...\n"); CHECKSIZE(hwTab, dpi, -1, "default width"); TABCHECKSETSIZE(hwTab, 50, 20, 50, 20, "set size"); @@ -609,6 +610,7 @@ static void test_tab(INT nMinTabWidth) ok( rTab.right - rTab.left == exp || broken(rTab.right - rTab.left == default_min_tab_width), "no icon, default width: Expected width [%d] got [%ld]\n", exp, rTab.right - rTab.left );
+ CHECKSIZE(hwTab, max(size.cx + TAB_PADDING_X*2, nMinTabWidth < 0 ? default_min_tab_width : nMinTabWidth), size.cy + 5, "Initial values"); for (i=0; i<8; i++) { INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(default_min_tab_width, i, 2) : nMinTabWidth; @@ -625,6 +627,11 @@ static void test_tab(INT nMinTabWidth) TABCHECKSETSIZE(hwTab, 50, 30, max(size.cx + 21 + i*3, nTabWidth), 30, "with icon, set size > icon"); TABCHECKSETSIZE(hwTab, 20, 20, max(size.cx + 21 + i*3, nTabWidth), 20, "with icon, set size < icon"); TABCHECKSETSIZE(hwTab, 0, 1, max(size.cx + 21 + i*3, nTabWidth), 1, "with icon, min size"); + + /* tests that a change to padding only doesn't impact reported size */ + SendMessageA(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i + 1, i + 1)); + CHECKSIZE(hwTab, max(size.cx + 21 + i*3, nTabWidth), 1, "with icon, min size, padding only change"); + TABCHECKSETSIZE(hwTab, 0, 1, max(size.cx + 21 + i*3, nTabWidth), 1, "with icon, min size, same size"); } DestroyWindow (hwTab);
@@ -637,6 +644,7 @@ static void test_tab(INT nMinTabWidth) ok( rTab.right - rTab.left == exp || broken(rTab.right - rTab.left == default_min_tab_width), "no icon, default width: Expected width [%d] got [%ld]\n", exp, rTab.right - rTab.left );
+ CHECKSIZE(hwTab, nMinTabWidth < 0 ? default_min_tab_width : nMinTabWidth, size.cy + 5, "Initial values"); for (i=0; i<8; i++) { INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(default_min_tab_width, i, 2) : nMinTabWidth; @@ -654,6 +662,11 @@ static void test_tab(INT nMinTabWidth) TABCHECKSETSIZE(hwTab, 50, 30, nTabWidth, 30, "with icon, set size > icon"); TABCHECKSETSIZE(hwTab, 20, 20, nTabWidth, 20, "with icon, set size < icon"); TABCHECKSETSIZE(hwTab, 0, 1, nTabWidth, 1, "with icon, min size"); + + /* tests that a change to padding only doesn't impact reported size */ + SendMessageA(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i + 1, i + 1)); + CHECKSIZE(hwTab, nTabWidth, 1, "with icon, min size, padding only change"); + TABCHECKSETSIZE(hwTab, 0, 1, nTabWidth, 1, "with icon, min size, same size"); }
DestroyWindow (hwTab);
From: Brendan McGrath bmcgrath@codeweavers.com
--- dlls/comctl32/tests/tab.c | 43 ++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 10 deletions(-)
diff --git a/dlls/comctl32/tests/tab.c b/dlls/comctl32/tests/tab.c index 7fc9c83a67d..6d38baae8a6 100644 --- a/dlls/comctl32/tests/tab.c +++ b/dlls/comctl32/tests/tab.c @@ -676,16 +676,39 @@ static void test_tab(INT nMinTabWidth)
static void test_width(void) { - trace ("Testing with default MinWidth\n"); - test_tab(-1); - trace ("Testing with MinWidth set to -3\n"); - test_tab(-3); - trace ("Testing with MinWidth set to 24\n"); - test_tab(24); - trace ("Testing with MinWidth set to 54\n"); - test_tab(54); - trace ("Testing with MinWidth set to 94\n"); - test_tab(94); + HFONT oldFont = hFont; + const char *fonts[] = { + "System", + "Arial", + "Tahoma", + "Courier New", + "MS Shell Dlg", + }; + + LOGFONTA logfont = { + .lfHeight = -12, + .lfWeight = FW_NORMAL, + .lfCharSet = ANSI_CHARSET + }; + + for(int i = 0; i < sizeof(fonts)/sizeof(fonts[0]); i++) { + trace ("Testing with the '%s' font\n", fonts[i]); + lstrcpyA(logfont.lfFaceName, fonts[i]); + hFont = CreateFontIndirectA(&logfont); + + trace ("Testing with default MinWidth\n"); + test_tab(-1); + trace ("Testing with MinWidth set to -3\n"); + test_tab(-3); + trace ("Testing with MinWidth set to 24\n"); + test_tab(24); + trace ("Testing with MinWidth set to 54\n"); + test_tab(54); + trace ("Testing with MinWidth set to 94\n"); + test_tab(94); + } + + hFont = oldFont; }
static void test_setitemsize(void)
v8: Fixes the tests that were failing under the Japanese locale
This merge request was approved by Nikolay Sivov.