This is confirmed by the tests in test_scrollbar() and manual tests on XP. Even though scrollbar arrows and thumb are in fact transparent, DrawThemeParentBackground() is not called to paint the parent background, leaving the transparent area untouched. On Windows, even if the scrollbar arrows are reported to be transparent, the bitmaps for arrow parts in the stock themes are in fact opaque.
Fix Ice Cream Calculator slow scrolling after 4cb229a because the WM_PRINTCLIENT handling in the application is slow.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53337
-- v2: comctl32/datetime: Do not paint parent background when painting arrows. uxtheme: Do not draw parent background even if scrollbar arrows and thumb are transparent. uxtheme: Use the brush from WM_CTLCOLORSCROLLBAR to paint SB_CTL scrollbar tracks if present. comctl32/tests: Add themed scrollbar background tests. uxtheme/tests: Add theme tests.
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/uxtheme/tests/system.c | 45 +++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
diff --git a/dlls/uxtheme/tests/system.c b/dlls/uxtheme/tests/system.c index debc712a73c..a90c512091f 100644 --- a/dlls/uxtheme/tests/system.c +++ b/dlls/uxtheme/tests/system.c @@ -2550,6 +2550,50 @@ static void test_GetThemeBackgroundRegion(void) DestroyWindow(hwnd); }
+static void test_theme(void) +{ + BOOL transparent; + HTHEME htheme; + HRESULT hr; + HWND hwnd; + + if (!IsThemeActive()) + { + skip("Theming is inactive.\n"); + return; + } + + hwnd = CreateWindowA(WC_STATICA, "", WS_POPUP, 0, 0, 1, 1, 0, 0, 0, NULL); + ok(!!hwnd, "CreateWindowA failed, error %#lx.\n", GetLastError()); + + /* Test that scrollbar arrow parts are transparent */ + htheme = OpenThemeData(hwnd, L"ScrollBar"); + ok(!!htheme, "OpenThemeData failed.\n"); + + transparent = FALSE; + hr = GetThemeBool(htheme, SBP_ARROWBTN, 0, TMT_TRANSPARENT, &transparent); + /* XP does use opaque scrollbar arrow parts and TMT_TRANSPARENT is FALSE */ + if (LOBYTE(LOWORD(GetVersion())) < 6) + { + ok(hr == E_PROP_ID_UNSUPPORTED, "Got unexpected hr %#lx.\n", hr); + + transparent = IsThemeBackgroundPartiallyTransparent(htheme, SBP_ARROWBTN, 0); + ok(!transparent, "Expected opaque.\n"); + } + /* > XP use opaque scrollbar arrow parts, but TMT_TRANSPARENT is TRUE */ + else + { + ok(hr == S_OK, "Got unexpected hr %#lx,\n", hr); + ok(transparent, "Expected transparent.\n"); + + transparent = IsThemeBackgroundPartiallyTransparent(htheme, SBP_ARROWBTN, 0); + ok(transparent, "Expected transparent.\n"); + } + CloseThemeData(htheme); + + DestroyWindow(hwnd); +} + START_TEST(system) { ULONG_PTR ctx_cookie; @@ -2574,6 +2618,7 @@ START_TEST(system) test_DrawThemeParentBackground(); test_DrawThemeBackgroundEx(); test_GetThemeBackgroundRegion(); + test_theme();
if (load_v6_module(&ctx_cookie, &ctx)) {
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/comctl32/tests/misc.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-)
diff --git a/dlls/comctl32/tests/misc.c b/dlls/comctl32/tests/misc.c index 737778a836d..61b2149a463 100644 --- a/dlls/comctl32/tests/misc.c +++ b/dlls/comctl32/tests/misc.c @@ -890,6 +890,9 @@ static void test_themed_background(void) {WC_SCROLLBARA, 0, scrollbar_seq, TRUE}, {WC_SCROLLBARA, SBS_SIZEBOX, empty_seq}, {WC_SCROLLBARA, SBS_SIZEGRIP, empty_seq}, + /* Scrollbars in non-client area */ + {"ChildClass", WS_HSCROLL, empty_seq}, + {"ChildClass", WS_VSCROLL, empty_seq}, };
uxtheme = LoadLibraryA("uxtheme.dll"); @@ -915,7 +918,11 @@ static void test_themed_background(void) cls.lpszClassName = "ParentClass"; RegisterClassA(&cls);
- parent = CreateWindowA(cls.lpszClassName, "parent", WS_POPUP | WS_VISIBLE, 100, 100, 100, 100, + cls.lpfnWndProc = DefWindowProcA; + cls.lpszClassName = "ChildClass"; + RegisterClassA(&cls); + + parent = CreateWindowA("ParentClass", "parent", WS_POPUP | WS_VISIBLE, 100, 100, 100, 100, 0, 0, 0, 0); ok(parent != NULL, "CreateWindowA failed, error %lu.\n", GetLastError());
@@ -924,7 +931,7 @@ static void test_themed_background(void) winetest_push_context("%s %#lx", tests[i].class_name, tests[i].style);
child = CreateWindowA(tests[i].class_name, " ", WS_CHILD | WS_VISIBLE | tests[i].style, - 0, 0, 50, 50, parent, 0, 0, 0); + 0, 0, 50, 100, parent, 0, 0, 0); ok(child != NULL, "CreateWindowA failed, error %lu.\n", GetLastError()); flush_events(); flush_sequences(sequences, NUM_MSG_SEQUENCES); @@ -965,6 +972,17 @@ static void test_themed_background(void) color = GetPixel(hdc, 10, 10); ok(color == 0x808080, "Expected color %#x, got %#lx.\n", 0x808080, color); } + else if (tests[i].seq == scrollbar_seq) + { + /* WM_CTLCOLORSCROLLBAR is used to fill tracks only */ + color = GetPixel(hdc, 10, 10); + ok(color != RGB(255, 0, 0), "Got unexpected color %#08lx.\n", color); + + color = GetPixel(hdc, 10, 60); + todo_wine + ok(color == RGB(255, 0, 0) || broken(color == CLR_INVALID), /* Win7 on TestBots */ + "Got unexpected color %#08lx.\n", color); + }
ReleaseDC(child, hdc); } @@ -974,7 +992,8 @@ static void test_themed_background(void) }
DestroyWindow(parent); - UnregisterClassA(cls.lpszClassName, GetModuleHandleA(0)); + UnregisterClassA("ChildClass", GetModuleHandleA(0)); + UnregisterClassA("ParentClass", GetModuleHandleA(0)); if (pSetThreadDpiAwarenessContext) pSetThreadDpiAwarenessContext(old_context); }
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/comctl32/tests/misc.c | 1 - dlls/uxtheme/scrollbar.c | 32 ++++++++++++++++++++------------ 2 files changed, 20 insertions(+), 13 deletions(-)
diff --git a/dlls/comctl32/tests/misc.c b/dlls/comctl32/tests/misc.c index 61b2149a463..9f6eb611388 100644 --- a/dlls/comctl32/tests/misc.c +++ b/dlls/comctl32/tests/misc.c @@ -979,7 +979,6 @@ static void test_themed_background(void) ok(color != RGB(255, 0, 0), "Got unexpected color %#08lx.\n", color);
color = GetPixel(hdc, 10, 60); - todo_wine ok(color == RGB(255, 0, 0) || broken(color == CLR_INVALID), /* Win7 on TestBots */ "Got unexpected color %#08lx.\n", color); } diff --git a/dlls/uxtheme/scrollbar.c b/dlls/uxtheme/scrollbar.c index 4ae1b2a8724..1f1c61d74e1 100644 --- a/dlls/uxtheme/scrollbar.c +++ b/dlls/uxtheme/scrollbar.c @@ -68,9 +68,13 @@ void WINAPI UXTHEME_ScrollBarDraw(HWND hwnd, HDC dc, INT bar, enum SCROLL_HITTES DrawThemeBackground(theme, dc, SBP_SIZEBOX, state, rect, NULL); } else { int uppertrackstate, lowertrackstate, thumbstate; + HBRUSH track_brush = NULL; RECT partrect; SIZE grippersize;
+ if (bar == SB_CTL) + track_brush = (HBRUSH)SendMessageW(GetParent(hwnd), WM_CTLCOLORSCROLLBAR, (WPARAM)dc, (LPARAM)hwnd); + if (disabled) { uppertrackstate = SCRBS_DISABLED; lowertrackstate = SCRBS_DISABLED; @@ -148,9 +152,10 @@ void WINAPI UXTHEME_ScrollBarDraw(HWND hwnd, HDC dc, INT bar, enum SCROLL_HITTES partrect.top = rect->top + arrowsize; partrect.bottom = rect->top + thumbpos;
- if (bar == SB_CTL && IsThemeBackgroundPartiallyTransparent(theme, SBP_UPPERTRACKVERT, uppertrackstate)) - DrawThemeParentBackground(hwnd, dc, &partrect); - DrawThemeBackground(theme, dc, SBP_UPPERTRACKVERT, uppertrackstate, &partrect, NULL); + if (bar == SB_CTL && track_brush) + FillRect(dc, &partrect, track_brush); + else + DrawThemeBackground(theme, dc, SBP_UPPERTRACKVERT, uppertrackstate, &partrect, NULL); }
if (thumbsize > 0) { @@ -178,9 +183,10 @@ void WINAPI UXTHEME_ScrollBarDraw(HWND hwnd, HDC dc, INT bar, enum SCROLL_HITTES partrect.top = rect->top + arrowsize; if (partrect.bottom > partrect.top) { - if (bar == SB_CTL && IsThemeBackgroundPartiallyTransparent(theme, SBP_LOWERTRACKVERT, lowertrackstate)) - DrawThemeParentBackground(hwnd, dc, &partrect); - DrawThemeBackground(theme, dc, SBP_LOWERTRACKVERT, lowertrackstate, &partrect, NULL); + if (bar == SB_CTL && track_brush) + FillRect(dc, &partrect, track_brush); + else + DrawThemeBackground(theme, dc, SBP_LOWERTRACKVERT, lowertrackstate, &partrect, NULL); } } else { int leftarrowstate, rightarrowstate; @@ -225,9 +231,10 @@ void WINAPI UXTHEME_ScrollBarDraw(HWND hwnd, HDC dc, INT bar, enum SCROLL_HITTES partrect.left = rect->left + arrowsize; partrect.right = rect->left + thumbpos;
- if (bar == SB_CTL && IsThemeBackgroundPartiallyTransparent(theme, SBP_UPPERTRACKHORZ, uppertrackstate)) - DrawThemeParentBackground(hwnd, dc, &partrect); - DrawThemeBackground(theme, dc, SBP_UPPERTRACKHORZ, uppertrackstate, &partrect, NULL); + if (bar == SB_CTL && track_brush) + FillRect(dc, &partrect, track_brush); + else + DrawThemeBackground(theme, dc, SBP_UPPERTRACKHORZ, uppertrackstate, &partrect, NULL); }
if (thumbsize > 0) { @@ -255,9 +262,10 @@ void WINAPI UXTHEME_ScrollBarDraw(HWND hwnd, HDC dc, INT bar, enum SCROLL_HITTES partrect.left = rect->left + arrowsize; if (partrect.right > partrect.left) { - if (bar == SB_CTL && IsThemeBackgroundPartiallyTransparent(theme, SBP_LOWERTRACKHORZ, lowertrackstate)) - DrawThemeParentBackground(hwnd, dc, &partrect); - DrawThemeBackground(theme, dc, SBP_LOWERTRACKHORZ, lowertrackstate, &partrect, NULL); + if (bar == SB_CTL && track_brush) + FillRect(dc, &partrect, track_brush); + else + DrawThemeBackground(theme, dc, SBP_LOWERTRACKHORZ, lowertrackstate, &partrect, NULL); } } }
From: Zhiyi Zhang zzhang@codeweavers.com
This is confirmed by the tests in test_scrollbar() and manual tests on XP. Even though scrollbar arrows and thumb are in fact transparent, DrawThemeParentBackground() is not called to paint the parent background, leaving the transparent area untouched. On Windows, even if the scrollbar arrows are reported to be transparent, the bitmaps for arrow parts in the stock themes are in fact opaque.
Fix Ice Cream Calculator slow scrolling after 4cb229a because the WM_PRINTCLIENT handling in the application is slow.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53337 --- dlls/comctl32/tests/misc.c | 2 +- dlls/uxtheme/scrollbar.c | 14 -------------- 2 files changed, 1 insertion(+), 15 deletions(-)
diff --git a/dlls/comctl32/tests/misc.c b/dlls/comctl32/tests/misc.c index 9f6eb611388..ac4c3abaf30 100644 --- a/dlls/comctl32/tests/misc.c +++ b/dlls/comctl32/tests/misc.c @@ -887,7 +887,7 @@ static void test_themed_background(void) {TRACKBAR_CLASSA, 0, wm_ctlcolorstatic_seq}, {WC_TREEVIEWA, 0, treeview_seq}, {UPDOWN_CLASSA, 0, empty_seq}, - {WC_SCROLLBARA, 0, scrollbar_seq, TRUE}, + {WC_SCROLLBARA, 0, scrollbar_seq}, {WC_SCROLLBARA, SBS_SIZEBOX, empty_seq}, {WC_SCROLLBARA, SBS_SIZEGRIP, empty_seq}, /* Scrollbars in non-client area */ diff --git a/dlls/uxtheme/scrollbar.c b/dlls/uxtheme/scrollbar.c index 1f1c61d74e1..d5735c5279a 100644 --- a/dlls/uxtheme/scrollbar.c +++ b/dlls/uxtheme/scrollbar.c @@ -138,14 +138,10 @@ void WINAPI UXTHEME_ScrollBarDraw(HWND hwnd, HDC dc, INT bar, enum SCROLL_HITTES
partrect = *rect; partrect.bottom = partrect.top + arrowsize; - if (bar == SB_CTL && IsThemeBackgroundPartiallyTransparent(theme, SBP_ARROWBTN, uparrowstate)) - DrawThemeParentBackground(hwnd, dc, &partrect); DrawThemeBackground(theme, dc, SBP_ARROWBTN, uparrowstate, &partrect, NULL);
partrect.bottom = rect->bottom; partrect.top = partrect.bottom - arrowsize; - if (bar == SB_CTL && IsThemeBackgroundPartiallyTransparent(theme, SBP_ARROWBTN, downarrowstate)) - DrawThemeParentBackground(hwnd, dc, &partrect); DrawThemeBackground(theme, dc, SBP_ARROWBTN, downarrowstate, &partrect, NULL);
if (thumbpos > 0) { @@ -161,9 +157,6 @@ void WINAPI UXTHEME_ScrollBarDraw(HWND hwnd, HDC dc, INT bar, enum SCROLL_HITTES if (thumbsize > 0) { partrect.top = rect->top + thumbpos; partrect.bottom = partrect.top + thumbsize; - - if (bar == SB_CTL && IsThemeBackgroundPartiallyTransparent(theme, SBP_THUMBBTNVERT, thumbstate)) - DrawThemeParentBackground(hwnd, dc, &partrect); DrawThemeBackground(theme, dc, SBP_THUMBBTNVERT, thumbstate, &partrect, NULL);
if (SUCCEEDED(GetThemePartSize(theme, dc, SBP_GRIPPERVERT, thumbstate, NULL, TS_DRAW, &grippersize))) { @@ -217,14 +210,10 @@ void WINAPI UXTHEME_ScrollBarDraw(HWND hwnd, HDC dc, INT bar, enum SCROLL_HITTES
partrect = *rect; partrect.right = partrect.left + arrowsize; - if (bar == SB_CTL && IsThemeBackgroundPartiallyTransparent(theme, SBP_ARROWBTN, leftarrowstate)) - DrawThemeParentBackground(hwnd, dc, &partrect); DrawThemeBackground(theme, dc, SBP_ARROWBTN, leftarrowstate, &partrect, NULL);
partrect.right = rect->right; partrect.left = partrect.right - arrowsize; - if (bar == SB_CTL && IsThemeBackgroundPartiallyTransparent(theme, SBP_ARROWBTN, rightarrowstate)) - DrawThemeParentBackground(hwnd, dc, &partrect); DrawThemeBackground(theme, dc, SBP_ARROWBTN, rightarrowstate, &partrect, NULL);
if (thumbpos > 0) { @@ -240,9 +229,6 @@ void WINAPI UXTHEME_ScrollBarDraw(HWND hwnd, HDC dc, INT bar, enum SCROLL_HITTES if (thumbsize > 0) { partrect.left = rect->left + thumbpos; partrect.right = partrect.left + thumbsize; - - if (bar == SB_CTL && IsThemeBackgroundPartiallyTransparent(theme, SBP_THUMBBTNHORZ, thumbstate)) - DrawThemeParentBackground(hwnd, dc, &partrect); DrawThemeBackground(theme, dc, SBP_THUMBBTNHORZ, thumbstate, &partrect, NULL);
if (SUCCEEDED(GetThemePartSize(theme, dc, SBP_GRIPPERHORZ, thumbstate, NULL, TS_DRAW, &grippersize))) {
From: Zhiyi Zhang zzhang@codeweavers.com
This is tested manually on XP, Win7 and Win10. --- dlls/comctl32/datetime.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/dlls/comctl32/datetime.c b/dlls/comctl32/datetime.c index f142ea8ede5..53c17798668 100644 --- a/dlls/comctl32/datetime.c +++ b/dlls/comctl32/datetime.c @@ -793,8 +793,6 @@ DATETIME_Refresh (DATETIME_INFO *infoPtr, HDC hdc) else state = ABS_DOWNNORMAL;
- if (IsThemeBackgroundPartiallyTransparent(theme, SBP_ARROWBTN, state)) - DrawThemeParentBackground(infoPtr->hwndSelf, hdc, &infoPtr->calbutton); DrawThemeBackground(theme, hdc, SBP_ARROWBTN, state, &infoPtr->calbutton, NULL); } else