Fix Spy++ Toolbar buttons have artifacts. Spy++ first creates a Toolbar window, then calls OpenThemeData(hwnd, "Rebar") with the Toolbar window. Then when the Toolbar control uses the theme handle from GetWindowTheme(), it gets a Rebar theme the next time it draws, thus drawing wrong theme parts.
According the tests, not all of the common controls have such behaviors. Some of them do have theme handles opened by their window and then use that theme handle afterwards even it's changed from the outside. However, for other controls, the behaviors are not very consistent across all Windows versions. Also no applications depend on such behaviors for other controls yet. So, only modify the Toolbar control for now.
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/comctl32/tests/toolbar.c | 2 -- dlls/comctl32/toolbar.c | 36 ++++++++++++++++------------------- 2 files changed, 16 insertions(+), 22 deletions(-)
diff --git a/dlls/comctl32/tests/toolbar.c b/dlls/comctl32/tests/toolbar.c index d6ee358b04a..87b4611d056 100644 --- a/dlls/comctl32/tests/toolbar.c +++ b/dlls/comctl32/tests/toolbar.c @@ -2641,7 +2641,6 @@ static void test_visual(void) ok(ret, "TB_ADDBUTTONSA failed.\n");
theme = pGetWindowTheme(toolbar); - todo_wine ok(!theme, "Expected theme not opened by window.\n");
toolbar_dc = GetDC(toolbar); @@ -2672,7 +2671,6 @@ static void test_visual(void) BitBlt(mem_dc2, 0, 0, width, height, toolbar_dc, 0, 0, SRCCOPY);
ret = equal_dc(mem_dc1, mem_dc2, width, height); - todo_wine ok(ret, "Expected same content.\n");
pCloseThemeData(theme); diff --git a/dlls/comctl32/toolbar.c b/dlls/comctl32/toolbar.c index a8777ae5480..2585e11530e 100644 --- a/dlls/comctl32/toolbar.c +++ b/dlls/comctl32/toolbar.c @@ -142,6 +142,7 @@ typedef struct INT iListGap; /* default gap between text and image for toolbar with list style */ HFONT hDefaultFont; HFONT hFont; /* text font */ + HTHEME hTheme; /* theme */ HIMAGELIST himlInt; /* image list created internally */ PIMLENTRY *himlDef; /* default image list array */ INT cimlDef; /* default image list array count */ @@ -780,7 +781,7 @@ TOOLBAR_DrawImage(const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, INT left, I } else if (tbcd->nmcd.uItemState & CDIS_CHECKED || ((tbcd->nmcd.uItemState & CDIS_HOT) - && ((infoPtr->dwStyle & TBSTYLE_FLAT) || GetWindowTheme (infoPtr->hwndSelf)))) + && ((infoPtr->dwStyle & TBSTYLE_FLAT) || infoPtr->hTheme))) { /* if hot, attempt to draw with hot image list, if fails, use default image list */ @@ -900,7 +901,7 @@ TOOLBAR_DrawButton (const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HDC hdc, INT oldBkMode; DWORD dwItemCustDraw; DWORD dwItemCDFlag; - HTHEME theme = GetWindowTheme (infoPtr->hwndSelf); + HTHEME theme = infoPtr->hTheme;
rc = btnPtr->rect; rcArrow = rc; @@ -1053,8 +1054,7 @@ TOOLBAR_DrawButton (const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HDC hdc, ((tbcd.nmcd.uItemState & CDIS_CHECKED) || (tbcd.nmcd.uItemState & CDIS_INDETERMINATE))) TOOLBAR_DrawPattern (&rc, &tbcd);
- if (((infoPtr->dwStyle & TBSTYLE_FLAT) || GetWindowTheme (infoPtr->hwndSelf)) - && (tbcd.nmcd.uItemState & CDIS_HOT)) + if (((infoPtr->dwStyle & TBSTYLE_FLAT) || theme) && (tbcd.nmcd.uItemState & CDIS_HOT)) { if ( dwItemCDFlag & TBCDRF_HILITEHOTTRACK ) { @@ -3506,7 +3506,7 @@ TOOLBAR_GetHotImageList (const TOOLBAR_INFO *infoPtr, WPARAM wParam) static LRESULT TOOLBAR_GetHotItem (const TOOLBAR_INFO *infoPtr) { - if (!((infoPtr->dwStyle & TBSTYLE_FLAT) || GetWindowTheme (infoPtr->hwndSelf))) + if (!((infoPtr->dwStyle & TBSTYLE_FLAT) || infoPtr->hTheme)) return -1;
if (infoPtr->nHotItem < 0) @@ -5313,8 +5313,7 @@ TOOLBAR_Create (HWND hwnd, const CREATESTRUCTW *lpcs)
SystemParametersInfoW (SPI_GETICONTITLELOGFONT, 0, &logFont, 0); infoPtr->hFont = infoPtr->hDefaultFont = CreateFontIndirectW (&logFont); - - OpenThemeData (hwnd, themeClass); + infoPtr->hTheme = OpenThemeData (NULL, themeClass);
TOOLBAR_CheckStyle (infoPtr);
@@ -5358,8 +5357,8 @@ TOOLBAR_Destroy (TOOLBAR_INFO *infoPtr)
/* delete default font */ DeleteObject (infoPtr->hDefaultFont); - - CloseThemeData (GetWindowTheme (infoPtr->hwndSelf)); + + CloseThemeData (infoPtr->hTheme);
/* free toolbar info data */ SetWindowLongPtrW (infoPtr->hwndSelf, 0, 0); @@ -5375,7 +5374,6 @@ TOOLBAR_EraseBackground (TOOLBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) NMTBCUSTOMDRAW tbcd; INT ret = FALSE; DWORD ntfret; - HTHEME theme = GetWindowTheme (infoPtr->hwndSelf); DWORD dwEraseCustDraw = 0;
/* the app has told us not to redraw the toolbar */ @@ -5405,7 +5403,7 @@ TOOLBAR_EraseBackground (TOOLBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) /* If the toolbar is "transparent" then pass the WM_ERASEBKGND up * to my parent for processing. */ - if (theme || (infoPtr->dwStyle & TBSTYLE_TRANSPARENT)) { + if (infoPtr->hTheme || (infoPtr->dwStyle & TBSTYLE_TRANSPARENT)) { POINT pt, ptorig; HDC hdc = (HDC)wParam; HWND parent; @@ -5957,7 +5955,7 @@ TOOLBAR_MouseMove (TOOLBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) if ((infoPtr->dwStyle & TBSTYLE_TOOLTIPS) && (infoPtr->hwndToolTip == NULL)) TOOLBAR_TooltipCreateControl(infoPtr);
- if ((infoPtr->dwStyle & TBSTYLE_FLAT) || GetWindowTheme (infoPtr->hwndSelf)) { + if ((infoPtr->dwStyle & TBSTYLE_FLAT) || infoPtr->hTheme) { /* fill in the TRACKMOUSEEVENT struct */ trackinfo.cbSize = sizeof(TRACKMOUSEEVENT); trackinfo.dwFlags = TME_QUERY; @@ -5985,8 +5983,7 @@ TOOLBAR_MouseMove (TOOLBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
nHit = TOOLBAR_InternalHitTest (infoPtr, &pt, &button);
- if (((infoPtr->dwStyle & TBSTYLE_FLAT) || GetWindowTheme (infoPtr->hwndSelf)) - && (!infoPtr->bAnchor || button)) + if (((infoPtr->dwStyle & TBSTYLE_FLAT) || infoPtr->hTheme) && (!infoPtr->bAnchor || button)) TOOLBAR_SetHotItemEx(infoPtr, button ? nHit : TOOLBAR_NOWHERE, HICF_MOUSE);
if (infoPtr->nOldHit != nHit) @@ -6550,12 +6547,11 @@ TOOLBAR_SysColorChange (void)
/* update theme after a WM_THEMECHANGED message */ -static LRESULT theme_changed (HWND hwnd) +static LRESULT theme_changed (TOOLBAR_INFO *infoPtr) { - HTHEME theme = GetWindowTheme (hwnd); - CloseThemeData (theme); - OpenThemeData (hwnd, themeClass); - InvalidateRect (hwnd, NULL, TRUE); + CloseThemeData (infoPtr->hTheme); + infoPtr->hTheme = OpenThemeData (NULL, themeClass); + InvalidateRect (infoPtr->hwndSelf, NULL, TRUE); return 0; }
@@ -6945,7 +6941,7 @@ ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) return TOOLBAR_SysColorChange ();
case WM_THEMECHANGED: - return theme_changed (hwnd); + return theme_changed (infoPtr);
/* case WM_WININICHANGE: */