2 * Dialog theming support
4 * Copyright 2022 Zhiyi Zhang for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "uxthemedll.h"
31 extern ATOM atDialogThemeEnabled
;
32 static const WCHAR wine_dialog_brush
[] = L
"wine_dialog_brush";
34 static HBRUSH
get_dialog_background_brush(HWND hwnd
, BOOL create
)
36 HBITMAP bitmap
, old_bitmap
;
48 flag
= HandleToUlong(GetPropW(hwnd
, (LPCWSTR
)MAKEINTATOM(atDialogThemeEnabled
)));
49 if (flag
!= ETDT_ENABLETAB
&& flag
!= ETDT_ENABLEAEROWIZARDTAB
)
52 brush
= GetPropW(hwnd
, wine_dialog_brush
);
59 theme
= OpenThemeData(NULL
, L
"Tab");
63 hr
= GetThemePartSize(theme
, NULL
, TABP_BODY
, 0, NULL
, TS_TRUE
, &size
);
70 hdc_screen
= GetDC(NULL
);
71 hdc
= CreateCompatibleDC(hdc_screen
);
72 bitmap
= CreateCompatibleBitmap(hdc_screen
, size
.cx
, size
.cy
);
73 old_bitmap
= SelectObject(hdc
, bitmap
);
75 SetRect(&rect
, 0, 0, size
.cx
, size
.cy
);
76 /* FIXME: XP draws the tab body bitmap directly without transparency even if there is */
77 FillRect(hdc
, &rect
, GetSysColorBrush(COLOR_3DFACE
));
78 hr
= DrawThemeBackground(theme
, hdc
, TABP_BODY
, 0, &rect
, NULL
);
81 brush
= CreatePatternBrush(bitmap
);
82 SetPropW(hwnd
, wine_dialog_brush
, brush
);
85 SelectObject(hdc
, old_bitmap
);
87 ReleaseDC(NULL
, hdc_screen
);
88 CloseThemeData(theme
);
92 static void destroy_dialog_brush(HWND hwnd
)
97 brush
= GetPropW(hwnd
, wine_dialog_brush
);
100 RemovePropW(hwnd
, wine_dialog_brush
);
101 if (GetObjectW(brush
, sizeof(logbrush
), &logbrush
) == sizeof(logbrush
))
102 DeleteObject((HBITMAP
)logbrush
.lbHatch
);
107 LRESULT WINAPI
UXTHEME_DefDlgProc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
, BOOL unicode
)
120 destroy_dialog_brush(hwnd
);
123 case WM_THEMECHANGED
:
125 destroy_dialog_brush(hwnd
);
126 InvalidateRect(hwnd
, NULL
, TRUE
);
131 dlgproc
= (WNDPROC
)GetWindowLongPtrW(hwnd
, DWLP_DLGPROC
);
132 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 0);
133 lr
= LOWORD(CallWindowProcW(dlgproc
, hwnd
, msg
, wp
, lp
));
134 if (lr
|| !IsWindow(hwnd
))
135 return GetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
);
137 brush
= get_dialog_background_brush(hwnd
, TRUE
);
140 /* Copied from DEFDLG_Proc() */
141 brush
= (HBRUSH
)SendMessageW(hwnd
, WM_CTLCOLORDLG
, wp
, (LPARAM
)hwnd
);
143 brush
= (HBRUSH
)DefWindowProcW(hwnd
, WM_CTLCOLORDLG
, wp
, (LPARAM
)hwnd
);
147 GetClientRect(hwnd
, &rect
);
148 DPtoLP(hdc
, (LPPOINT
)&rect
, 2);
149 FillRect(hdc
, &rect
, brush
);
154 /* Using FillRect() to draw background could introduce a tiling effect if the destination
155 * rectangle is larger than the pattern brush size, which is usually 10x600. This bug is
156 * visible on property sheet pages if system DPI is set to 192. However, the same bug also
157 * exists on XP and explains why vista+ don't use gradient tab body background anymore */
159 GetViewportOrgEx(hdc
, &org
);
160 SetBrushOrgEx(hdc
, org
.x
, org
.y
, &old_org
);
161 GetClientRect(hwnd
, &rect
);
162 FillRect(hdc
, &rect
, brush
);
163 SetBrushOrgEx(hdc
, old_org
.x
, old_org
.y
, NULL
);
166 case WM_CTLCOLORMSGBOX
:
169 case WM_CTLCOLORSTATIC
:
171 dlgproc
= (WNDPROC
)GetWindowLongPtrW(hwnd
, DWLP_DLGPROC
);
172 lr
= CallWindowProcW(dlgproc
, hwnd
, msg
, wp
, lp
);
173 if (lr
|| !IsWindow(hwnd
))
176 brush
= get_dialog_background_brush(hwnd
, FALSE
);
178 return DefWindowProcW(hwnd
, msg
, wp
, lp
);
181 SetBkColor(hdc
, GetSysColor(COLOR_BTNFACE
));
182 SetBkMode(hdc
, TRANSPARENT
);
186 MapWindowPoints((HWND
)lp
, hwnd
, &org
, 1);
187 SetBrushOrgEx(hdc
, -org
.x
, -org
.y
, NULL
);
188 return (LRESULT
)brush
;
192 return user_api
.pDefDlgProc(hwnd
, msg
, wp
, lp
, unicode
);