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