d3d11/tests: Add some tests for ID3DUserDefinedAnnotation.
[wine.git] / dlls / uxtheme / dialog.c
blob87c2b7d1c13c648db5dd798d826981e852c0d6c6
1 /*
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
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 #include "uxtheme.h"
28 #include "uxthemedll.h"
29 #include "vssym32.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;
37 HDC hdc, hdc_screen;
38 HBRUSH brush;
39 HTHEME theme;
40 DWORD flag;
41 HRESULT hr;
42 RECT rect;
43 SIZE size;
45 if (!IsThemeActive())
46 return NULL;
48 flag = HandleToUlong(GetPropW(hwnd, (LPCWSTR)MAKEINTATOM(atDialogThemeEnabled)));
49 if (flag != ETDT_ENABLETAB && flag != ETDT_ENABLEAEROWIZARDTAB)
50 return NULL;
52 brush = GetPropW(hwnd, wine_dialog_brush);
53 if (brush)
54 return brush;
56 if (!create)
57 return NULL;
59 theme = OpenThemeData(NULL, L"Tab");
60 if (!theme)
61 return NULL;
63 hr = GetThemePartSize(theme, NULL, TABP_BODY, 0, NULL, TS_TRUE, &size);
64 if (FAILED(hr))
66 size.cx = 10;
67 size.cy = 600;
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);
79 if (SUCCEEDED(hr))
81 brush = CreatePatternBrush(bitmap);
82 SetPropW(hwnd, wine_dialog_brush, brush);
85 SelectObject(hdc, old_bitmap);
86 DeleteDC(hdc);
87 ReleaseDC(NULL, hdc_screen);
88 CloseThemeData(theme);
89 return brush;
92 static void destroy_dialog_brush(HWND hwnd)
94 LOGBRUSH logbrush;
95 HBRUSH brush;
97 brush = GetPropW(hwnd, wine_dialog_brush);
98 if (brush)
100 RemovePropW(hwnd, wine_dialog_brush);
101 if (GetObjectW(brush, sizeof(logbrush), &logbrush) == sizeof(logbrush))
102 DeleteObject((HBITMAP)logbrush.lbHatch);
103 DeleteObject(brush);
107 LRESULT WINAPI UXTHEME_DefDlgProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, BOOL unicode)
109 POINT org, old_org;
110 WNDPROC dlgproc;
111 HBRUSH brush;
112 LRESULT lr;
113 RECT rect;
114 HDC hdc;
116 switch (msg)
118 case WM_NCDESTROY:
120 destroy_dialog_brush(hwnd);
121 break;
123 case WM_THEMECHANGED:
125 destroy_dialog_brush(hwnd);
126 InvalidateRect(hwnd, NULL, TRUE);
127 break;
129 case WM_ERASEBKGND:
131 dlgproc = (WNDPROC)GetWindowLongPtrW(hwnd, DWLP_DLGPROC);
132 lr = CallWindowProcW(dlgproc, hwnd, msg, wp, lp);
133 if (lr)
134 return lr;
136 brush = get_dialog_background_brush(hwnd, TRUE);
137 if (!brush)
138 break;
140 /* Using FillRect() to draw background could introduce a tiling effect if the destination
141 * rectangle is larger than the pattern brush size, which is usually 10x600. This bug is
142 * visible on property sheet pages if system DPI is set to 192. However, the same bug also
143 * exists on XP and explains why vista+ don't use gradient tab body background anymore */
144 hdc = (HDC)wp;
145 GetViewportOrgEx(hdc, &org);
146 SetBrushOrgEx(hdc, org.x, org.y, &old_org);
147 GetClientRect(hwnd, &rect);
148 FillRect(hdc, &rect, brush);
149 SetBrushOrgEx(hdc, old_org.x, old_org.y, NULL);
150 return TRUE;
152 case WM_CTLCOLORSTATIC:
154 dlgproc = (WNDPROC)GetWindowLongPtrW(hwnd, DWLP_DLGPROC);
155 lr = CallWindowProcW(dlgproc, hwnd, msg, wp, lp);
156 if (lr)
157 return lr;
159 brush = get_dialog_background_brush(hwnd, FALSE);
160 if (!brush)
161 break;
163 hdc = (HDC)wp;
164 SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
165 SetBkMode(hdc, TRANSPARENT);
167 org.x = 0;
168 org.y = 0;
169 MapWindowPoints((HWND)lp, hwnd, &org, 1);
170 SetBrushOrgEx(hdc, -org.x, -org.y, NULL);
171 return (LRESULT)brush;
175 return user_api.pDefDlgProc(hwnd, msg, wp, lp, unicode);