[PATCH v4 0/1] MR10340: comctl32/tooltips: suppress icon and title when title is NULL or empty.
Per MSDN, TTM_SETTITLE with a NULL or empty title string should suppress both the title row and any associated icon. Previously an empty string was treated the same as a non-empty title, causing the icon to still be displayed and the tooltip to be incorrectly sized. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58236 Signed-off-by: Larry Starr <Larry_A_Starr@yahoo.com> -- v4: comctl32/tooltips: suppress icon and title when title is NULL or empty. https://gitlab.winehq.org/wine/wine/-/merge_requests/10340
From: Larry Starr <Larry_A_Starr@yahoo.com> Per MSDN, TTM_SETTITLE with a NULL or empty title string should suppress both the title row and any associated icon. Previously an empty string was treated the same as a non-empty title, causing the icon to still be displayed and the tooltip to be incorrectly sized. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58236 Signed-off-by: Larry Starr <Larry_A_Starr@yahoo.com> --- dlls/comctl32/tests/tooltips.c | 75 ++++++++++++++++++++++++++++++++++ dlls/comctl32/tooltips.c | 14 +++++-- 2 files changed, 85 insertions(+), 4 deletions(-) diff --git a/dlls/comctl32/tests/tooltips.c b/dlls/comctl32/tests/tooltips.c index d34f83806b5..5bf336349d2 100644 --- a/dlls/comctl32/tests/tooltips.c +++ b/dlls/comctl32/tests/tooltips.c @@ -1179,6 +1179,79 @@ static const struct message ttn_show_parent_seq[] = { 0 } }; +/* Helper: activate a tracked tooltip and measure its window size. */ +static void get_tracked_size(HWND tt, TTTOOLINFOW *info, SIZE *sz) +{ + RECT rc; + SendMessageW(tt, TTM_TRACKACTIVATE, TRUE, (LPARAM)info); + SendMessageW(tt, TTM_TRACKPOSITION, 0, MAKELPARAM(10, 10)); + flush_events(100); + GetWindowRect(tt, &rc); + sz->cx = rc.right - rc.left; + sz->cy = rc.bottom - rc.top; + SendMessageW(tt, TTM_TRACKACTIVATE, FALSE, (LPARAM)info); + flush_events(50); +} + +/* regression test for https://bugs.winehq.org/show_bug.cgi?id=58236 */ +static void test_TTM_SETTITLE(void) +{ + HWND parent, tt; + TTTOOLINFOW info = { 0 }; + SIZE sz_no_title, sz_null_icon, sz_empty_icon; + LRESULT res; + + parent = CreateWindowExW(0, WC_STATICW, NULL, WS_CAPTION | WS_VISIBLE, + 50, 50, 400, 400, NULL, NULL, GetModuleHandleW(NULL), 0); + ok(parent != NULL, "failed to create parent window\n"); + ShowWindow(parent, SW_SHOWNORMAL); + flush_events(100); + + tt = CreateWindowExW(WS_EX_TOPMOST, TOOLTIPS_CLASSW, NULL, + TTS_NOPREFIX | TTS_ALWAYSTIP, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + parent, NULL, GetModuleHandleW(NULL), 0); + ok(tt != NULL, "failed to create tooltip window\n"); + + info.cbSize = TTTOOLINFOW_V1_SIZE; + info.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE; + info.hwnd = parent; + info.hinst = GetModuleHandleW(NULL); + info.lpszText = (WCHAR *)L"x"; + info.uId = (UINT_PTR)parent; + GetClientRect(parent, &info.rect); + + res = SendMessageW(tt, TTM_ADDTOOLW, 0, (LPARAM)&info); + ok(res, "TTM_ADDTOOLW failed\n"); + + /* Baseline: no title, no icon */ + SendMessageW(tt, TTM_SETTITLEW, TTI_NONE, (LPARAM)NULL); + get_tracked_size(tt, &info, &sz_no_title); + + /* Icon requested with NULL title — must be suppressed */ + SendMessageW(tt, TTM_SETTITLEW, TTI_WARNING, (LPARAM)NULL); + get_tracked_size(tt, &info, &sz_null_icon); + ok(sz_null_icon.cy == sz_no_title.cy, + "NULL title + icon: height %ld, expected %ld (same as no-title)\n", + sz_null_icon.cy, sz_no_title.cy); + ok(sz_null_icon.cx == sz_no_title.cx, + "NULL title + icon: width %ld, expected %ld (same as no-title)\n", + sz_null_icon.cx, sz_no_title.cx); + + /* Icon requested with empty string title — must also be suppressed */ + SendMessageW(tt, TTM_SETTITLEW, TTI_WARNING, (LPARAM)L""); + get_tracked_size(tt, &info, &sz_empty_icon); + ok(sz_empty_icon.cy == sz_no_title.cy, + "empty title + icon: height %ld, expected %ld (same as no-title)\n", + sz_empty_icon.cy, sz_no_title.cy); + ok(sz_empty_icon.cx == sz_no_title.cx, + "empty title + icon: width %ld, expected %ld (same as no-title)\n", + sz_empty_icon.cx, sz_no_title.cx); + + DestroyWindow(tt); + DestroyWindow(parent); +} + static void test_TTN_SHOW(void) { HWND hwndTip, hwnd; @@ -1255,6 +1328,7 @@ START_TEST(tooltips) test_margin(); test_TTM_ADDTOOL(FALSE); test_TTN_SHOW(); + test_TTM_SETTITLE(); if (!load_v6_module(&ctx_cookie, &hCtx)) return; @@ -1267,6 +1341,7 @@ START_TEST(tooltips) test_margin(); test_TTM_ADDTOOL(TRUE); test_TTN_SHOW(); + test_TTM_SETTITLE(); unload_v6_module(ctx_cookie, hCtx); } diff --git a/dlls/comctl32/tooltips.c b/dlls/comctl32/tooltips.c index 876736b11e4..f150efeabc1 100644 --- a/dlls/comctl32/tooltips.c +++ b/dlls/comctl32/tooltips.c @@ -1638,7 +1638,8 @@ TOOLTIPS_SetTitleT (TOOLTIPS_INFO *infoPtr, UINT_PTR uTitleIcon, LPCWSTR pszTitl Free(infoPtr->pszTitle); - if (pszTitle) + /* Suppress title and icon if title is NULL or empty (MSDN, bug 58236). */ + if (pszTitle && (isW ? ((LPCWSTR)pszTitle)[0] : ((LPCSTR)pszTitle)[0])) { if (isW) { @@ -1671,10 +1672,15 @@ TOOLTIPS_SetTitleT (TOOLTIPS_INFO *infoPtr, UINT_PTR uTitleIcon, LPCWSTR pszTitl infoPtr->iconHeight = GetSystemMetrics(SM_CYSMICON); } - if (uTitleIcon <= TTI_ERROR_LARGE) - infoPtr->hTitleIcon = hTooltipIcons[uTitleIcon]; + if (infoPtr->pszTitle) + { + if (uTitleIcon <= TTI_ERROR_LARGE) + infoPtr->hTitleIcon = hTooltipIcons[uTitleIcon]; + else + infoPtr->hTitleIcon = CopyIcon((HICON)uTitleIcon); + } else - infoPtr->hTitleIcon = CopyIcon((HICON)uTitleIcon); + infoPtr->hTitleIcon = NULL; TRACE("icon = %p\n", infoPtr->hTitleIcon); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10340
On Tue Mar 24 19:26:39 2026 +0000, Zhiyi Zhang wrote:
Please fix the CI failures. Done.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10340#note_133564
participants (2)
-
Larry Starr -
Larry Starr (@starrl)