comctl32/toolbar: Don't use outside theme handles.

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>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zhiyi Zhang 2021-06-22 16:21:15 +08:00 committed by Alexandre Julliard
parent 677c459b86
commit 8107462b8a
2 changed files with 16 additions and 22 deletions

View file

@ -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);

View file

@ -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: */