PageRenderTime 116ms CodeModel.GetById 19ms app.highlight 88ms RepoModel.GetById 1ms app.codeStats 1ms

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