/thirdparty/wtl/atltheme.h

http://crashrpt.googlecode.com/ · C++ Header · 1218 lines · 895 code · 212 blank · 111 comment · 151 complexity · 2c5b63af4d8f1418c0d8d2f0efcceaf2 MD5 · raw file

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