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