atltheme.h 32 KB

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