|
1
|
1 // Windows Template Library - WTL version 10.0
|
|
|
2 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
|
|
|
3 //
|
|
|
4 // This file is a part of the Windows Template Library.
|
|
|
5 // The use and distribution terms for this software are covered by the
|
|
|
6 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
|
|
|
7 // which can be found in the file MS-PL.txt at the root folder.
|
|
|
8
|
|
|
9 #ifndef __ATLTHEME_H__
|
|
|
10 #define __ATLTHEME_H__
|
|
|
11
|
|
|
12 #pragma once
|
|
|
13
|
|
|
14 #ifndef __ATLAPP_H__
|
|
|
15 #error atltheme.h requires atlapp.h to be included first
|
|
|
16 #endif
|
|
|
17
|
|
|
18 #ifndef __ATLWIN_H__
|
|
|
19 #error atltheme.h requires atlwin.h to be included first
|
|
|
20 #endif
|
|
|
21
|
|
|
22 #include <vssym32.h>
|
|
|
23
|
|
|
24 // Note: To create an application that also runs on older versions of Windows,
|
|
|
25 // use delay load of uxtheme.dll and ensure that no calls to the Theme API are
|
|
|
26 // made if theming is not supported. It is enough to check if m_hTheme is NULL.
|
|
|
27 // Example:
|
|
|
28 // if(m_hTheme != NULL)
|
|
|
29 // {
|
|
|
30 // DrawThemeBackground(dc, BP_PUSHBUTTON, PBS_NORMAL, &rect, NULL);
|
|
|
31 // DrawThemeText(dc, BP_PUSHBUTTON, PBS_NORMAL, L"Button", -1, DT_SINGLELINE | DT_CENTER | DT_VCENTER, 0, &rect);
|
|
|
32 // }
|
|
|
33 // else
|
|
|
34 // {
|
|
|
35 // dc.DrawFrameControl(&rect, DFC_BUTTON, DFCS_BUTTONPUSH);
|
|
|
36 // dc.DrawText(_T("Button"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
|
|
|
37 // }
|
|
|
38 //
|
|
|
39 // Delay load is NOT AUTOMATIC for VC++ 7, you have to link to delayimp.lib,
|
|
|
40 // and add uxtheme.dll in the Linker.Input.Delay Loaded DLLs section of the
|
|
|
41 // project properties.
|
|
|
42
|
|
|
43
|
|
|
44 ///////////////////////////////////////////////////////////////////////////////
|
|
|
45 // Classes in this file:
|
|
|
46 //
|
|
|
47 // CTheme
|
|
|
48 // CThemeImpl<T, TBase>
|
|
|
49 //
|
|
|
50 // CBufferedPaint
|
|
|
51 // CBufferedPaintImpl<T>
|
|
|
52 // CBufferedPaintWindowImpl<T, TBase, TWinTraits>
|
|
|
53 // CBufferedAnimation
|
|
|
54 // CBufferedAnimationImpl<T, TState>
|
|
|
55 // CBufferedAnimationWindowImpl<T, TState, TBase, TWinTraits>
|
|
|
56 //
|
|
|
57 // Global functions:
|
|
|
58 // AtlDrawThemeClientEdge()
|
|
|
59
|
|
|
60
|
|
|
61 namespace WTL
|
|
|
62 {
|
|
|
63
|
|
|
64 ///////////////////////////////////////////////////////////////////////////////
|
|
|
65 // CTheme - wrapper for theme handle
|
|
|
66
|
|
|
67 class CTheme
|
|
|
68 {
|
|
|
69 public:
|
|
|
70 // Data members
|
|
|
71 HTHEME m_hTheme;
|
|
|
72 static int m_nIsThemingSupported;
|
|
|
73
|
|
|
74 // Constructor
|
|
|
75 CTheme(HTHEME hTheme = NULL) : m_hTheme(hTheme)
|
|
|
76 {
|
|
|
77 IsThemingSupported();
|
|
|
78 }
|
|
|
79
|
|
|
80 // Operators and helpers
|
|
|
81 bool IsThemeNull() const
|
|
|
82 {
|
|
|
83 return (m_hTheme == NULL);
|
|
|
84 }
|
|
|
85
|
|
|
86 CTheme& operator =(HTHEME hTheme)
|
|
|
87 {
|
|
|
88 m_hTheme = hTheme;
|
|
|
89 return *this;
|
|
|
90 }
|
|
|
91
|
|
|
92 operator HTHEME() const
|
|
|
93 {
|
|
|
94 return m_hTheme;
|
|
|
95 }
|
|
|
96
|
|
|
97 void Attach(HTHEME hTheme)
|
|
|
98 {
|
|
|
99 m_hTheme = hTheme;
|
|
|
100 }
|
|
|
101
|
|
|
102 HTHEME Detach()
|
|
|
103 {
|
|
|
104 HTHEME hTheme = m_hTheme;
|
|
|
105 m_hTheme = NULL;
|
|
|
106 return hTheme;
|
|
|
107 }
|
|
|
108
|
|
|
109 // Theme support helper
|
|
|
110 static bool IsThemingSupported()
|
|
|
111 {
|
|
|
112 if(m_nIsThemingSupported == -1)
|
|
|
113 {
|
|
|
114 CStaticDataInitCriticalSectionLock lock;
|
|
|
115 if(FAILED(lock.Lock()))
|
|
|
116 {
|
|
|
117 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CTheme::IsThemingSupported.\n"));
|
|
|
118 ATLASSERT(FALSE);
|
|
|
119 return false;
|
|
|
120 }
|
|
|
121
|
|
|
122 if(m_nIsThemingSupported == -1)
|
|
|
123 {
|
|
|
124 HMODULE hThemeDLL = ::LoadLibrary(_T("uxtheme.dll"));
|
|
|
125 m_nIsThemingSupported = (hThemeDLL != NULL) ? 1 : 0;
|
|
|
126 if(hThemeDLL != NULL)
|
|
|
127 ::FreeLibrary(hThemeDLL);
|
|
|
128 }
|
|
|
129
|
|
|
130 lock.Unlock();
|
|
|
131 }
|
|
|
132
|
|
|
133 ATLASSERT(m_nIsThemingSupported != -1);
|
|
|
134 return (m_nIsThemingSupported == 1);
|
|
|
135 }
|
|
|
136
|
|
|
137 // Operations and theme properties
|
|
|
138 HTHEME OpenThemeData(HWND hWnd, LPCWSTR pszClassList)
|
|
|
139 {
|
|
|
140 if(!IsThemingSupported())
|
|
|
141 return NULL;
|
|
|
142
|
|
|
143 ATLASSERT(m_hTheme == NULL);
|
|
|
144 m_hTheme = ::OpenThemeData(hWnd, pszClassList);
|
|
|
145 return m_hTheme;
|
|
|
146 }
|
|
|
147
|
|
|
148 HRESULT CloseThemeData()
|
|
|
149 {
|
|
|
150 HRESULT hRet = S_FALSE;
|
|
|
151 if(m_hTheme != NULL)
|
|
|
152 {
|
|
|
153 hRet = ::CloseThemeData(m_hTheme);
|
|
|
154 if(SUCCEEDED(hRet))
|
|
|
155 m_hTheme = NULL;
|
|
|
156 }
|
|
|
157 return hRet;
|
|
|
158 }
|
|
|
159
|
|
|
160 HRESULT DrawThemeBackground(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, LPCRECT pClipRect = NULL)
|
|
|
161 {
|
|
|
162 ATLASSERT(m_hTheme != NULL);
|
|
|
163 return ::DrawThemeBackground(m_hTheme, hDC, nPartID, nStateID, pRect, pClipRect);
|
|
|
164 }
|
|
|
165
|
|
|
166 // Missing in original uxtheme.h
|
|
|
167 #ifdef DTBG_CLIPRECT
|
|
|
168 HRESULT DrawThemeBackgroundEx(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, const DTBGOPTS* pOptions = NULL)
|
|
|
169 {
|
|
|
170 ATLASSERT(m_hTheme != NULL);
|
|
|
171 return ::DrawThemeBackgroundEx(m_hTheme, hDC, nPartID, nStateID, pRect, pOptions);
|
|
|
172 }
|
|
|
173 #endif // DTBG_CLIPRECT
|
|
|
174
|
|
|
175 HRESULT DrawThemeText(HDC hDC, int nPartID, int nStateID, LPCWSTR pszText, int nCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, LPCRECT pRect)
|
|
|
176 {
|
|
|
177 ATLASSERT(m_hTheme != NULL);
|
|
|
178 return ::DrawThemeText(m_hTheme, hDC, nPartID, nStateID, pszText, nCharCount, dwTextFlags, dwTextFlags2, pRect);
|
|
|
179 }
|
|
|
180
|
|
|
181 HRESULT GetThemeBackgroundContentRect(HDC hDC, int nPartID, int nStateID, LPCRECT pBoundingRect, LPRECT pContentRect) const
|
|
|
182 {
|
|
|
183 ATLASSERT(m_hTheme != NULL);
|
|
|
184 return ::GetThemeBackgroundContentRect(m_hTheme, hDC, nPartID, nStateID, pBoundingRect, pContentRect);
|
|
|
185 }
|
|
|
186
|
|
|
187 HRESULT GetThemeBackgroundExtent(HDC hDC, int nPartID, int nStateID, LPCRECT pContentRect, LPRECT pExtentRect) const
|
|
|
188 {
|
|
|
189 ATLASSERT(m_hTheme != NULL);
|
|
|
190 return ::GetThemeBackgroundExtent(m_hTheme, hDC, nPartID, nStateID, pContentRect, pExtentRect);
|
|
|
191 }
|
|
|
192
|
|
|
193 HRESULT GetThemePartSize(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, enum THEMESIZE eSize, LPSIZE pSize) const
|
|
|
194 {
|
|
|
195 ATLASSERT(m_hTheme != NULL);
|
|
|
196 return ::GetThemePartSize(m_hTheme, hDC, nPartID, nStateID, pRect, eSize, pSize);
|
|
|
197 }
|
|
|
198
|
|
|
199 HRESULT GetThemeTextExtent(HDC hDC, int nPartID, int nStateID, LPCWSTR pszText, int nCharCount, DWORD dwTextFlags, LPCRECT pBoundingRect, LPRECT pExtentRect) const
|
|
|
200 {
|
|
|
201 ATLASSERT(m_hTheme != NULL);
|
|
|
202 return ::GetThemeTextExtent(m_hTheme, hDC, nPartID, nStateID, pszText, nCharCount, dwTextFlags, pBoundingRect, pExtentRect);
|
|
|
203 }
|
|
|
204
|
|
|
205 HRESULT GetThemeTextMetrics(HDC hDC, int nPartID, int nStateID, PTEXTMETRICW pTextMetric) const
|
|
|
206 {
|
|
|
207 ATLASSERT(m_hTheme != NULL);
|
|
|
208 return ::GetThemeTextMetrics(m_hTheme, hDC, nPartID, nStateID, pTextMetric);
|
|
|
209 }
|
|
|
210
|
|
|
211 HRESULT GetThemeBackgroundRegion(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, HRGN* pRegion) const
|
|
|
212 {
|
|
|
213 ATLASSERT(m_hTheme != NULL);
|
|
|
214 return ::GetThemeBackgroundRegion(m_hTheme, hDC, nPartID, nStateID, pRect, pRegion);
|
|
|
215 }
|
|
|
216
|
|
|
217 HRESULT HitTestThemeBackground(HDC hDC, int nPartID, int nStateID, DWORD dwOptions, LPCRECT pRect, HRGN hrgn, POINT ptTest, WORD* pwHitTestCode) const
|
|
|
218 {
|
|
|
219 ATLASSERT(m_hTheme != NULL);
|
|
|
220 return ::HitTestThemeBackground(m_hTheme, hDC, nPartID, nStateID, dwOptions, pRect, hrgn, ptTest, pwHitTestCode);
|
|
|
221 }
|
|
|
222
|
|
|
223 HRESULT DrawThemeEdge(HDC hDC, int nPartID, int nStateID, LPCRECT pDestRect, UINT uEdge, UINT uFlags, LPRECT pContentRect = NULL)
|
|
|
224 {
|
|
|
225 ATLASSERT(m_hTheme != NULL);
|
|
|
226 return ::DrawThemeEdge(m_hTheme, hDC, nPartID, nStateID, pDestRect, uEdge, uFlags, pContentRect);
|
|
|
227 }
|
|
|
228
|
|
|
229 HRESULT DrawThemeIcon(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, HIMAGELIST himl, int nImageIndex)
|
|
|
230 {
|
|
|
231 ATLASSERT(m_hTheme != NULL);
|
|
|
232 return ::DrawThemeIcon(m_hTheme, hDC, nPartID, nStateID, pRect, himl, nImageIndex);
|
|
|
233 }
|
|
|
234
|
|
|
235 BOOL IsThemePartDefined(int nPartID, int nStateID) const
|
|
|
236 {
|
|
|
237 ATLASSERT(m_hTheme != NULL);
|
|
|
238 return ::IsThemePartDefined(m_hTheme, nPartID, nStateID);
|
|
|
239 }
|
|
|
240
|
|
|
241 BOOL IsThemeBackgroundPartiallyTransparent(int nPartID, int nStateID) const
|
|
|
242 {
|
|
|
243 ATLASSERT(m_hTheme != NULL);
|
|
|
244 return ::IsThemeBackgroundPartiallyTransparent(m_hTheme, nPartID, nStateID);
|
|
|
245 }
|
|
|
246
|
|
|
247 HRESULT GetThemeColor(int nPartID, int nStateID, int nPropID, COLORREF* pColor) const
|
|
|
248 {
|
|
|
249 ATLASSERT(m_hTheme != NULL);
|
|
|
250 return ::GetThemeColor(m_hTheme, nPartID, nStateID, nPropID, pColor);
|
|
|
251 }
|
|
|
252
|
|
|
253 HRESULT GetThemeMetric(HDC hDC, int nPartID, int nStateID, int nPropID, int* pnVal) const
|
|
|
254 {
|
|
|
255 ATLASSERT(m_hTheme != NULL);
|
|
|
256 return ::GetThemeMetric(m_hTheme, hDC, nPartID, nStateID, nPropID, pnVal);
|
|
|
257 }
|
|
|
258
|
|
|
259 HRESULT GetThemeString(int nPartID, int nStateID, int nPropID, LPWSTR pszBuff, int cchMaxBuffChars) const
|
|
|
260 {
|
|
|
261 ATLASSERT(m_hTheme != NULL);
|
|
|
262 return ::GetThemeString(m_hTheme, nPartID, nStateID, nPropID, pszBuff, cchMaxBuffChars);
|
|
|
263 }
|
|
|
264
|
|
|
265 HRESULT GetThemeBool(int nPartID, int nStateID, int nPropID, BOOL* pfVal) const
|
|
|
266 {
|
|
|
267 ATLASSERT(m_hTheme != NULL);
|
|
|
268 return ::GetThemeBool(m_hTheme, nPartID, nStateID, nPropID, pfVal);
|
|
|
269 }
|
|
|
270
|
|
|
271 HRESULT GetThemeInt(int nPartID, int nStateID, int nPropID, int* pnVal) const
|
|
|
272 {
|
|
|
273 ATLASSERT(m_hTheme != NULL);
|
|
|
274 return ::GetThemeInt(m_hTheme, nPartID, nStateID, nPropID, pnVal);
|
|
|
275 }
|
|
|
276
|
|
|
277 HRESULT GetThemeEnumValue(int nPartID, int nStateID, int nPropID, int* pnVal) const
|
|
|
278 {
|
|
|
279 ATLASSERT(m_hTheme != NULL);
|
|
|
280 return ::GetThemeEnumValue(m_hTheme, nPartID, nStateID, nPropID, pnVal);
|
|
|
281 }
|
|
|
282
|
|
|
283 HRESULT GetThemePosition(int nPartID, int nStateID, int nPropID, LPPOINT pPoint) const
|
|
|
284 {
|
|
|
285 ATLASSERT(m_hTheme != NULL);
|
|
|
286 return ::GetThemePosition(m_hTheme, nPartID, nStateID, nPropID, pPoint);
|
|
|
287 }
|
|
|
288
|
|
|
289 // deprecated
|
|
|
290 HRESULT GetThemeFont(int nPartID, HDC hDC, int nStateID, int nPropID, LOGFONTW* pFont) const
|
|
|
291 {
|
|
|
292 ATLASSERT(m_hTheme != NULL);
|
|
|
293 return ::GetThemeFont(m_hTheme, hDC, nPartID, nStateID, nPropID, pFont);
|
|
|
294 }
|
|
|
295
|
|
|
296 HRESULT GetThemeFont(HDC hDC, int nPartID, int nStateID, int nPropID, LOGFONTW* pFont) const
|
|
|
297 {
|
|
|
298 ATLASSERT(m_hTheme != NULL);
|
|
|
299 return ::GetThemeFont(m_hTheme, hDC, nPartID, nStateID, nPropID, pFont);
|
|
|
300 }
|
|
|
301
|
|
|
302 HRESULT GetThemeRect(int nPartID, int nStateID, int nPropID, LPRECT pRect) const
|
|
|
303 {
|
|
|
304 ATLASSERT(m_hTheme != NULL);
|
|
|
305 return ::GetThemeRect(m_hTheme, nPartID, nStateID, nPropID, pRect);
|
|
|
306 }
|
|
|
307
|
|
|
308 HRESULT GetThemeMargins(HDC hDC, int nPartID, int nStateID, int nPropID, LPRECT pRect, PMARGINS pMargins) const
|
|
|
309 {
|
|
|
310 ATLASSERT(m_hTheme != NULL);
|
|
|
311 return ::GetThemeMargins(m_hTheme, hDC, nPartID, nStateID, nPropID, pRect, pMargins);
|
|
|
312 }
|
|
|
313
|
|
|
314 HRESULT GetThemeIntList(int nPartID, int nStateID, int nPropID, INTLIST* pIntList) const
|
|
|
315 {
|
|
|
316 ATLASSERT(m_hTheme != NULL);
|
|
|
317 return ::GetThemeIntList(m_hTheme, nPartID, nStateID, nPropID, pIntList);
|
|
|
318 }
|
|
|
319
|
|
|
320 HRESULT GetThemePropertyOrigin(int nPartID, int nStateID, int nPropID, enum PROPERTYORIGIN* pOrigin) const
|
|
|
321 {
|
|
|
322 ATLASSERT(m_hTheme != NULL);
|
|
|
323 return ::GetThemePropertyOrigin(m_hTheme, nPartID, nStateID, nPropID, pOrigin);
|
|
|
324 }
|
|
|
325
|
|
|
326 HRESULT GetThemeFilename(int nPartID, int nStateID, int nPropID, LPWSTR pszThemeFileName, int cchMaxBuffChars) const
|
|
|
327 {
|
|
|
328 ATLASSERT(m_hTheme != NULL);
|
|
|
329 return ::GetThemeFilename(m_hTheme, nPartID, nStateID, nPropID, pszThemeFileName, cchMaxBuffChars);
|
|
|
330 }
|
|
|
331
|
|
|
332 COLORREF GetThemeSysColor(int nColorID) const
|
|
|
333 {
|
|
|
334 ATLASSERT(m_hTheme != NULL);
|
|
|
335 return ::GetThemeSysColor(m_hTheme, nColorID);
|
|
|
336 }
|
|
|
337
|
|
|
338 HBRUSH GetThemeSysColorBrush(int nColorID) const
|
|
|
339 {
|
|
|
340 ATLASSERT(m_hTheme != NULL);
|
|
|
341 return ::GetThemeSysColorBrush(m_hTheme, nColorID);
|
|
|
342 }
|
|
|
343
|
|
|
344 int GetThemeSysSize(int nSizeID) const
|
|
|
345 {
|
|
|
346 ATLASSERT(m_hTheme != NULL);
|
|
|
347 return ::GetThemeSysSize(m_hTheme, nSizeID);
|
|
|
348 }
|
|
|
349
|
|
|
350 BOOL GetThemeSysBool(int nBoolID) const
|
|
|
351 {
|
|
|
352 ATLASSERT(m_hTheme != NULL);
|
|
|
353 return ::GetThemeSysBool(m_hTheme, nBoolID);
|
|
|
354 }
|
|
|
355
|
|
|
356 HRESULT GetThemeSysFont(int nFontID, LOGFONTW* plf) const
|
|
|
357 {
|
|
|
358 ATLASSERT(m_hTheme != NULL);
|
|
|
359 return ::GetThemeSysFont(m_hTheme, nFontID, plf);
|
|
|
360 }
|
|
|
361
|
|
|
362 HRESULT GetThemeSysString(int nStringID, LPWSTR pszStringBuff, int cchMaxStringChars) const
|
|
|
363 {
|
|
|
364 ATLASSERT(m_hTheme != NULL);
|
|
|
365 return ::GetThemeSysString(m_hTheme, nStringID, pszStringBuff, cchMaxStringChars);
|
|
|
366 }
|
|
|
367
|
|
|
368 HRESULT GetThemeSysInt(int nIntID, int* pnValue) const
|
|
|
369 {
|
|
|
370 ATLASSERT(m_hTheme != NULL);
|
|
|
371 return ::GetThemeSysInt(m_hTheme, nIntID, pnValue);
|
|
|
372 }
|
|
|
373
|
|
|
374 HTHEME OpenThemeDataEx(HWND hWnd, LPCWSTR pszClassList, DWORD dwFlags)
|
|
|
375 {
|
|
|
376 if(!IsThemingSupported())
|
|
|
377 return NULL;
|
|
|
378
|
|
|
379 ATLASSERT(m_hTheme == NULL);
|
|
|
380 m_hTheme = ::OpenThemeDataEx(hWnd, pszClassList, dwFlags);
|
|
|
381 return m_hTheme;
|
|
|
382 }
|
|
|
383
|
|
|
384 #if (_WIN32_WINNT >= 0x0600)
|
|
|
385 HRESULT DrawThemeTextEx(HDC hDC, int nPartID, int nStateID, LPCWSTR pszText, int cchText, DWORD dwTextFlags, LPRECT lpRect, const DTTOPTS* pOptions)
|
|
|
386 {
|
|
|
387 ATLASSERT(m_hTheme != NULL);
|
|
|
388 return ::DrawThemeTextEx(m_hTheme, hDC, nPartID, nStateID, pszText, cchText, dwTextFlags, lpRect, pOptions);
|
|
|
389 }
|
|
|
390
|
|
|
391 HRESULT GetThemeTransitionDuration(int nPartID, int nFromStateID, int nToStateID, int nPropID, DWORD& dwDuration)
|
|
|
392 {
|
|
|
393 ATLASSERT(m_hTheme != NULL);
|
|
|
394 return ::GetThemeTransitionDuration(m_hTheme, nPartID, nFromStateID, nToStateID, nPropID, &dwDuration);
|
|
|
395 }
|
|
|
396 #endif // (_WIN32_WINNT >= 0x0600)
|
|
|
397
|
|
|
398 #if (_WIN32_WINNT >= 0x0600)
|
|
|
399 HRESULT GetThemeBitmap(int nPartID, int nStateID, int nPropID, ULONG uFlags, HBITMAP& hBitmap)
|
|
|
400 {
|
|
|
401 ATLASSERT(m_hTheme != NULL);
|
|
|
402 return ::GetThemeBitmap(m_hTheme, nPartID, nStateID, nPropID, uFlags, &hBitmap);
|
|
|
403 }
|
|
|
404
|
|
|
405 HRESULT GetThemeStream(int nPartID, int nStateID, int nPropID, VOID** ppvStream, DWORD* pcbStream, HINSTANCE hInstance)
|
|
|
406 {
|
|
|
407 ATLASSERT(m_hTheme != NULL);
|
|
|
408 return ::GetThemeStream(m_hTheme, nPartID, nStateID, nPropID, ppvStream, pcbStream, hInstance);
|
|
|
409 }
|
|
|
410 #endif // (_WIN32_WINNT >= 0x0600)
|
|
|
411
|
|
|
412 #if (_WIN32_WINNT >= 0x0602)
|
|
|
413 HRESULT GetThemeAnimationProperty(int iStoryboardId, int iTargetId, TA_PROPERTY eProperty, VOID* pvProperty, DWORD cbSize, DWORD* pcbSizeOut)
|
|
|
414 {
|
|
|
415 ATLASSERT(m_hTheme != NULL);
|
|
|
416 return ::GetThemeAnimationProperty(m_hTheme, iStoryboardId, iTargetId, eProperty, pvProperty, cbSize, pcbSizeOut);
|
|
|
417 }
|
|
|
418
|
|
|
419 HRESULT GetThemeAnimationTransform(int iStoryboardId, int iTargetId, DWORD dwTransformIndex, TA_TRANSFORM* pTransform, DWORD cbSize, DWORD* pcbSizeOut)
|
|
|
420 {
|
|
|
421 ATLASSERT(m_hTheme != NULL);
|
|
|
422 return ::GetThemeAnimationTransform(m_hTheme, iStoryboardId, iTargetId, dwTransformIndex, pTransform, cbSize, pcbSizeOut);
|
|
|
423 }
|
|
|
424
|
|
|
425 HRESULT GetThemeTimingFunction(int iTimingFunctionId, TA_TIMINGFUNCTION* pTimingFunction, DWORD cbSize, DWORD* pcbSizeOut)
|
|
|
426 {
|
|
|
427 ATLASSERT(m_hTheme != NULL);
|
|
|
428 return ::GetThemeTimingFunction(m_hTheme, iTimingFunctionId, pTimingFunction, cbSize, pcbSizeOut);
|
|
|
429 }
|
|
|
430 #endif // (_WIN32_WINNT >= 0x0602)
|
|
|
431 };
|
|
|
432
|
|
|
433 __declspec(selectany) int CTheme::m_nIsThemingSupported = -1;
|
|
|
434
|
|
|
435
|
|
|
436 ///////////////////////////////////////////////////////////////////////////////
|
|
|
437 // CThemeImpl - theme support implementation
|
|
|
438
|
|
|
439 // Derive from this class to implement window with theme support.
|
|
|
440 // Example:
|
|
|
441 // class CMyThemeWindow : public CWindowImpl<CMyThemeWindow>, public CThemeImpl<CMyThemeWindow>
|
|
|
442 // {
|
|
|
443 // ...
|
|
|
444 // BEGIN_MSG_MAP(CMyThemeWindow)
|
|
|
445 // CHAIN_MSG_MAP(CThemeImpl<CMyThemeWindow>)
|
|
|
446 // ...
|
|
|
447 // END_MSG_MAP()
|
|
|
448 // ...
|
|
|
449 // };
|
|
|
450 //
|
|
|
451 // If you set theme class list, the class will automaticaly open/close/reopen theme data.
|
|
|
452
|
|
|
453
|
|
|
454 // Helper for drawing theme client edge
|
|
|
455 inline bool AtlDrawThemeClientEdge(HTHEME hTheme, HWND hWnd, HRGN hRgnUpdate = NULL, HBRUSH hBrush = NULL, int nPartID = 0, int nStateID = 0)
|
|
|
456 {
|
|
|
457 ATLASSERT(hTheme != NULL);
|
|
|
458 ATLASSERT(::IsWindow(hWnd));
|
|
|
459
|
|
|
460 CWindowDC dc(hWnd);
|
|
|
461 if(dc.IsNull())
|
|
|
462 return false;
|
|
|
463
|
|
|
464 // Get border size
|
|
|
465 int cxBorder = ::GetSystemMetrics(SM_CXBORDER);
|
|
|
466 int cyBorder = ::GetSystemMetrics(SM_CYBORDER);
|
|
|
467 if(SUCCEEDED(::GetThemeInt(hTheme, nPartID, nStateID, TMT_SIZINGBORDERWIDTH, &cxBorder)))
|
|
|
468 cyBorder = cxBorder;
|
|
|
469
|
|
|
470 RECT rect = {};
|
|
|
471 ::GetWindowRect(hWnd, &rect);
|
|
|
472
|
|
|
473 // Remove the client edge from the update region
|
|
|
474 int cxEdge = ::GetSystemMetrics(SM_CXEDGE);
|
|
|
475 int cyEdge = ::GetSystemMetrics(SM_CYEDGE);
|
|
|
476 ::InflateRect(&rect, -cxEdge, -cyEdge);
|
|
|
477 CRgn rgn;
|
|
|
478 rgn.CreateRectRgnIndirect(&rect);
|
|
|
479 if(rgn.IsNull())
|
|
|
480 return false;
|
|
|
481
|
|
|
482 if(hRgnUpdate != NULL)
|
|
|
483 rgn.CombineRgn(hRgnUpdate, rgn, RGN_AND);
|
|
|
484
|
|
|
485 ::OffsetRect(&rect, -rect.left, -rect.top);
|
|
|
486
|
|
|
487 ::OffsetRect(&rect, cxEdge, cyEdge);
|
|
|
488 dc.ExcludeClipRect(&rect);
|
|
|
489 ::InflateRect(&rect, cxEdge, cyEdge);
|
|
|
490
|
|
|
491 ::DrawThemeBackground(hTheme, dc, nPartID, nStateID, &rect, NULL);
|
|
|
492
|
|
|
493 // Use background brush too, since theme border might not cover everything
|
|
|
494 if((cxBorder < cxEdge) && (cyBorder < cyEdge))
|
|
|
495 {
|
|
|
496 if(hBrush == NULL)
|
|
|
497 hBrush = (HBRUSH)::GetClassLongPtr(hWnd, GCLP_HBRBACKGROUND);
|
|
|
498
|
|
|
499 ::InflateRect(&rect, cxBorder - cxEdge, cyBorder - cyEdge);
|
|
|
500 dc.FillRect(&rect, hBrush);
|
|
|
501 }
|
|
|
502
|
|
|
503 ::DefWindowProc(hWnd, WM_NCPAINT, (WPARAM)rgn.m_hRgn, 0L);
|
|
|
504
|
|
|
505 return true;
|
|
|
506 }
|
|
|
507
|
|
|
508
|
|
|
509 // Theme extended styles
|
|
|
510 #define THEME_EX_3DCLIENTEDGE 0x00000001
|
|
|
511 #define THEME_EX_THEMECLIENTEDGE 0x00000002
|
|
|
512
|
|
|
513 template <class T, class TBase = CTheme>
|
|
|
514 class CThemeImpl : public TBase
|
|
|
515 {
|
|
|
516 public:
|
|
|
517 // Data members
|
|
|
518 LPWSTR m_lpstrThemeClassList;
|
|
|
519 DWORD m_dwExtendedStyle; // theme specific extended styles
|
|
|
520
|
|
|
521 // Constructor & destructor
|
|
|
522 CThemeImpl() : m_lpstrThemeClassList(NULL), m_dwExtendedStyle(0)
|
|
|
523 { }
|
|
|
524
|
|
|
525 ~CThemeImpl()
|
|
|
526 {
|
|
|
527 delete [] m_lpstrThemeClassList;
|
|
|
528 }
|
|
|
529
|
|
|
530 // Attributes
|
|
|
531 bool SetThemeClassList(LPCWSTR lpstrThemeClassList)
|
|
|
532 {
|
|
|
533 if(m_lpstrThemeClassList != NULL)
|
|
|
534 {
|
|
|
535 delete [] m_lpstrThemeClassList;
|
|
|
536 m_lpstrThemeClassList = NULL;
|
|
|
537 }
|
|
|
538
|
|
|
539 if(lpstrThemeClassList == NULL)
|
|
|
540 return true;
|
|
|
541
|
|
|
542 int cchLen = lstrlenW(lpstrThemeClassList) + 1;
|
|
|
543 ATLTRY(m_lpstrThemeClassList = new WCHAR[cchLen]);
|
|
|
544 if(m_lpstrThemeClassList == NULL)
|
|
|
545 return false;
|
|
|
546
|
|
|
547 ATL::Checked::wcscpy_s(m_lpstrThemeClassList, cchLen, lpstrThemeClassList);
|
|
|
548
|
|
|
549 return true;
|
|
|
550 }
|
|
|
551
|
|
|
552 bool GetThemeClassList(LPWSTR lpstrThemeClassList, int cchListBuffer) const
|
|
|
553 {
|
|
|
554 int cchLen = lstrlenW(m_lpstrThemeClassList) + 1;
|
|
|
555 if(cchListBuffer < cchLen)
|
|
|
556 return false;
|
|
|
557
|
|
|
558 ATL::Checked::wcscpy_s(lpstrThemeClassList, cchListBuffer, m_lpstrThemeClassList);
|
|
|
559
|
|
|
560 return true;
|
|
|
561 }
|
|
|
562
|
|
|
563 LPCWSTR GetThemeClassList() const
|
|
|
564 {
|
|
|
565 return m_lpstrThemeClassList;
|
|
|
566 }
|
|
|
567
|
|
|
568 DWORD SetThemeExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
|
|
|
569 {
|
|
|
570 DWORD dwPrevStyle = m_dwExtendedStyle;
|
|
|
571 if(dwMask == 0)
|
|
|
572 m_dwExtendedStyle = dwExtendedStyle;
|
|
|
573 else
|
|
|
574 m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
|
|
|
575
|
|
|
576 return dwPrevStyle;
|
|
|
577 }
|
|
|
578
|
|
|
579 DWORD GetThemeExtendedStyle() const
|
|
|
580 {
|
|
|
581 return m_dwExtendedStyle;
|
|
|
582 }
|
|
|
583
|
|
|
584 // Operations
|
|
|
585 HTHEME OpenThemeData()
|
|
|
586 {
|
|
|
587 T* pT = static_cast<T*>(this);
|
|
|
588 ATLASSERT(::IsWindow(pT->m_hWnd));
|
|
|
589 ATLASSERT(m_lpstrThemeClassList != NULL);
|
|
|
590 if(m_lpstrThemeClassList == NULL)
|
|
|
591 return NULL;
|
|
|
592 this->CloseThemeData();
|
|
|
593
|
|
|
594 return TBase::OpenThemeData(pT->m_hWnd, m_lpstrThemeClassList);
|
|
|
595 }
|
|
|
596
|
|
|
597 HTHEME OpenThemeData(LPCWSTR pszClassList)
|
|
|
598 {
|
|
|
599 if(!SetThemeClassList(pszClassList))
|
|
|
600 return NULL;
|
|
|
601
|
|
|
602 return OpenThemeData();
|
|
|
603 }
|
|
|
604
|
|
|
605 HRESULT SetWindowTheme(LPCWSTR pszSubAppName, LPCWSTR pszSubIDList)
|
|
|
606 {
|
|
|
607 if(!this->IsThemingSupported())
|
|
|
608 return S_FALSE;
|
|
|
609
|
|
|
610 T* pT = static_cast<T*>(this);
|
|
|
611 ATLASSERT(::IsWindow(pT->m_hWnd));
|
|
|
612 return ::SetWindowTheme(pT->m_hWnd, pszSubAppName, pszSubIDList);
|
|
|
613 }
|
|
|
614
|
|
|
615 HTHEME GetWindowTheme() const
|
|
|
616 {
|
|
|
617 if(!this->IsThemingSupported())
|
|
|
618 return NULL;
|
|
|
619
|
|
|
620 const T* pT = static_cast<const T*>(this);
|
|
|
621 ATLASSERT(::IsWindow(pT->m_hWnd));
|
|
|
622 return ::GetWindowTheme(pT->m_hWnd);
|
|
|
623 }
|
|
|
624
|
|
|
625 HRESULT EnableThemeDialogTexture(DWORD dwFlags)
|
|
|
626 {
|
|
|
627 if(!this->IsThemingSupported())
|
|
|
628 return S_FALSE;
|
|
|
629
|
|
|
630 T* pT = static_cast<T*>(this);
|
|
|
631 ATLASSERT(::IsWindow(pT->m_hWnd));
|
|
|
632 return ::EnableThemeDialogTexture(pT->m_hWnd, dwFlags);
|
|
|
633 }
|
|
|
634
|
|
|
635 BOOL IsThemeDialogTextureEnabled() const
|
|
|
636 {
|
|
|
637 if(!this->IsThemingSupported())
|
|
|
638 return FALSE;
|
|
|
639
|
|
|
640 const T* pT = static_cast<const T*>(this);
|
|
|
641 ATLASSERT(::IsWindow(pT->m_hWnd));
|
|
|
642 return ::IsThemeDialogTextureEnabled(pT->m_hWnd);
|
|
|
643 }
|
|
|
644
|
|
|
645 HRESULT DrawThemeParentBackground(HDC hDC, const RECT* pRect = NULL)
|
|
|
646 {
|
|
|
647 if(!this->IsThemingSupported())
|
|
|
648 return S_FALSE;
|
|
|
649
|
|
|
650 T* pT = static_cast<T*>(this);
|
|
|
651 ATLASSERT(::IsWindow(pT->m_hWnd));
|
|
|
652 return ::DrawThemeParentBackground(pT->m_hWnd, hDC, pRect);
|
|
|
653 }
|
|
|
654
|
|
|
655 #if (_WIN32_WINNT >= 0x0600)
|
|
|
656 HRESULT SetWindowThemeAttribute(WINDOWTHEMEATTRIBUTETYPE type, PVOID pvAttribute, DWORD cbAttribute)
|
|
|
657 {
|
|
|
658 if(!this->IsThemingSupported())
|
|
|
659 return S_FALSE;
|
|
|
660
|
|
|
661 T* pT = static_cast<T*>(this);
|
|
|
662 ATLASSERT(::IsWindow(pT->m_hWnd));
|
|
|
663 return ::SetWindowThemeAttribute(pT->m_hWnd, type, pvAttribute, cbAttribute);
|
|
|
664 }
|
|
|
665
|
|
|
666 HRESULT SetWindowThemeNonClientAttributes(DWORD dwAttributes, DWORD dwMask)
|
|
|
667 {
|
|
|
668 if(!this->IsThemingSupported())
|
|
|
669 return S_FALSE;
|
|
|
670
|
|
|
671 T* pT = static_cast<T*>(this);
|
|
|
672 ATLASSERT(::IsWindow(pT->m_hWnd));
|
|
|
673 WTA_OPTIONS opt = { dwAttributes, dwMask };
|
|
|
674 return ::SetWindowThemeAttribute(pT->m_hWnd, WTA_NONCLIENT, (PVOID)&opt, sizeof(opt));
|
|
|
675 }
|
|
|
676
|
|
|
677 HRESULT DrawThemeParentBackgroundEx(HDC hDC, DWORD dwFlags, const RECT* lpRect = NULL)
|
|
|
678 {
|
|
|
679 if(!this->IsThemingSupported())
|
|
|
680 return S_FALSE;
|
|
|
681
|
|
|
682 T* pT = static_cast<T*>(this);
|
|
|
683 ATLASSERT(::IsWindow(pT->m_hWnd));
|
|
|
684 return ::DrawThemeParentBackgroundEx(pT->m_hWnd, hDC, dwFlags, lpRect);
|
|
|
685 }
|
|
|
686 #endif // (_WIN32_WINNT >= 0x0600)
|
|
|
687
|
|
|
688 // Message map and handlers
|
|
|
689 // Note: If you handle any of these messages in your derived class,
|
|
|
690 // it is better to put CHAIN_MSG_MAP at the start of your message map.
|
|
|
691 BEGIN_MSG_MAP(CThemeImpl)
|
|
|
692 MESSAGE_HANDLER(WM_CREATE, OnCreate)
|
|
|
693 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
|
|
|
694 MESSAGE_HANDLER(WM_THEMECHANGED, OnThemeChanged)
|
|
|
695 MESSAGE_HANDLER(WM_NCPAINT, OnNcPaint)
|
|
|
696 END_MSG_MAP()
|
|
|
697
|
|
|
698 LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
|
|
|
699 {
|
|
|
700 if(m_lpstrThemeClassList != NULL)
|
|
|
701 OpenThemeData();
|
|
|
702
|
|
|
703 bHandled = FALSE;
|
|
|
704 return 1;
|
|
|
705 }
|
|
|
706
|
|
|
707 LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
|
|
|
708 {
|
|
|
709 this->CloseThemeData();
|
|
|
710
|
|
|
711 bHandled = FALSE;
|
|
|
712 return 1;
|
|
|
713 }
|
|
|
714
|
|
|
715 LRESULT OnThemeChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
|
|
|
716 {
|
|
|
717 this->CloseThemeData();
|
|
|
718 if(m_lpstrThemeClassList != NULL)
|
|
|
719 this->OpenThemeData();
|
|
|
720
|
|
|
721 bHandled = FALSE;
|
|
|
722 return 1;
|
|
|
723 }
|
|
|
724
|
|
|
725 LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
|
|
726 {
|
|
|
727 T* pT = static_cast<T*>(this);
|
|
|
728 ATLASSERT(::IsWindow(pT->m_hWnd));
|
|
|
729 LRESULT lRet = 0;
|
|
|
730 bHandled = FALSE;
|
|
|
731 if(this->IsThemingSupported() && ((pT->GetExStyle() & WS_EX_CLIENTEDGE) != 0))
|
|
|
732 {
|
|
|
733 if((m_dwExtendedStyle & THEME_EX_3DCLIENTEDGE) != 0)
|
|
|
734 {
|
|
|
735 lRet = ::DefWindowProc(pT->m_hWnd, uMsg, wParam, lParam);
|
|
|
736 bHandled = TRUE;
|
|
|
737 }
|
|
|
738 else if((this->m_hTheme != NULL) && ((m_dwExtendedStyle & THEME_EX_THEMECLIENTEDGE) != 0))
|
|
|
739 {
|
|
|
740 HRGN hRgn = (wParam != 1) ? (HRGN)wParam : NULL;
|
|
|
741 if(pT->DrawThemeClientEdge(hRgn))
|
|
|
742 bHandled = TRUE;
|
|
|
743 }
|
|
|
744 }
|
|
|
745
|
|
|
746 return lRet;
|
|
|
747 }
|
|
|
748
|
|
|
749 // Drawing helper
|
|
|
750 bool DrawThemeClientEdge(HRGN hRgnUpdate)
|
|
|
751 {
|
|
|
752 T* pT = static_cast<T*>(this);
|
|
|
753 return AtlDrawThemeClientEdge(this->m_hTheme, pT->m_hWnd, hRgnUpdate, NULL, 0, 0);
|
|
|
754 }
|
|
|
755 };
|
|
|
756
|
|
|
757 ///////////////////////////////////////////////////////////////////////////////
|
|
|
758 // Buffered Paint and Animation
|
|
|
759
|
|
|
760 #if (_WIN32_WINNT >= 0x0600)
|
|
|
761
|
|
|
762 ///////////////////////////////////////////////////////////////////////////////
|
|
|
763 // CBufferedPaintBase - Buffered Paint support for othe classes
|
|
|
764
|
|
|
765 class CBufferedPaintBase
|
|
|
766 {
|
|
|
767 public:
|
|
|
768 static int m_nIsBufferedPaintSupported;
|
|
|
769
|
|
|
770 CBufferedPaintBase()
|
|
|
771 {
|
|
|
772 if(IsBufferedPaintSupported())
|
|
|
773 ATLVERIFY(SUCCEEDED(::BufferedPaintInit()));
|
|
|
774 }
|
|
|
775
|
|
|
776 ~CBufferedPaintBase()
|
|
|
777 {
|
|
|
778 if(IsBufferedPaintSupported())
|
|
|
779 ATLVERIFY(SUCCEEDED(::BufferedPaintUnInit()));
|
|
|
780 }
|
|
|
781
|
|
|
782 static bool IsBufferedPaintSupported()
|
|
|
783 {
|
|
|
784 if(m_nIsBufferedPaintSupported == -1)
|
|
|
785 {
|
|
|
786 CStaticDataInitCriticalSectionLock lock;
|
|
|
787 if(FAILED(lock.Lock()))
|
|
|
788 {
|
|
|
789 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CBufferedPaintBase::IsBufferedPaintSupported.\n"));
|
|
|
790 ATLASSERT(FALSE);
|
|
|
791 return false;
|
|
|
792 }
|
|
|
793
|
|
|
794 if(m_nIsBufferedPaintSupported == -1)
|
|
|
795 m_nIsBufferedPaintSupported = RunTimeHelper::IsVista() ? 1 : 0;
|
|
|
796
|
|
|
797 lock.Unlock();
|
|
|
798 }
|
|
|
799
|
|
|
800 ATLASSERT(m_nIsBufferedPaintSupported != -1);
|
|
|
801 return (m_nIsBufferedPaintSupported == 1);
|
|
|
802 }
|
|
|
803 };
|
|
|
804
|
|
|
805 __declspec(selectany) int CBufferedPaintBase::m_nIsBufferedPaintSupported = -1;
|
|
|
806
|
|
|
807
|
|
|
808 ///////////////////////////////////////////////////////////////////////////////
|
|
|
809 // CBufferedPaint - support for buffered paint functions
|
|
|
810
|
|
|
811 class CBufferedPaint
|
|
|
812 {
|
|
|
813 public:
|
|
|
814 HPAINTBUFFER m_hPaintBuffer;
|
|
|
815
|
|
|
816 CBufferedPaint() : m_hPaintBuffer(NULL)
|
|
|
817 { }
|
|
|
818
|
|
|
819 ~CBufferedPaint()
|
|
|
820 {
|
|
|
821 ATLVERIFY(SUCCEEDED(End()));
|
|
|
822 }
|
|
|
823
|
|
|
824 bool IsNull() const
|
|
|
825 {
|
|
|
826 return (m_hPaintBuffer == NULL);
|
|
|
827 }
|
|
|
828
|
|
|
829 HPAINTBUFFER Begin(HDC hdcTarget, const RECT* prcTarget, BP_BUFFERFORMAT dwFormat, BP_PAINTPARAMS* pPaintParams, HDC* phdcPaint)
|
|
|
830 {
|
|
|
831 ATLASSERT(m_hPaintBuffer == NULL);
|
|
|
832 m_hPaintBuffer = ::BeginBufferedPaint(hdcTarget, prcTarget, dwFormat, pPaintParams, phdcPaint);
|
|
|
833 return m_hPaintBuffer;
|
|
|
834 }
|
|
|
835
|
|
|
836 HRESULT End(BOOL bUpdate = TRUE)
|
|
|
837 {
|
|
|
838 HRESULT hRet = S_FALSE;
|
|
|
839 if(m_hPaintBuffer != NULL)
|
|
|
840 {
|
|
|
841 hRet = ::EndBufferedPaint(m_hPaintBuffer, bUpdate);
|
|
|
842 m_hPaintBuffer = NULL;
|
|
|
843 }
|
|
|
844 return hRet;
|
|
|
845 }
|
|
|
846
|
|
|
847 HRESULT GetTargetRect(LPRECT pRect) const
|
|
|
848 {
|
|
|
849 ATLASSERT(m_hPaintBuffer != NULL);
|
|
|
850 return ::GetBufferedPaintTargetRect(m_hPaintBuffer, pRect);
|
|
|
851 }
|
|
|
852
|
|
|
853 HDC GetTargetDC() const
|
|
|
854 {
|
|
|
855 ATLASSERT(m_hPaintBuffer != NULL);
|
|
|
856 return ::GetBufferedPaintTargetDC(m_hPaintBuffer);
|
|
|
857 }
|
|
|
858
|
|
|
859 HDC GetPaintDC() const
|
|
|
860 {
|
|
|
861 ATLASSERT(m_hPaintBuffer != NULL);
|
|
|
862 return ::GetBufferedPaintDC(m_hPaintBuffer);
|
|
|
863 }
|
|
|
864
|
|
|
865 HRESULT GetBits(RGBQUAD** ppbBuffer, int* pcxRow) const
|
|
|
866 {
|
|
|
867 ATLASSERT(m_hPaintBuffer != NULL);
|
|
|
868 return ::GetBufferedPaintBits(m_hPaintBuffer, ppbBuffer, pcxRow);
|
|
|
869 }
|
|
|
870
|
|
|
871 HRESULT Clear(const RECT* pRect = NULL)
|
|
|
872 {
|
|
|
873 ATLASSERT(m_hPaintBuffer != NULL);
|
|
|
874 return ::BufferedPaintClear(m_hPaintBuffer, pRect);
|
|
|
875 }
|
|
|
876
|
|
|
877 HRESULT SetAlpha(BYTE alpha, const RECT* pRect = NULL)
|
|
|
878 {
|
|
|
879 ATLASSERT(m_hPaintBuffer != NULL);
|
|
|
880 return ::BufferedPaintSetAlpha(m_hPaintBuffer, pRect, alpha);
|
|
|
881 }
|
|
|
882
|
|
|
883 HRESULT MakeOpaque(const RECT* pRect = NULL)
|
|
|
884 {
|
|
|
885 ATLASSERT(m_hPaintBuffer != NULL);
|
|
|
886 return ::BufferedPaintSetAlpha(m_hPaintBuffer, pRect, 255);
|
|
|
887 }
|
|
|
888 };
|
|
|
889
|
|
|
890
|
|
|
891 ///////////////////////////////////////////////////////////////////////////////
|
|
|
892 // CBufferedPaintImpl - provides buffered paint for any window
|
|
|
893
|
|
|
894 template <class T>
|
|
|
895 class ATL_NO_VTABLE CBufferedPaintImpl : public CBufferedPaintBase
|
|
|
896 {
|
|
|
897 public:
|
|
|
898 CBufferedPaint m_BufferedPaint;
|
|
|
899 BP_BUFFERFORMAT m_dwFormat;
|
|
|
900 BP_PAINTPARAMS m_PaintParams;
|
|
|
901
|
|
|
902 CBufferedPaintImpl() : m_dwFormat(BPBF_TOPDOWNDIB)
|
|
|
903 {
|
|
|
904 memset(&m_PaintParams, 0, sizeof(BP_PAINTPARAMS));
|
|
|
905 m_PaintParams.cbSize = sizeof(BP_PAINTPARAMS);
|
|
|
906 }
|
|
|
907
|
|
|
908 // Message map and handlers
|
|
|
909 BEGIN_MSG_MAP(CBufferedPaintImpl)
|
|
|
910 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
|
|
|
911 MESSAGE_HANDLER(WM_PAINT, OnPaint)
|
|
|
912 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
|
|
|
913 END_MSG_MAP()
|
|
|
914
|
|
|
915 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
|
|
|
916 {
|
|
|
917 return 1; // no background needed
|
|
|
918 }
|
|
|
919
|
|
|
920 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
|
|
|
921 {
|
|
|
922 T* pT = static_cast<T*>(this);
|
|
|
923 if(wParam != NULL)
|
|
|
924 {
|
|
|
925 RECT rect = {};
|
|
|
926 pT->GetClientRect(&rect);
|
|
|
927 pT->DoPaint((HDC)wParam, rect);
|
|
|
928 }
|
|
|
929 else
|
|
|
930 {
|
|
|
931 CPaintDC dc(pT->m_hWnd);
|
|
|
932 pT->DoBufferedPaint(dc.m_hDC, dc.m_ps.rcPaint);
|
|
|
933 }
|
|
|
934
|
|
|
935 return 0;
|
|
|
936 }
|
|
|
937
|
|
|
938 // Overrideables
|
|
|
939 void DoBufferedPaint(CDCHandle dc, RECT& rect)
|
|
|
940 {
|
|
|
941 HDC hDCPaint = NULL;
|
|
|
942 if(IsBufferedPaintSupported())
|
|
|
943 m_BufferedPaint.Begin(dc, &rect, m_dwFormat, &m_PaintParams, &hDCPaint);
|
|
|
944
|
|
|
945 T* pT = static_cast<T*>(this);
|
|
|
946 if(hDCPaint != NULL)
|
|
|
947 pT->DoPaint(hDCPaint, rect);
|
|
|
948 else
|
|
|
949 pT->DoPaint(dc.m_hDC, rect);
|
|
|
950
|
|
|
951 if(IsBufferedPaintSupported())
|
|
|
952 m_BufferedPaint.End();
|
|
|
953 }
|
|
|
954
|
|
|
955 void DoPaint(CDCHandle /*dc*/, RECT& /*rect*/)
|
|
|
956 {
|
|
|
957 // must be implemented in a derived class
|
|
|
958 ATLASSERT(FALSE);
|
|
|
959 }
|
|
|
960 };
|
|
|
961
|
|
|
962
|
|
|
963 ///////////////////////////////////////////////////////////////////////////////
|
|
|
964 // CBufferedPaintWindowImpl - implements a window that uses buffered paint
|
|
|
965
|
|
|
966 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
|
|
|
967 class ATL_NO_VTABLE CBufferedPaintWindowImpl :
|
|
|
968 public ATL::CWindowImpl<T, TBase, TWinTraits>,
|
|
|
969 public CBufferedPaintImpl< T >
|
|
|
970 {
|
|
|
971 public:
|
|
|
972 BEGIN_MSG_MAP(CBufferedPaintWindowImpl)
|
|
|
973 CHAIN_MSG_MAP(CBufferedPaintImpl< T >)
|
|
|
974 END_MSG_MAP()
|
|
|
975 };
|
|
|
976
|
|
|
977
|
|
|
978 ///////////////////////////////////////////////////////////////////////////////
|
|
|
979 // CBufferedAnimation - support for buffered animation
|
|
|
980
|
|
|
981 class CBufferedAnimation
|
|
|
982 {
|
|
|
983 public:
|
|
|
984 HANIMATIONBUFFER m_hAnimationBuffer;
|
|
|
985
|
|
|
986 CBufferedAnimation() : m_hAnimationBuffer(NULL)
|
|
|
987 { }
|
|
|
988
|
|
|
989 ~CBufferedAnimation()
|
|
|
990 {
|
|
|
991 ATLVERIFY(SUCCEEDED(End()));
|
|
|
992 }
|
|
|
993
|
|
|
994 bool IsNull() const
|
|
|
995 {
|
|
|
996 return (m_hAnimationBuffer == NULL);
|
|
|
997 }
|
|
|
998
|
|
|
999 HANIMATIONBUFFER Begin(HWND hWnd, HDC hDCTarget, const RECT* pRectTarget, BP_BUFFERFORMAT dwFormat, BP_PAINTPARAMS* pPaintParams, BP_ANIMATIONPARAMS* pAnimationParams, HDC* phdcFrom, HDC* phdcTo)
|
|
|
1000 {
|
|
|
1001 ATLASSERT(m_hAnimationBuffer == NULL);
|
|
|
1002 m_hAnimationBuffer = ::BeginBufferedAnimation(hWnd, hDCTarget, pRectTarget, dwFormat, pPaintParams, pAnimationParams, phdcFrom, phdcTo);
|
|
|
1003 return m_hAnimationBuffer;
|
|
|
1004 }
|
|
|
1005
|
|
|
1006 HRESULT End(BOOL bUpdate = TRUE)
|
|
|
1007 {
|
|
|
1008 HRESULT hRet = S_FALSE;
|
|
|
1009 if(m_hAnimationBuffer != NULL)
|
|
|
1010 {
|
|
|
1011 hRet = ::EndBufferedAnimation(m_hAnimationBuffer, bUpdate);
|
|
|
1012 m_hAnimationBuffer = NULL;
|
|
|
1013 }
|
|
|
1014 return hRet;
|
|
|
1015 }
|
|
|
1016
|
|
|
1017 static bool IsRendering(HWND hWnd, HDC hDC)
|
|
|
1018 {
|
|
|
1019 return (::BufferedPaintRenderAnimation(hWnd, hDC) != FALSE);
|
|
|
1020 }
|
|
|
1021
|
|
|
1022 static HRESULT StopAllAnimations(HWND hWnd)
|
|
|
1023 {
|
|
|
1024 return ::BufferedPaintStopAllAnimations(hWnd);
|
|
|
1025 }
|
|
|
1026 };
|
|
|
1027
|
|
|
1028
|
|
|
1029 ///////////////////////////////////////////////////////////////////////////////
|
|
|
1030 // CBufferedAnimationImpl - provides buffered animation support for any window
|
|
|
1031
|
|
|
1032 // Note: You can either use m_State and m_NewState to store the state information
|
|
|
1033 // for the animation change, or map your state to those data members. DoPaint()
|
|
|
1034 // should only rely on the state information that is passed to it.
|
|
|
1035
|
|
|
1036 template <class T, class TState = DWORD_PTR>
|
|
|
1037 class ATL_NO_VTABLE CBufferedAnimationImpl : public CBufferedPaintBase
|
|
|
1038 {
|
|
|
1039 public:
|
|
|
1040 BP_BUFFERFORMAT m_dwFormat;
|
|
|
1041 BP_PAINTPARAMS m_PaintParams;
|
|
|
1042 BP_ANIMATIONPARAMS m_AnimationParams;
|
|
|
1043
|
|
|
1044 TState m_State;
|
|
|
1045 TState m_NewState;
|
|
|
1046
|
|
|
1047 CBufferedAnimationImpl(TState InitialState) : m_dwFormat(BPBF_TOPDOWNDIB)
|
|
|
1048 {
|
|
|
1049 memset(&m_PaintParams, 0, sizeof(BP_PAINTPARAMS));
|
|
|
1050 m_PaintParams.cbSize = sizeof(BP_PAINTPARAMS);
|
|
|
1051
|
|
|
1052 memset(&m_AnimationParams, 0, sizeof(BP_ANIMATIONPARAMS));
|
|
|
1053 m_AnimationParams.cbSize = sizeof(BP_ANIMATIONPARAMS);
|
|
|
1054 m_AnimationParams.style = BPAS_LINEAR;
|
|
|
1055 m_AnimationParams.dwDuration = 500;
|
|
|
1056
|
|
|
1057 T* pT = static_cast<T*>(this);
|
|
|
1058 pT->SetState(InitialState);
|
|
|
1059 pT->SetNewState(InitialState);
|
|
|
1060 }
|
|
|
1061
|
|
|
1062 DWORD GetDuration() const
|
|
|
1063 {
|
|
|
1064 return m_AnimationParams.dwDuration;
|
|
|
1065 }
|
|
|
1066
|
|
|
1067 void SetDuration(DWORD dwDuration)
|
|
|
1068 {
|
|
|
1069 m_AnimationParams.dwDuration = dwDuration;
|
|
|
1070 }
|
|
|
1071
|
|
|
1072 void DoAnimation(TState NewState, const RECT* pRect = NULL)
|
|
|
1073 {
|
|
|
1074 T* pT = static_cast<T*>(this);
|
|
|
1075 pT->SetNewState(NewState);
|
|
|
1076
|
|
|
1077 pT->InvalidateRect(pRect, FALSE);
|
|
|
1078 pT->UpdateWindow();
|
|
|
1079
|
|
|
1080 pT->SetState(NewState);
|
|
|
1081 }
|
|
|
1082
|
|
|
1083 // Message map and handlers
|
|
|
1084 BEGIN_MSG_MAP(CBufferedAnimationImpl)
|
|
|
1085 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
|
|
|
1086 MESSAGE_HANDLER(WM_PAINT, OnPaint)
|
|
|
1087 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
|
|
|
1088 END_MSG_MAP()
|
|
|
1089
|
|
|
1090 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
|
|
|
1091 {
|
|
|
1092 return 1; // no background needed
|
|
|
1093 }
|
|
|
1094
|
|
|
1095 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
|
|
|
1096 {
|
|
|
1097 T* pT = static_cast<T*>(this);
|
|
|
1098 if(wParam != NULL)
|
|
|
1099 {
|
|
|
1100 RECT rect = {};
|
|
|
1101 pT->GetClientRect(&rect);
|
|
|
1102 pT->DoPaint((HDC)wParam, rect, m_NewState);
|
|
|
1103 }
|
|
|
1104 else
|
|
|
1105 {
|
|
|
1106 CPaintDC dc(pT->m_hWnd);
|
|
|
1107 pT->DoAnimationPaint(dc.m_hDC, dc.m_ps.rcPaint);
|
|
|
1108 }
|
|
|
1109
|
|
|
1110 return 0;
|
|
|
1111 }
|
|
|
1112
|
|
|
1113 // Overrideables
|
|
|
1114 void SetState(TState State)
|
|
|
1115 {
|
|
|
1116 m_State = State;
|
|
|
1117 }
|
|
|
1118
|
|
|
1119 void SetNewState(TState State)
|
|
|
1120 {
|
|
|
1121 m_NewState = State;
|
|
|
1122 }
|
|
|
1123
|
|
|
1124 bool AreStatesEqual() const
|
|
|
1125 {
|
|
|
1126 return (m_State == m_NewState);
|
|
|
1127 }
|
|
|
1128
|
|
|
1129 void DoAnimationPaint(CDCHandle dc, RECT& rect)
|
|
|
1130 {
|
|
|
1131 T* pT = static_cast<T*>(this);
|
|
|
1132 if(IsBufferedPaintSupported() && CBufferedAnimation::IsRendering(pT->m_hWnd, dc))
|
|
|
1133 return;
|
|
|
1134
|
|
|
1135 DWORD dwDurationSave = m_AnimationParams.dwDuration;
|
|
|
1136 if(pT->AreStatesEqual())
|
|
|
1137 m_AnimationParams.dwDuration = 0;
|
|
|
1138
|
|
|
1139 HDC hdcFrom = NULL, hdcTo = NULL;
|
|
|
1140 CBufferedAnimation ba;
|
|
|
1141 if(IsBufferedPaintSupported())
|
|
|
1142 ba.Begin(pT->m_hWnd, dc, &rect, m_dwFormat, &m_PaintParams, &m_AnimationParams, &hdcFrom, &hdcTo);
|
|
|
1143
|
|
|
1144 if(!ba.IsNull())
|
|
|
1145 {
|
|
|
1146 if(hdcFrom != NULL)
|
|
|
1147 pT->DoPaint(hdcFrom, rect, m_State);
|
|
|
1148
|
|
|
1149 if (hdcTo != NULL)
|
|
|
1150 pT->DoPaint(hdcTo, rect, m_NewState);
|
|
|
1151 }
|
|
|
1152 else
|
|
|
1153 {
|
|
|
1154 pT->DoPaint(dc.m_hDC, rect, m_NewState);
|
|
|
1155 }
|
|
|
1156
|
|
|
1157 m_AnimationParams.dwDuration = dwDurationSave;
|
|
|
1158 }
|
|
|
1159
|
|
|
1160 void DoPaint(CDCHandle /*dc*/, RECT& /*rect*/, TState /*State*/)
|
|
|
1161 {
|
|
|
1162 // must be implemented in a derived class
|
|
|
1163 ATLASSERT(FALSE);
|
|
|
1164 }
|
|
|
1165 };
|
|
|
1166
|
|
|
1167
|
|
|
1168 ///////////////////////////////////////////////////////////////////////////////
|
|
|
1169 // CBufferedAnimationWindowImpl - implements a window that uses buffered animation
|
|
|
1170
|
|
|
1171 template <class T, class TState = DWORD_PTR, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
|
|
|
1172 class ATL_NO_VTABLE CBufferedAnimationWindowImpl :
|
|
|
1173 public ATL::CWindowImpl<T, TBase, TWinTraits>,
|
|
|
1174 public CBufferedAnimationImpl< T, TState >
|
|
|
1175 {
|
|
|
1176 public:
|
|
|
1177 CBufferedAnimationWindowImpl(TState InitialState) : CBufferedAnimationImpl< T, TState >(InitialState)
|
|
|
1178 { }
|
|
|
1179
|
|
|
1180 typedef CBufferedAnimationImpl< T, TState > _baseBufferedAnimation;
|
|
|
1181 BEGIN_MSG_MAP(CBufferedAnimationWindowImpl)
|
|
|
1182 CHAIN_MSG_MAP(_baseBufferedAnimation)
|
|
|
1183 END_MSG_MAP()
|
|
|
1184 };
|
|
|
1185
|
|
|
1186 #endif // (_WIN32_WINNT >= 0x0600)
|
|
|
1187
|
|
|
1188 } // namespace WTL
|
|
|
1189
|
|
|
1190 #endif // __ATLTHEME_H__
|