| // Windows Template Library - WTL version 8.0 | 
 | // Copyright (C) Microsoft Corporation. All rights reserved. | 
 | // | 
 | // This file is a part of the Windows Template Library. | 
 | // The use and distribution terms for this software are covered by the | 
 | // Microsoft Permissive License (Ms-PL) which can be found in the file | 
 | // Ms-PL.txt at the root of this distribution. | 
 |  | 
 | #ifndef __ATLGDI_H__ | 
 | #define __ATLGDI_H__ | 
 |  | 
 | #pragma once | 
 |  | 
 | #ifndef __cplusplus | 
 | 	#error ATL requires C++ compilation (use a .cpp suffix) | 
 | #endif | 
 |  | 
 | #ifndef __ATLAPP_H__ | 
 | 	#error atlgdi.h requires atlapp.h to be included first | 
 | #endif | 
 |  | 
 |  | 
 | // protect template members from windowsx.h macros | 
 | #ifdef _INC_WINDOWSX | 
 |   #undef CopyRgn | 
 |   #undef CreateBrush | 
 |   #undef CreatePen | 
 |   #undef SelectBrush | 
 |   #undef SelectPen | 
 |   #undef SelectFont | 
 |   #undef SelectBitmap | 
 | #endif // _INC_WINDOWSX | 
 |  | 
 | // required libraries | 
 | #if !defined(_ATL_NO_MSIMG) && !defined(_WIN32_WCE) | 
 |   #pragma comment(lib, "msimg32.lib") | 
 | #endif // !defined(_ATL_NO_MSIMG) && !defined(_WIN32_WCE) | 
 | #if !defined(_ATL_NO_OPENGL) && !defined(_WIN32_WCE) | 
 |   #pragma comment(lib, "opengl32.lib") | 
 | #endif // !defined(_ATL_NO_OPENGL) && !defined(_WIN32_WCE) | 
 |  | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 | // Classes in this file: | 
 | // | 
 | // CPenT<t_bManaged> | 
 | // CBrushT<t_bManaged> | 
 | // CLogFont | 
 | // CFontT<t_bManaged> | 
 | // CBitmapT<t_bManaged> | 
 | // CPaletteT<t_bManaged> | 
 | // CRgnT<t_bManaged> | 
 | // CDCT<t_bManaged> | 
 | // CPaintDC | 
 | // CClientDC | 
 | // CWindowDC | 
 | // CMemoryDC | 
 | // CEnhMetaFileInfo | 
 | // CEnhMetaFileT<t_bManaged> | 
 | // CEnhMetaFileDC | 
 | // | 
 | // Global functions: | 
 | //   AtlGetBitmapResourceInfo() | 
 | //   AtlGetBitmapResourceBitsPerPixel() | 
 | //   AtlIsAlphaBitmapResource() | 
 | //   AtlIsDib16() | 
 | //   AtlGetDibColorTableSize() | 
 | //   AtlGetDibNumColors(), | 
 | //   AtlGetDibBitmap() | 
 | //   AtlCopyBitmap() | 
 | //   AtlCreatePackedDib16() | 
 | //   AtlSetClipboardDib16() | 
 | //   AtlGetClipboardDib() | 
 |  | 
 |  | 
 | namespace WTL | 
 | { | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 | // Bitmap resource helpers to extract bitmap information for a bitmap resource | 
 |  | 
 | inline LPBITMAPINFOHEADER AtlGetBitmapResourceInfo(HMODULE hModule, ATL::_U_STRINGorID image) | 
 | { | 
 | 	HRSRC hResource = ::FindResource(hModule, image.m_lpstr, RT_BITMAP); | 
 | 	ATLASSERT(hResource != NULL); | 
 | 	HGLOBAL hGlobal = ::LoadResource(hModule, hResource); | 
 | 	ATLASSERT(hGlobal != NULL); | 
 | 	LPBITMAPINFOHEADER pBitmapInfoHeader = (LPBITMAPINFOHEADER)::LockResource(hGlobal); | 
 | 	ATLASSERT(pBitmapInfoHeader != NULL); | 
 | 	return pBitmapInfoHeader; | 
 | } | 
 |  | 
 | inline WORD AtlGetBitmapResourceBitsPerPixel(HMODULE hModule, ATL::_U_STRINGorID image) | 
 | { | 
 | 	LPBITMAPINFOHEADER pBitmapInfoHeader = AtlGetBitmapResourceInfo(hModule, image); | 
 | 	ATLASSERT(pBitmapInfoHeader != NULL); | 
 | 	return pBitmapInfoHeader->biBitCount; | 
 | } | 
 |  | 
 | inline WORD AtlGetBitmapResourceBitsPerPixel(ATL::_U_STRINGorID image) | 
 | { | 
 | 	return AtlGetBitmapResourceBitsPerPixel(ModuleHelper::GetResourceInstance(), image); | 
 | } | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 | // 32-bit (alpha channel) bitmap resource helper | 
 |  | 
 | // Note: 32-bit (alpha channel) images work only on Windows XP with Common Controls version 6. | 
 | // If you want your app to work on older version of Windows, load non-alpha images if Common | 
 | // Controls version is less than 6. | 
 |  | 
 | inline bool AtlIsAlphaBitmapResource(ATL::_U_STRINGorID image) | 
 | { | 
 | 	return (AtlGetBitmapResourceBitsPerPixel(image) == 32); | 
 | } | 
 |  | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 | // CPen | 
 |  | 
 | template <bool t_bManaged> | 
 | class CPenT | 
 | { | 
 | public: | 
 | // Data members | 
 | 	HPEN m_hPen; | 
 |  | 
 | // Constructor/destructor/operators | 
 | 	CPenT(HPEN hPen = NULL) : m_hPen(hPen) | 
 | 	{ } | 
 |  | 
 | 	~CPenT() | 
 | 	{ | 
 | 		if(t_bManaged && m_hPen != NULL) | 
 | 			DeleteObject(); | 
 | 	} | 
 |  | 
 | 	CPenT<t_bManaged>& operator =(HPEN hPen) | 
 | 	{ | 
 | 		Attach(hPen); | 
 | 		return *this; | 
 | 	} | 
 |  | 
 | 	void Attach(HPEN hPen) | 
 | 	{ | 
 | 		if(t_bManaged && m_hPen != NULL && m_hPen != hPen) | 
 | 			::DeleteObject(m_hPen); | 
 | 		m_hPen = hPen; | 
 | 	} | 
 |  | 
 | 	HPEN Detach() | 
 | 	{ | 
 | 		HPEN hPen = m_hPen; | 
 | 		m_hPen = NULL; | 
 | 		return hPen; | 
 | 	} | 
 |  | 
 | 	operator HPEN() const { return m_hPen; } | 
 |  | 
 | 	bool IsNull() const { return (m_hPen == NULL); } | 
 |  | 
 | // Create methods | 
 | 	HPEN CreatePen(int nPenStyle, int nWidth, COLORREF crColor) | 
 | 	{ | 
 | 		ATLASSERT(m_hPen == NULL); | 
 | 		m_hPen = ::CreatePen(nPenStyle, nWidth, crColor); | 
 | 		return m_hPen; | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	HPEN CreatePen(int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush, int nStyleCount = 0, const DWORD* lpStyle = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hPen == NULL); | 
 | 		m_hPen = ::ExtCreatePen(nPenStyle, nWidth, pLogBrush, nStyleCount, lpStyle); | 
 | 		return m_hPen; | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	HPEN CreatePenIndirect(LPLOGPEN lpLogPen) | 
 | 	{ | 
 | 		ATLASSERT(m_hPen == NULL); | 
 | 		m_hPen = ::CreatePenIndirect(lpLogPen); | 
 | 		return m_hPen; | 
 | 	} | 
 |  | 
 | 	BOOL DeleteObject() | 
 | 	{ | 
 | 		ATLASSERT(m_hPen != NULL); | 
 | 		BOOL bRet = ::DeleteObject(m_hPen); | 
 | 		if(bRet) | 
 | 			m_hPen = NULL; | 
 | 		return bRet; | 
 | 	} | 
 |  | 
 | // Attributes | 
 | 	int GetLogPen(LOGPEN* pLogPen) const | 
 | 	{ | 
 | 		ATLASSERT(m_hPen != NULL); | 
 | 		return ::GetObject(m_hPen, sizeof(LOGPEN), pLogPen); | 
 | 	} | 
 |  | 
 | 	bool GetLogPen(LOGPEN& LogPen) const | 
 | 	{ | 
 | 		ATLASSERT(m_hPen != NULL); | 
 | 		return (::GetObject(m_hPen, sizeof(LOGPEN), &LogPen) == sizeof(LOGPEN)); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	int GetExtLogPen(EXTLOGPEN* pLogPen) const | 
 | 	{ | 
 | 		ATLASSERT(m_hPen != NULL); | 
 | 		return ::GetObject(m_hPen, sizeof(EXTLOGPEN), pLogPen); | 
 | 	} | 
 |  | 
 | 	bool GetExtLogPen(EXTLOGPEN& ExtLogPen) const | 
 | 	{ | 
 | 		ATLASSERT(m_hPen != NULL); | 
 | 		return (::GetObject(m_hPen, sizeof(EXTLOGPEN), &ExtLogPen) == sizeof(EXTLOGPEN)); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 | }; | 
 |  | 
 | typedef CPenT<false>   CPenHandle; | 
 | typedef CPenT<true>    CPen; | 
 |  | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 | // CBrush | 
 |  | 
 | template <bool t_bManaged> | 
 | class CBrushT | 
 | { | 
 | public: | 
 | // Data members | 
 | 	HBRUSH m_hBrush; | 
 |  | 
 | // Constructor/destructor/operators | 
 | 	CBrushT(HBRUSH hBrush = NULL) : m_hBrush(hBrush) | 
 | 	{ } | 
 |  | 
 | 	~CBrushT() | 
 | 	{ | 
 | 		if(t_bManaged && m_hBrush != NULL) | 
 | 			DeleteObject(); | 
 | 	} | 
 |  | 
 | 	CBrushT<t_bManaged>& operator =(HBRUSH hBrush) | 
 | 	{ | 
 | 		Attach(hBrush); | 
 | 		return *this; | 
 | 	} | 
 |  | 
 | 	void Attach(HBRUSH hBrush) | 
 | 	{ | 
 | 		if(t_bManaged && m_hBrush != NULL && m_hBrush != hBrush) | 
 | 			::DeleteObject(m_hBrush); | 
 | 		m_hBrush = hBrush; | 
 | 	} | 
 |  | 
 | 	HBRUSH Detach() | 
 | 	{ | 
 | 		HBRUSH hBrush = m_hBrush; | 
 | 		m_hBrush = NULL; | 
 | 		return hBrush; | 
 | 	} | 
 |  | 
 | 	operator HBRUSH() const { return m_hBrush; } | 
 |  | 
 | 	bool IsNull() const { return (m_hBrush == NULL); } | 
 |  | 
 | // Create methods | 
 | 	HBRUSH CreateSolidBrush(COLORREF crColor) | 
 | 	{ | 
 | 		ATLASSERT(m_hBrush == NULL); | 
 | 		m_hBrush = ::CreateSolidBrush(crColor); | 
 | 		return m_hBrush; | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	HBRUSH CreateHatchBrush(int nIndex, COLORREF crColor) | 
 | 	{ | 
 | 		ATLASSERT(m_hBrush == NULL); | 
 | 		m_hBrush = ::CreateHatchBrush(nIndex, crColor); | 
 | 		return m_hBrush; | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | #if !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800) | 
 | 	HBRUSH CreateBrushIndirect(const LOGBRUSH* lpLogBrush) | 
 | 	{ | 
 | 		ATLASSERT(m_hBrush == NULL); | 
 | #ifndef _WIN32_WCE | 
 | 		m_hBrush = ::CreateBrushIndirect(lpLogBrush); | 
 | #else // CE specific | 
 | 		m_hBrush = ATL::CreateBrushIndirect(lpLogBrush); | 
 | #endif // _WIN32_WCE | 
 | 		return m_hBrush; | 
 | 	} | 
 | #endif // !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800) | 
 |  | 
 | 	HBRUSH CreatePatternBrush(HBITMAP hBitmap) | 
 | 	{ | 
 | 		ATLASSERT(m_hBrush == NULL); | 
 | 		m_hBrush = ::CreatePatternBrush(hBitmap); | 
 | 		return m_hBrush; | 
 | 	} | 
 |  | 
 | 	HBRUSH CreateDIBPatternBrush(HGLOBAL hPackedDIB, UINT nUsage) | 
 | 	{ | 
 | 		ATLASSERT(hPackedDIB != NULL); | 
 | 		const void* lpPackedDIB = GlobalLock(hPackedDIB); | 
 | 		ATLASSERT(lpPackedDIB != NULL); | 
 | 		m_hBrush = ::CreateDIBPatternBrushPt(lpPackedDIB, nUsage); | 
 | 		GlobalUnlock(hPackedDIB); | 
 | 		return m_hBrush; | 
 | 	} | 
 |  | 
 | 	HBRUSH CreateDIBPatternBrush(const void* lpPackedDIB, UINT nUsage) | 
 | 	{ | 
 | 		ATLASSERT(m_hBrush == NULL); | 
 | 		m_hBrush = ::CreateDIBPatternBrushPt(lpPackedDIB, nUsage); | 
 | 		return m_hBrush; | 
 | 	} | 
 |  | 
 | 	HBRUSH CreateSysColorBrush(int nIndex) | 
 | 	{ | 
 | 		ATLASSERT(m_hBrush == NULL); | 
 | 		m_hBrush = ::GetSysColorBrush(nIndex); | 
 | 		return m_hBrush; | 
 | 	} | 
 |  | 
 | 	BOOL DeleteObject() | 
 | 	{ | 
 | 		ATLASSERT(m_hBrush != NULL); | 
 | 		BOOL bRet = ::DeleteObject(m_hBrush); | 
 | 		if(bRet) | 
 | 			m_hBrush = NULL; | 
 | 		return bRet; | 
 | 	} | 
 |  | 
 | // Attributes | 
 | 	int GetLogBrush(LOGBRUSH* pLogBrush) const | 
 | 	{ | 
 | 		ATLASSERT(m_hBrush != NULL); | 
 | 		return ::GetObject(m_hBrush, sizeof(LOGBRUSH), pLogBrush); | 
 | 	} | 
 |  | 
 | 	bool GetLogBrush(LOGBRUSH& LogBrush) const | 
 | 	{ | 
 | 		ATLASSERT(m_hBrush != NULL); | 
 | 		return (::GetObject(m_hBrush, sizeof(LOGBRUSH), &LogBrush) == sizeof(LOGBRUSH)); | 
 | 	} | 
 | }; | 
 |  | 
 | typedef CBrushT<false>   CBrushHandle; | 
 | typedef CBrushT<true>    CBrush; | 
 |  | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 | // CFont | 
 |  | 
 | class CLogFont : public LOGFONT | 
 | { | 
 | public: | 
 | 	CLogFont() | 
 | 	{ | 
 | 		memset(this, 0, sizeof(LOGFONT)); | 
 | 	} | 
 |  | 
 | 	CLogFont(const LOGFONT& lf) | 
 | 	{ | 
 | 		Copy(&lf); | 
 | 	} | 
 |  | 
 | 	CLogFont(HFONT hFont) | 
 | 	{ | 
 | 		ATLASSERT(::GetObjectType(hFont) == OBJ_FONT); | 
 | 		::GetObject(hFont, sizeof(LOGFONT), (LOGFONT*)this); | 
 | 	} | 
 |  | 
 | 	HFONT CreateFontIndirect() | 
 | 	{ | 
 | 		return ::CreateFontIndirect(this); | 
 | 	} | 
 |  | 
 | 	void SetBold() | 
 | 	{ | 
 | 		lfWeight = FW_BOLD; | 
 | 	} | 
 |  | 
 | 	bool IsBold() const | 
 | 	{ | 
 | 		return (lfWeight >= FW_BOLD); | 
 | 	} | 
 |  | 
 | 	void MakeBolder(int iScale = 1) | 
 | 	{ | 
 | 		lfWeight += FW_BOLD * iScale; | 
 | 	} | 
 |  | 
 | 	void MakeLarger(int iScale) | 
 | 	{ | 
 | 		if(lfHeight > 0) | 
 | 			lfHeight += iScale; | 
 | 		else | 
 | 			lfHeight -= iScale; | 
 | 	} | 
 |  | 
 | 	void SetHeight(LONG nPointSize, HDC hDC = NULL) | 
 | 	{ | 
 | 		// For MM_TEXT mapping mode | 
 | 		lfHeight = -::MulDiv(nPointSize, ::GetDeviceCaps(hDC, LOGPIXELSY), 72); | 
 | 	} | 
 |  | 
 | 	LONG GetHeight(HDC hDC = NULL) const | 
 | 	{ | 
 | 		// For MM_TEXT mapping mode | 
 | 		return ::MulDiv(-lfHeight, 72, ::GetDeviceCaps(hDC, LOGPIXELSY)); | 
 | 	} | 
 |  | 
 | 	LONG GetDeciPointHeight(HDC hDC = NULL) const | 
 | 	{ | 
 | #ifndef _WIN32_WCE | 
 | 		POINT ptOrg = { 0, 0 }; | 
 | 		::DPtoLP(hDC, &ptOrg, 1); | 
 | 		POINT pt = { 0, 0 }; | 
 | 		pt.y = abs(lfHeight) + ptOrg.y; | 
 | 		::LPtoDP(hDC,&pt,1); | 
 | 		return ::MulDiv(pt.y, 720, ::GetDeviceCaps(hDC, LOGPIXELSY));   // 72 points/inch, 10 decipoints/point | 
 | #else // CE specific | 
 | 		// DP and LP are always the same on CE | 
 | 		return ::MulDiv(abs(lfHeight), 720, ::GetDeviceCaps(hDC, LOGPIXELSY));   // 72 points/inch, 10 decipoints/point | 
 | #endif // _WIN32_WCE | 
 | 	} | 
 |  | 
 | 	void SetHeightFromDeciPoint(LONG nDeciPtHeight, HDC hDC = NULL) | 
 | 	{ | 
 | #ifndef _WIN32_WCE | 
 | 		POINT pt = { 0, 0 }; | 
 | 		pt.y = ::MulDiv(::GetDeviceCaps(hDC, LOGPIXELSY), nDeciPtHeight, 720);   // 72 points/inch, 10 decipoints/point | 
 | 		::DPtoLP(hDC, &pt, 1); | 
 | 		POINT ptOrg = { 0, 0 }; | 
 | 		::DPtoLP(hDC, &ptOrg, 1); | 
 | 		lfHeight = -abs(pt.y - ptOrg.y); | 
 | #else // CE specific | 
 | 		// DP and LP are always the same on CE | 
 | 		lfHeight = -abs(::MulDiv(::GetDeviceCaps(hDC, LOGPIXELSY), nDeciPtHeight, 720));   // 72 points/inch, 10 decipoints/point | 
 | #endif // _WIN32_WCE | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	void SetCaptionFont() | 
 | 	{ | 
 | 		NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() }; | 
 | 		ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0)); | 
 | 		Copy(&ncm.lfCaptionFont); | 
 | 	} | 
 |  | 
 | 	void SetMenuFont() | 
 | 	{ | 
 | 		NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() }; | 
 | 		ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0)); | 
 | 		Copy(&ncm.lfMenuFont); | 
 | 	} | 
 |  | 
 | 	void SetStatusFont() | 
 | 	{ | 
 | 		NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() }; | 
 | 		ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0)); | 
 | 		Copy(&ncm.lfStatusFont); | 
 | 	} | 
 |  | 
 | 	void SetMessageBoxFont() | 
 | 	{ | 
 | 		NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() }; | 
 | 		ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0)); | 
 | 		Copy(&ncm.lfMessageFont); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	void Copy(const LOGFONT* pLogFont) | 
 | 	{ | 
 | 		ATLASSERT(pLogFont != NULL); | 
 | 		*(LOGFONT*)this = *pLogFont; | 
 | 	} | 
 |  | 
 | 	CLogFont& operator =(const CLogFont& src) | 
 | 	{ | 
 | 		Copy(&src); | 
 | 		return *this; | 
 | 	} | 
 |  | 
 | 	CLogFont& operator =(const LOGFONT& src) | 
 | 	{ | 
 | 		Copy(&src); | 
 | 		return *this; | 
 | 	} | 
 |  | 
 | 	CLogFont& operator =(HFONT hFont) | 
 | 	{ | 
 | 		ATLASSERT(::GetObjectType(hFont) == OBJ_FONT); | 
 | 		::GetObject(hFont, sizeof(LOGFONT), (LOGFONT*)this); | 
 | 		return *this; | 
 | 	} | 
 |  | 
 | 	bool operator ==(const LOGFONT& logfont) const | 
 | 	{ | 
 | 		return(logfont.lfHeight == lfHeight && | 
 | 		       logfont.lfWidth == lfWidth && | 
 | 		       logfont.lfEscapement == lfEscapement && | 
 | 		       logfont.lfOrientation == lfOrientation && | 
 | 		       logfont.lfWeight == lfWeight && | 
 | 		       logfont.lfItalic == lfItalic && | 
 | 		       logfont.lfUnderline == lfUnderline && | 
 | 		       logfont.lfStrikeOut == lfStrikeOut && | 
 | 		       logfont.lfCharSet == lfCharSet && | 
 | 		       logfont.lfOutPrecision == lfOutPrecision && | 
 | 		       logfont.lfClipPrecision == lfClipPrecision && | 
 | 		       logfont.lfQuality == lfQuality && | 
 | 		       logfont.lfPitchAndFamily == lfPitchAndFamily && | 
 | 		       lstrcmp(logfont.lfFaceName, lfFaceName) == 0); | 
 | 	} | 
 | }; | 
 |  | 
 |  | 
 | template <bool t_bManaged> | 
 | class CFontT | 
 | { | 
 | public: | 
 | // Data members | 
 | 	HFONT m_hFont; | 
 |  | 
 | // Constructor/destructor/operators | 
 | 	CFontT(HFONT hFont = NULL) : m_hFont(hFont) | 
 | 	{ } | 
 |  | 
 | 	~CFontT() | 
 | 	{ | 
 | 		if(t_bManaged && m_hFont != NULL) | 
 | 			DeleteObject(); | 
 | 	} | 
 |  | 
 | 	CFontT<t_bManaged>& operator =(HFONT hFont) | 
 | 	{ | 
 | 		Attach(hFont); | 
 | 		return *this; | 
 | 	} | 
 |  | 
 | 	void Attach(HFONT hFont) | 
 | 	{ | 
 | 		if(t_bManaged && m_hFont != NULL && m_hFont != hFont) | 
 | 			::DeleteObject(m_hFont); | 
 | 		m_hFont = hFont; | 
 | 	} | 
 |  | 
 | 	HFONT Detach() | 
 | 	{ | 
 | 		HFONT hFont = m_hFont; | 
 | 		m_hFont = NULL; | 
 | 		return hFont; | 
 | 	} | 
 |  | 
 | 	operator HFONT() const { return m_hFont; } | 
 |  | 
 | 	bool IsNull() const { return (m_hFont == NULL); } | 
 |  | 
 | // Create methods | 
 | 	HFONT CreateFontIndirect(const LOGFONT* lpLogFont) | 
 | 	{ | 
 | 		ATLASSERT(m_hFont == NULL); | 
 | 		m_hFont = ::CreateFontIndirect(lpLogFont); | 
 | 		return m_hFont; | 
 | 	} | 
 |  | 
 | #if !defined(_WIN32_WCE) && (_WIN32_WINNT >= 0x0500) | 
 | 	HFONT CreateFontIndirectEx(CONST ENUMLOGFONTEXDV* penumlfex) | 
 | 	{ | 
 | 		ATLASSERT(m_hFont == NULL); | 
 | 		m_hFont = ::CreateFontIndirectEx(penumlfex); | 
 | 		return m_hFont; | 
 | 	} | 
 | #endif // !defined(_WIN32_WCE) && (_WIN32_WINNT >= 0x0500) | 
 |  | 
 | #if !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800) | 
 | 	HFONT CreateFont(int nHeight, int nWidth, int nEscapement, | 
 | 			int nOrientation, int nWeight, BYTE bItalic, BYTE bUnderline, | 
 | 			BYTE cStrikeOut, BYTE nCharSet, BYTE nOutPrecision, | 
 | 			BYTE nClipPrecision, BYTE nQuality, BYTE nPitchAndFamily, | 
 | 			LPCTSTR lpszFacename) | 
 | 	{ | 
 | 		ATLASSERT(m_hFont == NULL); | 
 | #ifndef _WIN32_WCE | 
 | 		m_hFont = ::CreateFont(nHeight, nWidth, nEscapement, | 
 | 			nOrientation, nWeight, bItalic, bUnderline, cStrikeOut, | 
 | 			nCharSet, nOutPrecision, nClipPrecision, nQuality, | 
 | 			nPitchAndFamily, lpszFacename); | 
 | #else // CE specific | 
 | 		m_hFont = ATL::CreateFont(nHeight, nWidth, nEscapement, | 
 | 			nOrientation, nWeight, bItalic, bUnderline, cStrikeOut, | 
 | 			nCharSet, nOutPrecision, nClipPrecision, nQuality, | 
 | 			nPitchAndFamily, lpszFacename); | 
 | #endif // _WIN32_WCE | 
 | 		return m_hFont; | 
 | 	} | 
 | #endif // !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800) | 
 |  | 
 | 	HFONT CreatePointFont(int nPointSize, LPCTSTR lpszFaceName, HDC hDC = NULL, bool bBold = false, bool bItalic = false) | 
 | 	{ | 
 | 		LOGFONT logFont = { 0 }; | 
 | 		logFont.lfCharSet = DEFAULT_CHARSET; | 
 | 		logFont.lfHeight = nPointSize; | 
 | 		SecureHelper::strncpy_x(logFont.lfFaceName, _countof(logFont.lfFaceName), lpszFaceName, _TRUNCATE); | 
 |  | 
 | 		if(bBold) | 
 | 			logFont.lfWeight = FW_BOLD; | 
 | 		if(bItalic) | 
 | 			logFont.lfItalic = (BYTE)TRUE; | 
 |  | 
 | 		return CreatePointFontIndirect(&logFont, hDC); | 
 | 	} | 
 |  | 
 | 	HFONT CreatePointFontIndirect(const LOGFONT* lpLogFont, HDC hDC = NULL) | 
 | 	{ | 
 | 		HDC hDC1 = (hDC != NULL) ? hDC : ::GetDC(NULL); | 
 |  | 
 | 		// convert nPointSize to logical units based on hDC | 
 | 		LOGFONT logFont = *lpLogFont; | 
 | #ifndef _WIN32_WCE | 
 | 		POINT pt = { 0, 0 }; | 
 | 		pt.y = ::MulDiv(::GetDeviceCaps(hDC1, LOGPIXELSY), logFont.lfHeight, 720);   // 72 points/inch, 10 decipoints/point | 
 | 		::DPtoLP(hDC1, &pt, 1); | 
 | 		POINT ptOrg = { 0, 0 }; | 
 | 		::DPtoLP(hDC1, &ptOrg, 1); | 
 | 		logFont.lfHeight = -abs(pt.y - ptOrg.y); | 
 | #else // CE specific | 
 | 		// DP and LP are always the same on CE | 
 | 		logFont.lfHeight = -abs(::MulDiv(::GetDeviceCaps(hDC1, LOGPIXELSY), logFont.lfHeight, 720));   // 72 points/inch, 10 decipoints/point | 
 | #endif // _WIN32_WCE | 
 |  | 
 | 		if(hDC == NULL) | 
 | 			::ReleaseDC(NULL, hDC1); | 
 |  | 
 | 		return CreateFontIndirect(&logFont); | 
 | 	} | 
 |  | 
 | 	BOOL DeleteObject() | 
 | 	{ | 
 | 		ATLASSERT(m_hFont != NULL); | 
 | 		BOOL bRet = ::DeleteObject(m_hFont); | 
 | 		if(bRet) | 
 | 			m_hFont = NULL; | 
 | 		return bRet; | 
 | 	} | 
 |  | 
 | // Attributes | 
 | 	int GetLogFont(LOGFONT* pLogFont) const | 
 | 	{ | 
 | 		ATLASSERT(m_hFont != NULL); | 
 | 		return ::GetObject(m_hFont, sizeof(LOGFONT), pLogFont); | 
 | 	} | 
 |  | 
 | 	bool GetLogFont(LOGFONT& LogFont) const | 
 | 	{ | 
 | 		ATLASSERT(m_hFont != NULL); | 
 | 		return (::GetObject(m_hFont, sizeof(LOGFONT), &LogFont) == sizeof(LOGFONT)); | 
 | 	} | 
 | }; | 
 |  | 
 | typedef CFontT<false>   CFontHandle; | 
 | typedef CFontT<true>    CFont; | 
 |  | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 | // CBitmap | 
 |  | 
 | template <bool t_bManaged> | 
 | class CBitmapT | 
 | { | 
 | public: | 
 | // Data members | 
 | 	HBITMAP m_hBitmap; | 
 |  | 
 | // Constructor/destructor/operators | 
 | 	CBitmapT(HBITMAP hBitmap = NULL) : m_hBitmap(hBitmap) | 
 | 	{ } | 
 |  | 
 | 	~CBitmapT() | 
 | 	{ | 
 | 		if(t_bManaged && m_hBitmap != NULL) | 
 | 			DeleteObject(); | 
 | 	} | 
 |  | 
 | 	CBitmapT<t_bManaged>& operator =(HBITMAP hBitmap) | 
 | 	{ | 
 | 		Attach(hBitmap); | 
 | 		return *this; | 
 | 	} | 
 |  | 
 | 	void Attach(HBITMAP hBitmap) | 
 | 	{ | 
 | 		if(t_bManaged && m_hBitmap != NULL&& m_hBitmap != hBitmap) | 
 | 			::DeleteObject(m_hBitmap); | 
 | 		m_hBitmap = hBitmap; | 
 | 	} | 
 |  | 
 | 	HBITMAP Detach() | 
 | 	{ | 
 | 		HBITMAP hBitmap = m_hBitmap; | 
 | 		m_hBitmap = NULL; | 
 | 		return hBitmap; | 
 | 	} | 
 |  | 
 | 	operator HBITMAP() const { return m_hBitmap; } | 
 |  | 
 | 	bool IsNull() const { return (m_hBitmap == NULL); } | 
 |  | 
 | // Create and load methods | 
 | 	HBITMAP LoadBitmap(ATL::_U_STRINGorID bitmap) | 
 | 	{ | 
 | 		ATLASSERT(m_hBitmap == NULL); | 
 | 		m_hBitmap = ::LoadBitmap(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr); | 
 | 		return m_hBitmap; | 
 | 	} | 
 |  | 
 | 	HBITMAP LoadOEMBitmap(UINT nIDBitmap) // for OBM_/OCR_/OIC_ | 
 | 	{ | 
 | 		ATLASSERT(m_hBitmap == NULL); | 
 | 		m_hBitmap = ::LoadBitmap(NULL, MAKEINTRESOURCE(nIDBitmap)); | 
 | 		return m_hBitmap; | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	HBITMAP LoadMappedBitmap(UINT nIDBitmap, UINT nFlags = 0, LPCOLORMAP lpColorMap = NULL, int nMapSize = 0) | 
 | 	{ | 
 | 		ATLASSERT(m_hBitmap == NULL); | 
 | 		m_hBitmap = ::CreateMappedBitmap(ModuleHelper::GetResourceInstance(), nIDBitmap, (WORD)nFlags, lpColorMap, nMapSize); | 
 | 		return m_hBitmap; | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	HBITMAP CreateBitmap(int nWidth, int nHeight, UINT nPlanes, UINT nBitsPerPixel, const void* lpBits) | 
 | 	{ | 
 | 		ATLASSERT(m_hBitmap == NULL); | 
 | 		m_hBitmap = ::CreateBitmap(nWidth, nHeight, nPlanes, nBitsPerPixel, lpBits); | 
 | 		return m_hBitmap; | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	HBITMAP CreateBitmapIndirect(LPBITMAP lpBitmap) | 
 | 	{ | 
 | 		ATLASSERT(m_hBitmap == NULL); | 
 | 		m_hBitmap = ::CreateBitmapIndirect(lpBitmap); | 
 | 		return m_hBitmap; | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	HBITMAP CreateCompatibleBitmap(HDC hDC, int nWidth, int nHeight) | 
 | 	{ | 
 | 		ATLASSERT(m_hBitmap == NULL); | 
 | 		m_hBitmap = ::CreateCompatibleBitmap(hDC, nWidth, nHeight); | 
 | 		return m_hBitmap; | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	HBITMAP CreateDiscardableBitmap(HDC hDC, int nWidth, int nHeight) | 
 | 	{ | 
 | 		ATLASSERT(m_hBitmap == NULL); | 
 | 		m_hBitmap = ::CreateDiscardableBitmap(hDC, nWidth, nHeight); | 
 | 		return m_hBitmap; | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	BOOL DeleteObject() | 
 | 	{ | 
 | 		ATLASSERT(m_hBitmap != NULL); | 
 | 		BOOL bRet = ::DeleteObject(m_hBitmap); | 
 | 		if(bRet) | 
 | 			m_hBitmap = NULL; | 
 | 		return bRet; | 
 | 	} | 
 |  | 
 | // Attributes | 
 | 	int GetBitmap(BITMAP* pBitMap) const | 
 | 	{ | 
 | 		ATLASSERT(m_hBitmap != NULL); | 
 | 		return ::GetObject(m_hBitmap, sizeof(BITMAP), pBitMap); | 
 | 	} | 
 |  | 
 | 	bool GetBitmap(BITMAP& bm) const | 
 | 	{ | 
 | 		ATLASSERT(m_hBitmap != NULL); | 
 | 		return (::GetObject(m_hBitmap, sizeof(BITMAP), &bm) == sizeof(BITMAP)); | 
 | 	} | 
 |  | 
 | 	bool GetSize(SIZE& size) const | 
 | 	{ | 
 | 		ATLASSERT(m_hBitmap != NULL); | 
 | 		BITMAP bm = { 0 }; | 
 | 		if(!GetBitmap(&bm)) | 
 | 			return false; | 
 | 		size.cx = bm.bmWidth; | 
 | 		size.cy = bm.bmHeight; | 
 | 		return true; | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	DWORD GetBitmapBits(DWORD dwCount, LPVOID lpBits) const | 
 | 	{ | 
 | 		ATLASSERT(m_hBitmap != NULL); | 
 | 		return ::GetBitmapBits(m_hBitmap, dwCount, lpBits); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 410) | 
 | 	DWORD SetBitmapBits(DWORD dwCount, const void* lpBits) | 
 | 	{ | 
 | 		ATLASSERT(m_hBitmap != NULL); | 
 | 		return ::SetBitmapBits(m_hBitmap, dwCount, lpBits); | 
 | 	} | 
 | #endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 410) | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	BOOL GetBitmapDimension(LPSIZE lpSize) const | 
 | 	{ | 
 | 		ATLASSERT(m_hBitmap != NULL); | 
 | 		return ::GetBitmapDimensionEx(m_hBitmap, lpSize); | 
 | 	} | 
 |  | 
 | 	BOOL SetBitmapDimension(int nWidth, int nHeight, LPSIZE lpSize = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hBitmap != NULL); | 
 | 		return ::SetBitmapDimensionEx(m_hBitmap, nWidth, nHeight, lpSize); | 
 | 	} | 
 |  | 
 | // DIB support | 
 | 	HBITMAP CreateDIBitmap(HDC hDC, CONST BITMAPINFOHEADER* lpbmih, DWORD dwInit, CONST VOID* lpbInit, CONST BITMAPINFO* lpbmi, UINT uColorUse) | 
 | 	{ | 
 | 		ATLASSERT(m_hBitmap == NULL); | 
 | 		m_hBitmap = ::CreateDIBitmap(hDC, lpbmih, dwInit, lpbInit, lpbmi, uColorUse); | 
 | 		return m_hBitmap; | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	HBITMAP CreateDIBSection(HDC hDC, CONST BITMAPINFO* lpbmi, UINT uColorUse, VOID** ppvBits, HANDLE hSection, DWORD dwOffset) | 
 | 	{ | 
 | 		ATLASSERT(m_hBitmap == NULL); | 
 | 		m_hBitmap = ::CreateDIBSection(hDC, lpbmi, uColorUse, ppvBits, hSection, dwOffset); | 
 | 		return m_hBitmap; | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	int GetDIBits(HDC hDC, UINT uStartScan, UINT cScanLines,  LPVOID lpvBits, LPBITMAPINFO lpbmi, UINT uColorUse) const | 
 | 	{ | 
 | 		ATLASSERT(m_hBitmap != NULL); | 
 | 		return ::GetDIBits(hDC, m_hBitmap, uStartScan, cScanLines,  lpvBits, lpbmi, uColorUse); | 
 | 	} | 
 |  | 
 | 	int SetDIBits(HDC hDC, UINT uStartScan, UINT cScanLines, CONST VOID* lpvBits, CONST BITMAPINFO* lpbmi, UINT uColorUse) | 
 | 	{ | 
 | 		ATLASSERT(m_hBitmap != NULL); | 
 | 		return ::SetDIBits(hDC, m_hBitmap, uStartScan, cScanLines, lpvBits, lpbmi, uColorUse); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 | }; | 
 |  | 
 | typedef CBitmapT<false>   CBitmapHandle; | 
 | typedef CBitmapT<true>    CBitmap; | 
 |  | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 | // CPalette | 
 |  | 
 | template <bool t_bManaged> | 
 | class CPaletteT | 
 | { | 
 | public: | 
 | // Data members | 
 | 	HPALETTE m_hPalette; | 
 |  | 
 | // Constructor/destructor/operators | 
 | 	CPaletteT(HPALETTE hPalette = NULL) : m_hPalette(hPalette) | 
 | 	{ } | 
 |  | 
 | 	~CPaletteT() | 
 | 	{ | 
 | 		if(t_bManaged && m_hPalette != NULL) | 
 | 			DeleteObject(); | 
 | 	} | 
 |  | 
 | 	CPaletteT<t_bManaged>& operator =(HPALETTE hPalette) | 
 | 	{ | 
 | 		Attach(hPalette); | 
 | 		return *this; | 
 | 	} | 
 |  | 
 | 	void Attach(HPALETTE hPalette) | 
 | 	{ | 
 | 		if(t_bManaged && m_hPalette != NULL && m_hPalette != hPalette) | 
 | 			::DeleteObject(m_hPalette); | 
 | 		m_hPalette = hPalette; | 
 | 	} | 
 |  | 
 | 	HPALETTE Detach() | 
 | 	{ | 
 | 		HPALETTE hPalette = m_hPalette; | 
 | 		m_hPalette = NULL; | 
 | 		return hPalette; | 
 | 	} | 
 |  | 
 | 	operator HPALETTE() const { return m_hPalette; } | 
 |  | 
 | 	bool IsNull() const { return (m_hPalette == NULL); } | 
 |  | 
 | // Create methods | 
 | 	HPALETTE CreatePalette(LPLOGPALETTE lpLogPalette) | 
 | 	{ | 
 | 		ATLASSERT(m_hPalette == NULL); | 
 | 		m_hPalette = ::CreatePalette(lpLogPalette); | 
 | 		return m_hPalette; | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	HPALETTE CreateHalftonePalette(HDC hDC) | 
 | 	{ | 
 | 		ATLASSERT(m_hPalette == NULL); | 
 | 		ATLASSERT(hDC != NULL); | 
 | 		m_hPalette = ::CreateHalftonePalette(hDC); | 
 | 		return m_hPalette; | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	BOOL DeleteObject() | 
 | 	{ | 
 | 		ATLASSERT(m_hPalette != NULL); | 
 | 		BOOL bRet = ::DeleteObject(m_hPalette); | 
 | 		if(bRet) | 
 | 			m_hPalette = NULL; | 
 | 		return bRet; | 
 | 	} | 
 |  | 
 | // Attributes | 
 | 	int GetEntryCount() const | 
 | 	{ | 
 | 		ATLASSERT(m_hPalette != NULL); | 
 | 		WORD nEntries = 0; | 
 | 		::GetObject(m_hPalette, sizeof(WORD), &nEntries); | 
 | 		return (int)nEntries; | 
 | 	} | 
 |  | 
 | 	UINT GetPaletteEntries(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors) const | 
 | 	{ | 
 | 		ATLASSERT(m_hPalette != NULL); | 
 | 		return ::GetPaletteEntries(m_hPalette, nStartIndex, nNumEntries, lpPaletteColors); | 
 | 	} | 
 |  | 
 | 	UINT SetPaletteEntries(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors) | 
 | 	{ | 
 | 		ATLASSERT(m_hPalette != NULL); | 
 | 		return ::SetPaletteEntries(m_hPalette, nStartIndex, nNumEntries, lpPaletteColors); | 
 | 	} | 
 |  | 
 | // Operations | 
 | #ifndef _WIN32_WCE | 
 | 	void AnimatePalette(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors) | 
 | 	{ | 
 | 		ATLASSERT(m_hPalette != NULL); | 
 | 		::AnimatePalette(m_hPalette, nStartIndex, nNumEntries, lpPaletteColors); | 
 | 	} | 
 |  | 
 | 	BOOL ResizePalette(UINT nNumEntries) | 
 | 	{ | 
 | 		ATLASSERT(m_hPalette != NULL); | 
 | 		return ::ResizePalette(m_hPalette, nNumEntries); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	UINT GetNearestPaletteIndex(COLORREF crColor) const | 
 | 	{ | 
 | 		ATLASSERT(m_hPalette != NULL); | 
 | 		return ::GetNearestPaletteIndex(m_hPalette, crColor); | 
 | 	} | 
 | }; | 
 |  | 
 | typedef CPaletteT<false>   CPaletteHandle; | 
 | typedef CPaletteT<true>    CPalette; | 
 |  | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 | // CRgn | 
 |  | 
 | template <bool t_bManaged> | 
 | class CRgnT | 
 | { | 
 | public: | 
 | // Data members | 
 | 	HRGN m_hRgn; | 
 |  | 
 | // Constructor/destructor/operators | 
 | 	CRgnT(HRGN hRgn = NULL) : m_hRgn(hRgn) | 
 | 	{ } | 
 |  | 
 | 	~CRgnT() | 
 | 	{ | 
 | 		if(t_bManaged && m_hRgn != NULL) | 
 | 			DeleteObject(); | 
 | 	} | 
 |  | 
 | 	CRgnT<t_bManaged>& operator =(HRGN hRgn) | 
 | 	{ | 
 | 		Attach(hRgn); | 
 | 		return *this; | 
 | 	} | 
 |  | 
 | 	void Attach(HRGN hRgn) | 
 | 	{ | 
 | 		if(t_bManaged && m_hRgn != NULL && m_hRgn != hRgn) | 
 | 			::DeleteObject(m_hRgn); | 
 | 		m_hRgn = hRgn; | 
 | 	} | 
 |  | 
 | 	HRGN Detach() | 
 | 	{ | 
 | 		HRGN hRgn = m_hRgn; | 
 | 		m_hRgn = NULL; | 
 | 		return hRgn; | 
 | 	} | 
 |  | 
 | 	operator HRGN() const { return m_hRgn; } | 
 |  | 
 | 	bool IsNull() const { return (m_hRgn == NULL); } | 
 |  | 
 | // Create methods | 
 | 	HRGN CreateRectRgn(int x1, int y1, int x2, int y2) | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn == NULL); | 
 | 		m_hRgn = ::CreateRectRgn(x1, y1, x2, y2); | 
 | 		return m_hRgn; | 
 | 	} | 
 |  | 
 | 	HRGN CreateRectRgnIndirect(LPCRECT lpRect) | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn == NULL); | 
 | 		m_hRgn = ::CreateRectRgnIndirect(lpRect); | 
 | 		return m_hRgn; | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	HRGN CreateEllipticRgn(int x1, int y1, int x2, int y2) | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn == NULL); | 
 | 		m_hRgn = ::CreateEllipticRgn(x1, y1, x2, y2); | 
 | 		return m_hRgn; | 
 | 	} | 
 |  | 
 | 	HRGN CreateEllipticRgnIndirect(LPCRECT lpRect) | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn == NULL); | 
 | 		m_hRgn = ::CreateEllipticRgnIndirect(lpRect); | 
 | 		return m_hRgn; | 
 | 	} | 
 |  | 
 | 	HRGN CreatePolygonRgn(LPPOINT lpPoints, int nCount, int nMode) | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn == NULL); | 
 | 		m_hRgn = ::CreatePolygonRgn(lpPoints, nCount, nMode); | 
 | 		return m_hRgn; | 
 | 	} | 
 |  | 
 | 	HRGN CreatePolyPolygonRgn(LPPOINT lpPoints, LPINT lpPolyCounts, int nCount, int nPolyFillMode) | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn == NULL); | 
 | 		m_hRgn = ::CreatePolyPolygonRgn(lpPoints, lpPolyCounts, nCount, nPolyFillMode); | 
 | 		return m_hRgn; | 
 | 	} | 
 |  | 
 | 	HRGN CreateRoundRectRgn(int x1, int y1, int x2, int y2, int x3, int y3) | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn == NULL); | 
 | 		m_hRgn = ::CreateRoundRectRgn(x1, y1, x2, y2, x3, y3); | 
 | 		return m_hRgn; | 
 | 	} | 
 |  | 
 | 	HRGN CreateFromPath(HDC hDC) | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn == NULL); | 
 | 		ATLASSERT(hDC != NULL); | 
 | 		m_hRgn = ::PathToRegion(hDC); | 
 | 		return m_hRgn; | 
 | 	} | 
 |  | 
 | 	HRGN CreateFromData(const XFORM* lpXForm, int nCount, const RGNDATA* pRgnData) | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn == NULL); | 
 | 		m_hRgn = ::ExtCreateRegion(lpXForm, nCount, pRgnData); | 
 | 		return m_hRgn; | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	BOOL DeleteObject() | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn != NULL); | 
 | 		BOOL bRet = ::DeleteObject(m_hRgn); | 
 | 		if(bRet) | 
 | 			m_hRgn = NULL; | 
 | 		return bRet; | 
 | 	} | 
 |  | 
 | // Operations | 
 | 	void SetRectRgn(int x1, int y1, int x2, int y2) | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn != NULL); | 
 | 		::SetRectRgn(m_hRgn, x1, y1, x2, y2); | 
 | 	} | 
 |  | 
 | 	void SetRectRgn(LPCRECT lpRect) | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn != NULL); | 
 | 		::SetRectRgn(m_hRgn, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); | 
 | 	} | 
 |  | 
 | 	int CombineRgn(HRGN hRgnSrc1, HRGN hRgnSrc2, int nCombineMode) | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn != NULL); | 
 | 		return ::CombineRgn(m_hRgn, hRgnSrc1, hRgnSrc2, nCombineMode); | 
 | 	} | 
 |  | 
 | 	int CombineRgn(HRGN hRgnSrc, int nCombineMode) | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn != NULL); | 
 | 		return ::CombineRgn(m_hRgn, m_hRgn, hRgnSrc, nCombineMode); | 
 | 	} | 
 |  | 
 | 	int CopyRgn(HRGN hRgnSrc) | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn != NULL); | 
 | 		return ::CombineRgn(m_hRgn, hRgnSrc, NULL, RGN_COPY); | 
 | 	} | 
 |  | 
 | 	BOOL EqualRgn(HRGN hRgn) const | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn != NULL); | 
 | 		return ::EqualRgn(m_hRgn, hRgn); | 
 | 	} | 
 |  | 
 | 	int OffsetRgn(int x, int y) | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn != NULL); | 
 | 		return ::OffsetRgn(m_hRgn, x, y); | 
 | 	} | 
 |  | 
 | 	int OffsetRgn(POINT point) | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn != NULL); | 
 | 		return ::OffsetRgn(m_hRgn, point.x, point.y); | 
 | 	} | 
 |  | 
 | 	int GetRgnBox(LPRECT lpRect) const | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn != NULL); | 
 | 		return ::GetRgnBox(m_hRgn, lpRect); | 
 | 	} | 
 |  | 
 | 	BOOL PtInRegion(int x, int y) const | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn != NULL); | 
 | 		return ::PtInRegion(m_hRgn, x, y); | 
 | 	} | 
 |  | 
 | 	BOOL PtInRegion(POINT point) const | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn != NULL); | 
 | 		return ::PtInRegion(m_hRgn, point.x, point.y); | 
 | 	} | 
 |  | 
 | 	BOOL RectInRegion(LPCRECT lpRect) const | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn != NULL); | 
 | 		return ::RectInRegion(m_hRgn, lpRect); | 
 | 	} | 
 |  | 
 | 	int GetRegionData(LPRGNDATA lpRgnData, int nDataSize) const | 
 | 	{ | 
 | 		ATLASSERT(m_hRgn != NULL); | 
 | 		return (int)::GetRegionData(m_hRgn, nDataSize, lpRgnData); | 
 | 	} | 
 | }; | 
 |  | 
 | typedef CRgnT<false>   CRgnHandle; | 
 | typedef CRgnT<true>    CRgn; | 
 |  | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 | // CDC - The device context class | 
 |  | 
 | template <bool t_bManaged> | 
 | class CDCT | 
 | { | 
 | public: | 
 | // Data members | 
 | 	HDC m_hDC; | 
 |  | 
 | // Constructor/destructor/operators | 
 | 	CDCT(HDC hDC = NULL) : m_hDC(hDC) | 
 | 	{ | 
 | 	} | 
 |  | 
 | 	~CDCT() | 
 | 	{ | 
 | 		if(t_bManaged && m_hDC != NULL) | 
 | 			::DeleteDC(Detach()); | 
 | 	} | 
 |  | 
 | 	CDCT<t_bManaged>& operator =(HDC hDC) | 
 | 	{ | 
 | 		Attach(hDC); | 
 | 		return *this; | 
 | 	} | 
 |  | 
 | 	void Attach(HDC hDC) | 
 | 	{ | 
 | 		if(t_bManaged && m_hDC != NULL && m_hDC != hDC) | 
 | 			::DeleteDC(m_hDC); | 
 | 		m_hDC = hDC; | 
 | 	} | 
 |  | 
 | 	HDC Detach() | 
 | 	{ | 
 | 		HDC hDC = m_hDC; | 
 | 		m_hDC = NULL; | 
 | 		return hDC; | 
 | 	} | 
 |  | 
 | 	operator HDC() const { return m_hDC; } | 
 |  | 
 | 	bool IsNull() const { return (m_hDC == NULL); } | 
 |  | 
 | // Operations | 
 | #ifndef _WIN32_WCE | 
 | 	HWND WindowFromDC() const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::WindowFromDC(m_hDC); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	CPenHandle GetCurrentPen() const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return CPenHandle((HPEN)::GetCurrentObject(m_hDC, OBJ_PEN)); | 
 | 	} | 
 |  | 
 | 	CBrushHandle GetCurrentBrush() const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return CBrushHandle((HBRUSH)::GetCurrentObject(m_hDC, OBJ_BRUSH)); | 
 | 	} | 
 |  | 
 | 	CPaletteHandle GetCurrentPalette() const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return CPaletteHandle((HPALETTE)::GetCurrentObject(m_hDC, OBJ_PAL)); | 
 | 	} | 
 |  | 
 | 	CFontHandle GetCurrentFont() const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return CFontHandle((HFONT)::GetCurrentObject(m_hDC, OBJ_FONT)); | 
 | 	} | 
 |  | 
 | 	CBitmapHandle GetCurrentBitmap() const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return CBitmapHandle((HBITMAP)::GetCurrentObject(m_hDC, OBJ_BITMAP)); | 
 | 	} | 
 |  | 
 | 	HDC CreateDC(LPCTSTR lpszDriverName, LPCTSTR lpszDeviceName, LPCTSTR lpszOutput, const DEVMODE* lpInitData) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC == NULL); | 
 | 		m_hDC = ::CreateDC(lpszDriverName, lpszDeviceName, lpszOutput, lpInitData); | 
 | 		return m_hDC; | 
 | 	} | 
 |  | 
 | 	HDC CreateCompatibleDC(HDC hDC = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC == NULL); | 
 | 		m_hDC = ::CreateCompatibleDC(hDC); | 
 | 		return m_hDC; | 
 | 	} | 
 |  | 
 | 	BOOL DeleteDC() | 
 | 	{ | 
 | 		if(m_hDC == NULL) | 
 | 			return FALSE; | 
 | 		BOOL bRet = ::DeleteDC(m_hDC); | 
 | 		if(bRet) | 
 | 			m_hDC = NULL; | 
 | 		return bRet; | 
 | 	} | 
 |  | 
 | // Device-Context Functions | 
 | 	int SaveDC() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SaveDC(m_hDC); | 
 | 	} | 
 |  | 
 | 	BOOL RestoreDC(int nSavedDC) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::RestoreDC(m_hDC, nSavedDC); | 
 | 	} | 
 |  | 
 | 	int GetDeviceCaps(int nIndex) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetDeviceCaps(m_hDC, nIndex); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	UINT SetBoundsRect(LPCRECT lpRectBounds, UINT flags) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetBoundsRect(m_hDC, lpRectBounds, flags); | 
 | 	} | 
 |  | 
 | 	UINT GetBoundsRect(LPRECT lpRectBounds, UINT flags) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetBoundsRect(m_hDC, lpRectBounds, flags); | 
 | 	} | 
 |  | 
 | 	BOOL ResetDC(const DEVMODE* lpDevMode) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::ResetDC(m_hDC, lpDevMode) != NULL; | 
 | 	} | 
 |  | 
 | // Drawing-Tool Functions | 
 | 	BOOL GetBrushOrg(LPPOINT lpPoint) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetBrushOrgEx(m_hDC, lpPoint); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	BOOL SetBrushOrg(int x, int y, LPPOINT lpPoint = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetBrushOrgEx(m_hDC, x, y, lpPoint); | 
 | 	} | 
 |  | 
 | 	BOOL SetBrushOrg(POINT point, LPPOINT lpPointRet = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetBrushOrgEx(m_hDC, point.x, point.y, lpPointRet); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	int EnumObjects(int nObjectType, int (CALLBACK* lpfn)(LPVOID, LPARAM), LPARAM lpData) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | #ifdef STRICT | 
 | 		return ::EnumObjects(m_hDC, nObjectType, (GOBJENUMPROC)lpfn, lpData); | 
 | #else | 
 | 		return ::EnumObjects(m_hDC, nObjectType, (GOBJENUMPROC)lpfn, (LPVOID)lpData); | 
 | #endif | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | // Type-safe selection helpers | 
 | 	HPEN SelectPen(HPEN hPen) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | #ifndef _WIN32_WCE | 
 | 		ATLASSERT(hPen == NULL || ::GetObjectType(hPen) == OBJ_PEN || ::GetObjectType(hPen) == OBJ_EXTPEN); | 
 | #else // CE specific | 
 | 		ATLASSERT(hPen == NULL || ::GetObjectType(hPen) == OBJ_PEN); | 
 | #endif // _WIN32_WCE | 
 | 		return (HPEN)::SelectObject(m_hDC, hPen); | 
 | 	} | 
 |  | 
 | 	HBRUSH SelectBrush(HBRUSH hBrush) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		ATLASSERT(hBrush == NULL || ::GetObjectType(hBrush) == OBJ_BRUSH); | 
 | 		return (HBRUSH)::SelectObject(m_hDC, hBrush); | 
 | 	} | 
 |  | 
 | 	HFONT SelectFont(HFONT hFont) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		ATLASSERT(hFont == NULL || ::GetObjectType(hFont) == OBJ_FONT); | 
 | 		return (HFONT)::SelectObject(m_hDC, hFont); | 
 | 	} | 
 |  | 
 | 	HBITMAP SelectBitmap(HBITMAP hBitmap) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		ATLASSERT(hBitmap == NULL || ::GetObjectType(hBitmap) == OBJ_BITMAP); | 
 | 		return (HBITMAP)::SelectObject(m_hDC, hBitmap); | 
 | 	} | 
 |  | 
 | 	int SelectRgn(HRGN hRgn)       // special return for regions | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		ATLASSERT(hRgn == NULL || ::GetObjectType(hRgn) == OBJ_REGION); | 
 | 		return PtrToInt(::SelectObject(m_hDC, hRgn)); | 
 | 	} | 
 |  | 
 | // Type-safe selection helpers for stock objects | 
 | 	HPEN SelectStockPen(int nPen) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | #if (_WIN32_WINNT >= 0x0500) | 
 | 		ATLASSERT(nPen == WHITE_PEN || nPen == BLACK_PEN || nPen == NULL_PEN || nPen == DC_PEN); | 
 | #else | 
 | 		ATLASSERT(nPen == WHITE_PEN || nPen == BLACK_PEN || nPen == NULL_PEN); | 
 | #endif // !(_WIN32_WINNT >= 0x0500) | 
 | 		return SelectPen((HPEN)::GetStockObject(nPen)); | 
 | 	} | 
 |  | 
 | 	HBRUSH SelectStockBrush(int nBrush) | 
 | 	{ | 
 | #if (_WIN32_WINNT >= 0x0500) | 
 | 		ATLASSERT((nBrush >= WHITE_BRUSH && nBrush <= HOLLOW_BRUSH) || nBrush == DC_BRUSH); | 
 | #else | 
 | 		ATLASSERT(nBrush >= WHITE_BRUSH && nBrush <= HOLLOW_BRUSH); | 
 | #endif // !(_WIN32_WINNT >= 0x0500) | 
 | 		return SelectBrush((HBRUSH)::GetStockObject(nBrush)); | 
 | 	} | 
 |  | 
 | 	HFONT SelectStockFont(int nFont) | 
 | 	{ | 
 | #ifndef _WIN32_WCE | 
 | 		ATLASSERT((nFont >= OEM_FIXED_FONT && nFont <= SYSTEM_FIXED_FONT) || nFont == DEFAULT_GUI_FONT); | 
 | #else // CE specific | 
 | 		ATLASSERT(nFont == SYSTEM_FONT); | 
 | #endif // _WIN32_WCE | 
 | 		return SelectFont((HFONT)::GetStockObject(nFont)); | 
 | 	} | 
 |  | 
 | 	HPALETTE SelectStockPalette(int nPalette, BOOL bForceBackground) | 
 | 	{ | 
 | 		ATLASSERT(nPalette == DEFAULT_PALETTE); // the only one supported | 
 | 		return SelectPalette((HPALETTE)::GetStockObject(nPalette), bForceBackground); | 
 | 	} | 
 |  | 
 | // Color and Color Palette Functions | 
 | 	COLORREF GetNearestColor(COLORREF crColor) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetNearestColor(m_hDC, crColor); | 
 | 	} | 
 |  | 
 | 	HPALETTE SelectPalette(HPALETTE hPalette, BOOL bForceBackground) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 |  | 
 | 		return ::SelectPalette(m_hDC, hPalette, bForceBackground); | 
 | 	} | 
 |  | 
 | 	UINT RealizePalette() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::RealizePalette(m_hDC); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	void UpdateColors() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		::UpdateColors(m_hDC); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | // Drawing-Attribute Functions | 
 | 	COLORREF GetBkColor() const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetBkColor(m_hDC); | 
 | 	} | 
 |  | 
 | 	int GetBkMode() const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetBkMode(m_hDC); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	int GetPolyFillMode() const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetPolyFillMode(m_hDC); | 
 | 	} | 
 |  | 
 | 	int GetROP2() const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetROP2(m_hDC); | 
 | 	} | 
 |  | 
 | 	int GetStretchBltMode() const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetStretchBltMode(m_hDC); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	COLORREF GetTextColor() const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetTextColor(m_hDC); | 
 | 	} | 
 |  | 
 | 	COLORREF SetBkColor(COLORREF crColor) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetBkColor(m_hDC, crColor); | 
 | 	} | 
 |  | 
 | 	int SetBkMode(int nBkMode) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetBkMode(m_hDC, nBkMode); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	int SetPolyFillMode(int nPolyFillMode) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetPolyFillMode(m_hDC, nPolyFillMode); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	int SetROP2(int nDrawMode) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetROP2(m_hDC, nDrawMode); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	int SetStretchBltMode(int nStretchMode) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetStretchBltMode(m_hDC, nStretchMode); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	COLORREF SetTextColor(COLORREF crColor) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetTextColor(m_hDC, crColor); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	BOOL GetColorAdjustment(LPCOLORADJUSTMENT lpColorAdjust) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetColorAdjustment(m_hDC, lpColorAdjust); | 
 | 	} | 
 |  | 
 | 	BOOL SetColorAdjustment(const COLORADJUSTMENT* lpColorAdjust) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetColorAdjustment(m_hDC, lpColorAdjust); | 
 | 	} | 
 |  | 
 | // Mapping Functions | 
 | 	int GetMapMode() const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetMapMode(m_hDC); | 
 | 	} | 
 |  | 
 | 	BOOL GetViewportOrg(LPPOINT lpPoint) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetViewportOrgEx(m_hDC, lpPoint); | 
 | 	} | 
 |  | 
 | 	int SetMapMode(int nMapMode) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetMapMode(m_hDC, nMapMode); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	// Viewport Origin | 
 | 	BOOL SetViewportOrg(int x, int y, LPPOINT lpPoint = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetViewportOrgEx(m_hDC, x, y, lpPoint); | 
 | 	} | 
 |  | 
 | 	BOOL SetViewportOrg(POINT point, LPPOINT lpPointRet = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return SetViewportOrg(point.x, point.y, lpPointRet); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	BOOL OffsetViewportOrg(int nWidth, int nHeight, LPPOINT lpPoint = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::OffsetViewportOrgEx(m_hDC, nWidth, nHeight, lpPoint); | 
 | 	} | 
 |  | 
 | 	// Viewport Extent | 
 | 	BOOL GetViewportExt(LPSIZE lpSize) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetViewportExtEx(m_hDC, lpSize); | 
 | 	} | 
 |  | 
 | 	BOOL SetViewportExt(int x, int y, LPSIZE lpSize = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetViewportExtEx(m_hDC, x, y, lpSize); | 
 | 	} | 
 |  | 
 | 	BOOL SetViewportExt(SIZE size, LPSIZE lpSizeRet = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return SetViewportExt(size.cx, size.cy, lpSizeRet); | 
 | 	} | 
 |  | 
 | 	BOOL ScaleViewportExt(int xNum, int xDenom, int yNum, int yDenom, LPSIZE lpSize = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::ScaleViewportExtEx(m_hDC, xNum, xDenom, yNum, yDenom, lpSize); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	// Window Origin | 
 | #ifndef _WIN32_WCE | 
 | 	BOOL GetWindowOrg(LPPOINT lpPoint) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetWindowOrgEx(m_hDC, lpPoint); | 
 | 	} | 
 |  | 
 | 	BOOL SetWindowOrg(int x, int y, LPPOINT lpPoint = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetWindowOrgEx(m_hDC, x, y, lpPoint); | 
 | 	} | 
 |  | 
 | 	BOOL SetWindowOrg(POINT point, LPPOINT lpPointRet = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return SetWindowOrg(point.x, point.y, lpPointRet); | 
 | 	} | 
 |  | 
 | 	BOOL OffsetWindowOrg(int nWidth, int nHeight, LPPOINT lpPoint = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::OffsetWindowOrgEx(m_hDC, nWidth, nHeight, lpPoint); | 
 | 	} | 
 |  | 
 | 	// Window extent | 
 | 	BOOL GetWindowExt(LPSIZE lpSize) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetWindowExtEx(m_hDC, lpSize); | 
 | 	} | 
 |  | 
 | 	BOOL SetWindowExt(int x, int y, LPSIZE lpSize = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetWindowExtEx(m_hDC, x, y, lpSize); | 
 | 	} | 
 |  | 
 | 	BOOL SetWindowExt(SIZE size, LPSIZE lpSizeRet = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return SetWindowExt(size.cx, size.cy, lpSizeRet); | 
 | 	} | 
 |  | 
 | 	BOOL ScaleWindowExt(int xNum, int xDenom, int yNum, int yDenom, LPSIZE lpSize = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::ScaleWindowExtEx(m_hDC, xNum, xDenom, yNum, yDenom, lpSize); | 
 | 	} | 
 |  | 
 | // Coordinate Functions | 
 | 	BOOL DPtoLP(LPPOINT lpPoints, int nCount = 1) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::DPtoLP(m_hDC, lpPoints, nCount); | 
 | 	} | 
 |  | 
 | 	BOOL DPtoLP(LPRECT lpRect) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::DPtoLP(m_hDC, (LPPOINT)lpRect, 2); | 
 | 	} | 
 |  | 
 | 	BOOL DPtoLP(LPSIZE lpSize) const | 
 | 	{ | 
 | 		SIZE sizeWinExt = { 0, 0 }; | 
 | 		if(!GetWindowExt(&sizeWinExt)) | 
 | 			return FALSE; | 
 | 		SIZE sizeVpExt = { 0, 0 }; | 
 | 		if(!GetViewportExt(&sizeVpExt)) | 
 | 			return FALSE; | 
 | 		lpSize->cx = ::MulDiv(lpSize->cx, abs(sizeWinExt.cx), abs(sizeVpExt.cx)); | 
 | 		lpSize->cy = ::MulDiv(lpSize->cy, abs(sizeWinExt.cy), abs(sizeVpExt.cy)); | 
 | 		return TRUE; | 
 | 	} | 
 |  | 
 | 	BOOL LPtoDP(LPPOINT lpPoints, int nCount = 1) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::LPtoDP(m_hDC, lpPoints, nCount); | 
 | 	} | 
 |  | 
 | 	BOOL LPtoDP(LPRECT lpRect) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::LPtoDP(m_hDC, (LPPOINT)lpRect, 2); | 
 | 	} | 
 |  | 
 | 	BOOL LPtoDP(LPSIZE lpSize) const | 
 | 	{ | 
 | 		SIZE sizeWinExt = { 0, 0 }; | 
 | 		if(!GetWindowExt(&sizeWinExt)) | 
 | 			return FALSE; | 
 | 		SIZE sizeVpExt = { 0, 0 }; | 
 | 		if(!GetViewportExt(&sizeVpExt)) | 
 | 			return FALSE; | 
 | 		lpSize->cx = ::MulDiv(lpSize->cx, abs(sizeVpExt.cx), abs(sizeWinExt.cx)); | 
 | 		lpSize->cy = ::MulDiv(lpSize->cy, abs(sizeVpExt.cy), abs(sizeWinExt.cy)); | 
 | 		return TRUE; | 
 | 	} | 
 |  | 
 | // Special Coordinate Functions (useful for dealing with metafiles and OLE) | 
 | 	#define HIMETRIC_INCH   2540    // HIMETRIC units per inch | 
 |  | 
 | 	void DPtoHIMETRIC(LPSIZE lpSize) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		int nMapMode; | 
 | 		if((nMapMode = GetMapMode()) < MM_ISOTROPIC && nMapMode != MM_TEXT) | 
 | 		{ | 
 | 			// when using a constrained map mode, map against physical inch | 
 | 			((CDCHandle*)this)->SetMapMode(MM_HIMETRIC); | 
 | 			DPtoLP(lpSize); | 
 | 			((CDCHandle*)this)->SetMapMode(nMapMode); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			// map against logical inch for non-constrained mapping modes | 
 | 			int cxPerInch = GetDeviceCaps(LOGPIXELSX); | 
 | 			int cyPerInch = GetDeviceCaps(LOGPIXELSY); | 
 | 			ATLASSERT(cxPerInch != 0 && cyPerInch != 0); | 
 | 			lpSize->cx = ::MulDiv(lpSize->cx, HIMETRIC_INCH, cxPerInch); | 
 | 			lpSize->cy = ::MulDiv(lpSize->cy, HIMETRIC_INCH, cyPerInch); | 
 | 		} | 
 | 	} | 
 |  | 
 | 	void HIMETRICtoDP(LPSIZE lpSize) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		int nMapMode; | 
 | 		if((nMapMode = GetMapMode()) < MM_ISOTROPIC && nMapMode != MM_TEXT) | 
 | 		{ | 
 | 			// when using a constrained map mode, map against physical inch | 
 | 			((CDCHandle*)this)->SetMapMode(MM_HIMETRIC); | 
 | 			LPtoDP(lpSize); | 
 | 			((CDCHandle*)this)->SetMapMode(nMapMode); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			// map against logical inch for non-constrained mapping modes | 
 | 			int cxPerInch = GetDeviceCaps(LOGPIXELSX); | 
 | 			int cyPerInch = GetDeviceCaps(LOGPIXELSY); | 
 | 			ATLASSERT(cxPerInch != 0 && cyPerInch != 0); | 
 | 			lpSize->cx = ::MulDiv(lpSize->cx, cxPerInch, HIMETRIC_INCH); | 
 | 			lpSize->cy = ::MulDiv(lpSize->cy, cyPerInch, HIMETRIC_INCH); | 
 | 		} | 
 | 	} | 
 |  | 
 | 	void LPtoHIMETRIC(LPSIZE lpSize) const | 
 | 	{ | 
 | 		LPtoDP(lpSize); | 
 | 		DPtoHIMETRIC(lpSize); | 
 | 	} | 
 |  | 
 | 	void HIMETRICtoLP(LPSIZE lpSize) const | 
 | 	{ | 
 | 		HIMETRICtoDP(lpSize); | 
 | 		DPtoLP(lpSize); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | // Region Functions | 
 | 	BOOL FillRgn(HRGN hRgn, HBRUSH hBrush) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::FillRgn(m_hDC, hRgn, hBrush); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	BOOL FrameRgn(HRGN hRgn, HBRUSH hBrush, int nWidth, int nHeight) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::FrameRgn(m_hDC, hRgn, hBrush, nWidth, nHeight); | 
 | 	} | 
 |  | 
 | 	BOOL InvertRgn(HRGN hRgn) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::InvertRgn(m_hDC, hRgn); | 
 | 	} | 
 |  | 
 | 	BOOL PaintRgn(HRGN hRgn) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::PaintRgn(m_hDC, hRgn); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | // Clipping Functions | 
 | 	int GetClipBox(LPRECT lpRect) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetClipBox(m_hDC, lpRect); | 
 | 	} | 
 |  | 
 | 	int GetClipRgn(CRgn& region) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		if(region.IsNull()) | 
 | 			region.CreateRectRgn(0, 0, 0, 0); | 
 |  | 
 | 		int nRet = ::GetClipRgn(m_hDC, region); | 
 | 		if(nRet != 1) | 
 | 			region.DeleteObject(); | 
 |  | 
 | 		return nRet; | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	BOOL PtVisible(int x, int y) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::PtVisible(m_hDC, x, y); | 
 | 	} | 
 |  | 
 | 	BOOL PtVisible(POINT point) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::PtVisible(m_hDC, point.x, point.y); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	BOOL RectVisible(LPCRECT lpRect) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::RectVisible(m_hDC, lpRect); | 
 | 	} | 
 |  | 
 | 	int SelectClipRgn(HRGN hRgn) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SelectClipRgn(m_hDC, (HRGN)hRgn); | 
 | 	} | 
 |  | 
 | 	int ExcludeClipRect(int x1, int y1, int x2, int y2) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::ExcludeClipRect(m_hDC, x1, y1, x2, y2); | 
 | 	} | 
 |  | 
 | 	int ExcludeClipRect(LPCRECT lpRect) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::ExcludeClipRect(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	int ExcludeUpdateRgn(HWND hWnd) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::ExcludeUpdateRgn(m_hDC, hWnd); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	int IntersectClipRect(int x1, int y1, int x2, int y2) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::IntersectClipRect(m_hDC, x1, y1, x2, y2); | 
 | 	} | 
 |  | 
 | 	int IntersectClipRect(LPCRECT lpRect) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::IntersectClipRect(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	int OffsetClipRgn(int x, int y) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::OffsetClipRgn(m_hDC, x, y); | 
 | 	} | 
 |  | 
 | 	int OffsetClipRgn(SIZE size) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::OffsetClipRgn(m_hDC, size.cx, size.cy); | 
 | 	} | 
 |  | 
 | 	int SelectClipRgn(HRGN hRgn, int nMode) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::ExtSelectClipRgn(m_hDC, hRgn, nMode); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | // Line-Output Functions | 
 | #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) | 
 | 	BOOL GetCurrentPosition(LPPOINT lpPoint) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetCurrentPositionEx(m_hDC, lpPoint); | 
 | 	} | 
 |  | 
 | 	BOOL MoveTo(int x, int y, LPPOINT lpPoint = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::MoveToEx(m_hDC, x, y, lpPoint); | 
 | 	} | 
 |  | 
 | 	BOOL MoveTo(POINT point, LPPOINT lpPointRet = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return MoveTo(point.x, point.y, lpPointRet); | 
 | 	} | 
 |  | 
 | 	BOOL LineTo(int x, int y) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::LineTo(m_hDC, x, y); | 
 | 	} | 
 |  | 
 | 	BOOL LineTo(POINT point) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return LineTo(point.x, point.y); | 
 | 	} | 
 | #endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	BOOL Arc(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::Arc(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4); | 
 | 	} | 
 |  | 
 | 	BOOL Arc(LPCRECT lpRect, POINT ptStart, POINT ptEnd) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::Arc(m_hDC, lpRect->left, lpRect->top, | 
 | 			lpRect->right, lpRect->bottom, ptStart.x, ptStart.y, | 
 | 			ptEnd.x, ptEnd.y); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	BOOL Polyline(LPPOINT lpPoints, int nCount) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::Polyline(m_hDC, lpPoints, nCount); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	BOOL AngleArc(int x, int y, int nRadius, float fStartAngle, float fSweepAngle) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::AngleArc(m_hDC, x, y, nRadius, fStartAngle, fSweepAngle); | 
 | 	} | 
 |  | 
 | 	BOOL ArcTo(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::ArcTo(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4); | 
 | 	} | 
 |  | 
 | 	BOOL ArcTo(LPCRECT lpRect, POINT ptStart, POINT ptEnd) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ArcTo(lpRect->left, lpRect->top, lpRect->right, | 
 | 		lpRect->bottom, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y); | 
 | 	} | 
 |  | 
 | 	int GetArcDirection() const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetArcDirection(m_hDC); | 
 | 	} | 
 |  | 
 | 	int SetArcDirection(int nArcDirection) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetArcDirection(m_hDC, nArcDirection); | 
 | 	} | 
 |  | 
 | 	BOOL PolyDraw(const POINT* lpPoints, const BYTE* lpTypes, int nCount) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::PolyDraw(m_hDC, lpPoints, lpTypes, nCount); | 
 | 	} | 
 |  | 
 | 	BOOL PolylineTo(const POINT* lpPoints, int nCount) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::PolylineTo(m_hDC, lpPoints, nCount); | 
 | 	} | 
 |  | 
 | 	BOOL PolyPolyline(const POINT* lpPoints, | 
 | 		const DWORD* lpPolyPoints, int nCount) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::PolyPolyline(m_hDC, lpPoints, lpPolyPoints, nCount); | 
 | 	} | 
 |  | 
 | 	BOOL PolyBezier(const POINT* lpPoints, int nCount) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::PolyBezier(m_hDC, lpPoints, nCount); | 
 | 	} | 
 |  | 
 | 	BOOL PolyBezierTo(const POINT* lpPoints, int nCount) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::PolyBezierTo(m_hDC, lpPoints, nCount); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | // Simple Drawing Functions | 
 | 	BOOL FillRect(LPCRECT lpRect, HBRUSH hBrush) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::FillRect(m_hDC, lpRect, hBrush); | 
 | 	} | 
 |  | 
 | 	BOOL FillRect(LPCRECT lpRect, int nColorIndex) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | #ifndef _WIN32_WCE | 
 | 		return ::FillRect(m_hDC, lpRect, (HBRUSH)LongToPtr(nColorIndex + 1)); | 
 | #else // CE specific | 
 | 		return ::FillRect(m_hDC, lpRect, ::GetSysColorBrush(nColorIndex)); | 
 | #endif // _WIN32_WCE | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	BOOL FrameRect(LPCRECT lpRect, HBRUSH hBrush) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::FrameRect(m_hDC, lpRect, hBrush); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 420) | 
 | 	BOOL InvertRect(LPCRECT lpRect) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::InvertRect(m_hDC, lpRect); | 
 | 	} | 
 | #endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 420) | 
 |  | 
 | 	BOOL DrawIcon(int x, int y, HICON hIcon) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | #ifndef _WIN32_WCE | 
 | 		return ::DrawIcon(m_hDC, x, y, hIcon); | 
 | #else // CE specific | 
 | 		return ::DrawIconEx(m_hDC, x, y, hIcon, 0, 0, 0, NULL, DI_NORMAL); | 
 | #endif // _WIN32_WCE | 
 | 	} | 
 |  | 
 | 	BOOL DrawIcon(POINT point, HICON hIcon) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | #ifndef _WIN32_WCE | 
 | 		return ::DrawIcon(m_hDC, point.x, point.y, hIcon); | 
 | #else // CE specific | 
 | 		return ::DrawIconEx(m_hDC, point.x, point.y, hIcon, 0, 0, 0, NULL, DI_NORMAL); | 
 | #endif // _WIN32_WCE | 
 | 	} | 
 |  | 
 | 	BOOL DrawIconEx(int x, int y, HICON hIcon, int cxWidth, int cyWidth, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::DrawIconEx(m_hDC, x, y, hIcon, cxWidth, cyWidth, uStepIfAniCur, hbrFlickerFreeDraw, uFlags); | 
 | 	} | 
 |  | 
 | 	BOOL DrawIconEx(POINT point, HICON hIcon, SIZE size, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::DrawIconEx(m_hDC, point.x, point.y, hIcon, size.cx, size.cy, uStepIfAniCur, hbrFlickerFreeDraw, uFlags); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	BOOL DrawState(POINT pt, SIZE size, HBITMAP hBitmap, UINT nFlags, HBRUSH hBrush = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::DrawState(m_hDC, hBrush, NULL, (LPARAM)hBitmap, 0, pt.x, pt.y, size.cx, size.cy, nFlags | DST_BITMAP); | 
 | 	} | 
 |  | 
 | 	BOOL DrawState(POINT pt, SIZE size, HICON hIcon, UINT nFlags, HBRUSH hBrush = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::DrawState(m_hDC, hBrush, NULL, (LPARAM)hIcon, 0, pt.x, pt.y, size.cx, size.cy, nFlags | DST_ICON); | 
 | 	} | 
 |  | 
 | 	BOOL DrawState(POINT pt, SIZE size, LPCTSTR lpszText, UINT nFlags, BOOL bPrefixText = TRUE, int nTextLen = 0, HBRUSH hBrush = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::DrawState(m_hDC, hBrush, NULL, (LPARAM)lpszText, (WPARAM)nTextLen, pt.x, pt.y, size.cx, size.cy, nFlags | (bPrefixText ? DST_PREFIXTEXT : DST_TEXT)); | 
 | 	} | 
 |  | 
 | 	BOOL DrawState(POINT pt, SIZE size, DRAWSTATEPROC lpDrawProc, LPARAM lData, UINT nFlags, HBRUSH hBrush = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::DrawState(m_hDC, hBrush, lpDrawProc, lData, 0, pt.x, pt.y, size.cx, size.cy, nFlags | DST_COMPLEX); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | // Ellipse and Polygon Functions | 
 | #ifndef _WIN32_WCE | 
 | 	BOOL Chord(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::Chord(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4); | 
 | 	} | 
 |  | 
 | 	BOOL Chord(LPCRECT lpRect, POINT ptStart, POINT ptEnd) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::Chord(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	void DrawFocusRect(LPCRECT lpRect) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		::DrawFocusRect(m_hDC, lpRect); | 
 | 	} | 
 |  | 
 | 	BOOL Ellipse(int x1, int y1, int x2, int y2) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::Ellipse(m_hDC, x1, y1, x2, y2); | 
 | 	} | 
 |  | 
 | 	BOOL Ellipse(LPCRECT lpRect) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::Ellipse(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	BOOL Pie(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::Pie(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4); | 
 | 	} | 
 |  | 
 | 	BOOL Pie(LPCRECT lpRect, POINT ptStart, POINT ptEnd) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::Pie(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	BOOL Polygon(LPPOINT lpPoints, int nCount) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::Polygon(m_hDC, lpPoints, nCount); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	BOOL PolyPolygon(LPPOINT lpPoints, LPINT lpPolyCounts, int nCount) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::PolyPolygon(m_hDC, lpPoints, lpPolyCounts, nCount); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	BOOL Rectangle(int x1, int y1, int x2, int y2) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::Rectangle(m_hDC, x1, y1, x2, y2); | 
 | 	} | 
 |  | 
 | 	BOOL Rectangle(LPCRECT lpRect) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::Rectangle(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); | 
 | 	} | 
 |  | 
 | 	BOOL RoundRect(int x1, int y1, int x2, int y2, int x3, int y3) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::RoundRect(m_hDC, x1, y1, x2, y2, x3, y3); | 
 | 	} | 
 |  | 
 | 	BOOL RoundRect(LPCRECT lpRect, POINT point) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::RoundRect(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, point.x, point.y); | 
 | 	} | 
 |  | 
 | // Bitmap Functions | 
 | 	BOOL PatBlt(int x, int y, int nWidth, int nHeight, DWORD dwRop) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::PatBlt(m_hDC, x, y, nWidth, nHeight, dwRop); | 
 | 	} | 
 |  | 
 | 	BOOL BitBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, | 
 | 		int xSrc, int ySrc, DWORD dwRop) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::BitBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, dwRop); | 
 | 	} | 
 |  | 
 | 	BOOL StretchBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::StretchBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, dwRop); | 
 | 	} | 
 |  | 
 | 	COLORREF GetPixel(int x, int y) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetPixel(m_hDC, x, y); | 
 | 	} | 
 |  | 
 | 	COLORREF GetPixel(POINT point) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetPixel(m_hDC, point.x, point.y); | 
 | 	} | 
 |  | 
 | 	COLORREF SetPixel(int x, int y, COLORREF crColor) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetPixel(m_hDC, x, y, crColor); | 
 | 	} | 
 |  | 
 | 	COLORREF SetPixel(POINT point, COLORREF crColor) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetPixel(m_hDC, point.x, point.y, crColor); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	BOOL FloodFill(int x, int y, COLORREF crColor) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::FloodFill(m_hDC, x, y, crColor); | 
 | 	} | 
 |  | 
 | 	BOOL ExtFloodFill(int x, int y, COLORREF crColor, UINT nFillType) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::ExtFloodFill(m_hDC, x, y, crColor, nFillType); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	BOOL MaskBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, HBITMAP hMaskBitmap, int xMask, int yMask, DWORD dwRop) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::MaskBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, hMaskBitmap, xMask, yMask, dwRop); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	BOOL PlgBlt(LPPOINT lpPoint, HDC hSrcDC, int xSrc, int ySrc, int nWidth, int nHeight, HBITMAP hMaskBitmap, int xMask, int yMask) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::PlgBlt(m_hDC, lpPoint, hSrcDC, xSrc, ySrc, nWidth, nHeight, hMaskBitmap, xMask, yMask); | 
 | 	} | 
 |  | 
 | 	BOOL SetPixelV(int x, int y, COLORREF crColor) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetPixelV(m_hDC, x, y, crColor); | 
 | 	} | 
 |  | 
 | 	BOOL SetPixelV(POINT point, COLORREF crColor) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetPixelV(m_hDC, point.x, point.y, crColor); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | #if !defined(_ATL_NO_MSIMG) || defined(_WIN32_WCE) | 
 | #ifndef _WIN32_WCE | 
 | 	BOOL TransparentBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, UINT crTransparent) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::TransparentBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, crTransparent); | 
 | 	} | 
 | #else // CE specific | 
 | 	BOOL TransparentImage(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, UINT crTransparent) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::TransparentImage(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, crTransparent); | 
 | 	} | 
 | #endif // _WIN32_WCE | 
 |  | 
 | #if (!defined(_WIN32_WCE) || (_WIN32_WCE >= 420)) | 
 | 	BOOL GradientFill(const PTRIVERTEX pVertices, DWORD nVertices, void* pMeshElements, DWORD nMeshElements, DWORD dwMode) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GradientFill(m_hDC, pVertices, nVertices, pMeshElements, nMeshElements, dwMode); | 
 | 	} | 
 | #endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 420) | 
 |  | 
 | #if !defined(_WIN32_WCE) || (_WIN32_WCE > 0x500) | 
 | 	BOOL AlphaBlend(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, BLENDFUNCTION bf) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::AlphaBlend(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, bf); | 
 | 	} | 
 | #endif // !defined(_WIN32_WCE) || (_WIN32_WCE > 0x500) | 
 | #endif //  !defined(_ATL_NO_MSIMG) || defined(_WIN32_WCE) | 
 |  | 
 | // Extra bitmap functions | 
 | 	// Helper function for painting a disabled toolbar or menu bitmap | 
 | 	// This function can take either an HBITMAP (for SS) or a DC with  | 
 | 	//           the bitmap already painted (for cmdbar) | 
 | 	BOOL DitherBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, HBITMAP hBitmap, int xSrc, int ySrc, | 
 | 			HBRUSH hBrushBackground = ::GetSysColorBrush(COLOR_3DFACE), | 
 | 			HBRUSH hBrush3DEffect = ::GetSysColorBrush(COLOR_3DHILIGHT), | 
 | 			HBRUSH hBrushDisabledImage = ::GetSysColorBrush(COLOR_3DSHADOW)) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL || hBitmap != NULL); | 
 | 		ATLASSERT(nWidth > 0 && nHeight > 0); | 
 | 		 | 
 | 		// Create a generic DC for all BitBlts | 
 | 		CDCHandle dc = (hSrcDC != NULL) ? hSrcDC : ::CreateCompatibleDC(m_hDC); | 
 | 		ATLASSERT(dc.m_hDC != NULL); | 
 | 		if(dc.m_hDC == NULL) | 
 | 			return FALSE; | 
 | 		 | 
 | 		// Create a DC for the monochrome DIB section | 
 | 		CDC dcBW = ::CreateCompatibleDC(m_hDC); | 
 | 		ATLASSERT(dcBW.m_hDC != NULL); | 
 | 		if(dcBW.m_hDC == NULL) | 
 | 		{ | 
 | 			if(hSrcDC == NULL) | 
 | 				dc.DeleteDC(); | 
 | 			return FALSE; | 
 | 		} | 
 |  | 
 | 		// Create the monochrome DIB section with a black and white palette | 
 | 		struct RGBBWBITMAPINFO | 
 | 		{ | 
 | 			BITMAPINFOHEADER bmiHeader;  | 
 | 			RGBQUAD bmiColors[2];  | 
 | 		}; | 
 |  | 
 | 		RGBBWBITMAPINFO rgbBWBitmapInfo =  | 
 | 		{ | 
 | 			{ sizeof(BITMAPINFOHEADER), nWidth, nHeight, 1, 1, BI_RGB, 0, 0, 0, 0, 0 }, | 
 | 			{ { 0x00, 0x00, 0x00, 0x00 }, { 0xFF, 0xFF, 0xFF, 0x00 } } | 
 | 		}; | 
 |  | 
 | 		VOID* pbitsBW; | 
 | 		CBitmap bmpBW = ::CreateDIBSection(dcBW, (LPBITMAPINFO)&rgbBWBitmapInfo, DIB_RGB_COLORS, &pbitsBW, NULL, 0); | 
 | 		ATLASSERT(bmpBW.m_hBitmap != NULL); | 
 | 		if(bmpBW.m_hBitmap == NULL) | 
 | 		{ | 
 | 			if(hSrcDC == NULL) | 
 | 				dc.DeleteDC(); | 
 | 			return FALSE; | 
 | 		} | 
 | 		 | 
 | 		// Attach the monochrome DIB section and the bitmap to the DCs | 
 | 		HBITMAP hbmOldBW = dcBW.SelectBitmap(bmpBW); | 
 | 		HBITMAP hbmOldDC = NULL; | 
 | 		if(hBitmap != NULL) | 
 | 			hbmOldDC = dc.SelectBitmap(hBitmap); | 
 |  | 
 | 		// Block: Dark gray removal: we want (128, 128, 128) pixels to become black and not white | 
 | 		{ | 
 | 			CDC dcTemp1 = ::CreateCompatibleDC(m_hDC); | 
 | 			CDC dcTemp2 = ::CreateCompatibleDC(m_hDC); | 
 | 			CBitmap bmpTemp1; | 
 | 			bmpTemp1.CreateCompatibleBitmap(dc, nWidth, nHeight); | 
 | 			CBitmap bmpTemp2; | 
 | 			bmpTemp2.CreateBitmap(nWidth, nHeight, 1, 1, NULL); | 
 | 			HBITMAP hOldBmp1 = dcTemp1.SelectBitmap(bmpTemp1); | 
 | 			HBITMAP hOldBmp2 = dcTemp2.SelectBitmap(bmpTemp2); | 
 | 			// Let's copy our image, it will be altered | 
 | 			dcTemp1.BitBlt(0, 0, nWidth, nHeight, dc, xSrc, ySrc, SRCCOPY); | 
 |  | 
 | 			// All dark gray pixels will become white, the others black | 
 | 			dcTemp1.SetBkColor(RGB(128, 128, 128)); | 
 | 			dcTemp2.BitBlt(0, 0, nWidth, nHeight, dcTemp1, 0, 0, SRCCOPY); | 
 | 			// Do an XOR to set to black these white pixels | 
 | 			dcTemp1.BitBlt(0, 0, nWidth, nHeight, dcTemp2, 0, 0, SRCINVERT); | 
 |  | 
 | 			// BitBlt the bitmap into the monochrome DIB section | 
 | 			// The DIB section will do a true monochrome conversion | 
 | 			// The magenta background being closer to white will become white | 
 | 			dcBW.BitBlt(0, 0, nWidth, nHeight, dcTemp1, 0, 0, SRCCOPY); | 
 |  | 
 | 			// Cleanup | 
 | 			dcTemp1.SelectBitmap(hOldBmp1); | 
 | 			dcTemp2.SelectBitmap(hOldBmp2); | 
 | 		} | 
 | 		 | 
 | 		// Paint the destination rectangle using hBrushBackground | 
 | 		if(hBrushBackground != NULL) | 
 | 		{ | 
 | 			RECT rc = { x, y, x + nWidth, y + nHeight }; | 
 | 			FillRect(&rc, hBrushBackground); | 
 | 		} | 
 |  | 
 | 		// BitBlt the black bits in the monochrome bitmap into hBrush3DEffect color in the destination DC | 
 | 		// The magic ROP comes from the Charles Petzold's book | 
 | 		HBRUSH hOldBrush = SelectBrush(hBrush3DEffect); | 
 | 		BitBlt(x + 1, y + 1, nWidth, nHeight, dcBW, 0, 0, 0xB8074A); | 
 |  | 
 | 		// BitBlt the black bits in the monochrome bitmap into hBrushDisabledImage color in the destination DC | 
 | 		SelectBrush(hBrushDisabledImage); | 
 | 		BitBlt(x, y, nWidth, nHeight, dcBW, 0, 0, 0xB8074A); | 
 |  | 
 | 		SelectBrush(hOldBrush); | 
 | 		dcBW.SelectBitmap(hbmOldBW); | 
 | 		dc.SelectBitmap(hbmOldDC); | 
 |  | 
 | 		if(hSrcDC == NULL) | 
 | 			dc.DeleteDC(); | 
 |  | 
 | 		return TRUE; | 
 | 	} | 
 |  | 
 | // Text Functions | 
 | #ifndef _WIN32_WCE | 
 | 	BOOL TextOut(int x, int y, LPCTSTR lpszString, int nCount = -1) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		if(nCount == -1) | 
 | 			nCount = lstrlen(lpszString); | 
 | 		return ::TextOut(m_hDC, x, y, lpszString, nCount); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	BOOL ExtTextOut(int x, int y, UINT nOptions, LPCRECT lpRect, LPCTSTR lpszString, UINT nCount = -1, LPINT lpDxWidths = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		if(nCount == -1) | 
 | 			nCount = lstrlen(lpszString); | 
 | 		return ::ExtTextOut(m_hDC, x, y, nOptions, lpRect, lpszString, nCount, lpDxWidths); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	SIZE TabbedTextOut(int x, int y, LPCTSTR lpszString, int nCount = -1, int nTabPositions = 0, LPINT lpnTabStopPositions = NULL, int nTabOrigin = 0) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		if(nCount == -1) | 
 | 			nCount = lstrlen(lpszString); | 
 | 		LONG lRes = ::TabbedTextOut(m_hDC, x, y, lpszString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin); | 
 | 		SIZE size = { GET_X_LPARAM(lRes), GET_Y_LPARAM(lRes) }; | 
 | 		return size; | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	int DrawText(LPCTSTR lpstrText, int cchText, LPRECT lpRect, UINT uFormat) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | #ifndef _WIN32_WCE | 
 | 		ATLASSERT((uFormat & DT_MODIFYSTRING) == 0); | 
 | #endif // !_WIN32_WCE | 
 | 		return ::DrawText(m_hDC, lpstrText, cchText, lpRect, uFormat); | 
 | 	} | 
 |  | 
 | 	int DrawText(LPTSTR lpstrText, int cchText, LPRECT lpRect, UINT uFormat) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::DrawText(m_hDC, lpstrText, cchText, lpRect, uFormat); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	int DrawTextEx(LPTSTR lpstrText, int cchText, LPRECT lpRect, UINT uFormat, LPDRAWTEXTPARAMS lpDTParams = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::DrawTextEx(m_hDC, lpstrText, cchText, lpRect, uFormat, lpDTParams); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | #if (_WIN32_WINNT >= 0x0501) | 
 | 	int DrawShadowText(LPCWSTR lpstrText, int cchText, LPRECT lpRect, DWORD dwFlags, COLORREF clrText, COLORREF clrShadow, int xOffset, int yOffset) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		// This function is present only if comctl32.dll version 6 is loaded; | 
 | 		// we use LoadLibrary/GetProcAddress to allow apps compiled with | 
 | 		// _WIN32_WINNT >= 0x0501 to run on older Windows/CommCtrl | 
 | 		int nRet = 0; | 
 | 		HMODULE hCommCtrlDLL = ::LoadLibrary(_T("comctl32.dll")); | 
 | 		ATLASSERT(hCommCtrlDLL != NULL); | 
 | 		if(hCommCtrlDLL != NULL) | 
 | 		{ | 
 | 			typedef int (WINAPI *PFN_DrawShadowText)(HDC hDC, LPCWSTR lpstrText, UINT cchText, LPRECT lpRect, DWORD dwFlags, COLORREF clrText, COLORREF clrShadow, int xOffset, int yOffset); | 
 | 			PFN_DrawShadowText pfnDrawShadowText = (PFN_DrawShadowText)::GetProcAddress(hCommCtrlDLL, "DrawShadowText"); | 
 | 			ATLASSERT(pfnDrawShadowText != NULL);   // this function requires CommCtrl6 | 
 | 			if(pfnDrawShadowText != NULL) | 
 | 				nRet = pfnDrawShadowText(m_hDC, lpstrText, cchText, lpRect, dwFlags, clrText, clrShadow, xOffset, yOffset); | 
 | 			::FreeLibrary(hCommCtrlDLL); | 
 | 		} | 
 | 		return nRet; | 
 | 	} | 
 | #endif // (_WIN32_WINNT >= 0x0501) | 
 |  | 
 | 	BOOL GetTextExtent(LPCTSTR lpszString, int nCount, LPSIZE lpSize) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		if(nCount == -1) | 
 | 			nCount = lstrlen(lpszString); | 
 | 		return ::GetTextExtentPoint32(m_hDC, lpszString, nCount, lpSize); | 
 | 	} | 
 |  | 
 | 	BOOL GetTextExtentExPoint(LPCTSTR lpszString, int cchString, LPSIZE lpSize, int nMaxExtent, LPINT lpnFit = NULL, LPINT alpDx = NULL) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetTextExtentExPoint(m_hDC, lpszString, cchString, nMaxExtent, lpnFit, alpDx, lpSize); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	DWORD GetTabbedTextExtent(LPCTSTR lpszString, int nCount = -1, int nTabPositions = 0, LPINT lpnTabStopPositions = NULL) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		if(nCount == -1) | 
 | 			nCount = lstrlen(lpszString); | 
 | 		return ::GetTabbedTextExtent(m_hDC, lpszString, nCount, nTabPositions, lpnTabStopPositions); | 
 | 	} | 
 |  | 
 | 	BOOL GrayString(HBRUSH hBrush, BOOL (CALLBACK* lpfnOutput)(HDC, LPARAM, int), LPARAM lpData, int nCount, int x, int y, int nWidth, int nHeight) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GrayString(m_hDC, hBrush, (GRAYSTRINGPROC)lpfnOutput, lpData, nCount, x, y, nWidth, nHeight); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) | 
 | 	UINT GetTextAlign() const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetTextAlign(m_hDC); | 
 | 	} | 
 |  | 
 | 	UINT SetTextAlign(UINT nFlags) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetTextAlign(m_hDC, nFlags); | 
 | 	} | 
 | #endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) | 
 |  | 
 | 	int GetTextFace(LPTSTR lpszFacename, int nCount) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetTextFace(m_hDC, nCount, lpszFacename); | 
 | 	} | 
 |  | 
 | 	int GetTextFaceLen() const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetTextFace(m_hDC, 0, NULL); | 
 | 	} | 
 |  | 
 | #ifndef _ATL_NO_COM | 
 | #ifdef _OLEAUTO_H_ | 
 | 	BOOL GetTextFace(BSTR& bstrFace) const | 
 | 	{ | 
 | 		USES_CONVERSION; | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		ATLASSERT(bstrFace == NULL); | 
 |  | 
 | 		int nLen = GetTextFaceLen(); | 
 | 		if(nLen == 0) | 
 | 			return FALSE; | 
 |  | 
 | 		CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff; | 
 | 		LPTSTR lpszText = buff.Allocate(nLen); | 
 | 		if(lpszText == NULL) | 
 | 			return FALSE; | 
 |  | 
 | 		if(!GetTextFace(lpszText, nLen)) | 
 | 			return FALSE; | 
 |  | 
 | 		bstrFace = ::SysAllocString(T2OLE(lpszText)); | 
 | 		return (bstrFace != NULL) ? TRUE : FALSE; | 
 | 	} | 
 | #endif | 
 | #endif // !_ATL_NO_COM | 
 |  | 
 | #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) | 
 | 	int GetTextFace(_CSTRING_NS::CString& strFace) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 |  | 
 | 		int nLen = GetTextFaceLen(); | 
 | 		if(nLen == 0) | 
 | 			return 0; | 
 |  | 
 | 		LPTSTR lpstr = strFace.GetBufferSetLength(nLen); | 
 | 		if(lpstr == NULL) | 
 | 			return 0; | 
 | 		int nRet = GetTextFace(lpstr, nLen); | 
 | 		strFace.ReleaseBuffer(); | 
 | 		return nRet; | 
 | 	} | 
 | #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) | 
 |  | 
 | 	BOOL GetTextMetrics(LPTEXTMETRIC lpMetrics) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetTextMetrics(m_hDC, lpMetrics); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	int SetTextJustification(int nBreakExtra, int nBreakCount) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetTextJustification(m_hDC, nBreakExtra, nBreakCount); | 
 | 	} | 
 |  | 
 | 	int GetTextCharacterExtra() const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetTextCharacterExtra(m_hDC); | 
 | 	} | 
 |  | 
 | 	int SetTextCharacterExtra(int nCharExtra) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetTextCharacterExtra(m_hDC, nCharExtra); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | // Advanced Drawing | 
 | 	BOOL DrawEdge(LPRECT lpRect, UINT nEdge, UINT nFlags) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::DrawEdge(m_hDC, lpRect, nEdge, nFlags); | 
 | 	} | 
 |  | 
 | 	BOOL DrawFrameControl(LPRECT lpRect, UINT nType, UINT nState) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::DrawFrameControl(m_hDC, lpRect, nType, nState); | 
 | 	} | 
 |  | 
 | // Scrolling Functions | 
 | 	BOOL ScrollDC(int dx, int dy, LPCRECT lpRectScroll, LPCRECT lpRectClip, HRGN hRgnUpdate, LPRECT lpRectUpdate) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::ScrollDC(m_hDC, dx, dy, lpRectScroll, lpRectClip, hRgnUpdate, lpRectUpdate); | 
 | 	} | 
 |  | 
 | // Font Functions | 
 | #ifndef _WIN32_WCE | 
 | 	BOOL GetCharWidth(UINT nFirstChar, UINT nLastChar, LPINT lpBuffer) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetCharWidth(m_hDC, nFirstChar, nLastChar, lpBuffer); | 
 | 	} | 
 |  | 
 | 	// GetCharWidth32 is not supported under Win9x | 
 | 	BOOL GetCharWidth32(UINT nFirstChar, UINT nLastChar, LPINT lpBuffer) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetCharWidth32(m_hDC, nFirstChar, nLastChar, lpBuffer); | 
 | 	} | 
 |  | 
 | 	DWORD SetMapperFlags(DWORD dwFlag) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetMapperFlags(m_hDC, dwFlag); | 
 | 	} | 
 |  | 
 | 	BOOL GetAspectRatioFilter(LPSIZE lpSize) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetAspectRatioFilterEx(m_hDC, lpSize); | 
 | 	} | 
 |  | 
 | 	BOOL GetCharABCWidths(UINT nFirstChar, UINT nLastChar, LPABC lpabc) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetCharABCWidths(m_hDC, nFirstChar, nLastChar, lpabc); | 
 | 	} | 
 |  | 
 | 	DWORD GetFontData(DWORD dwTable, DWORD dwOffset, LPVOID lpData, DWORD cbData) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetFontData(m_hDC, dwTable, dwOffset, lpData, cbData); | 
 | 	} | 
 |  | 
 | 	int GetKerningPairs(int nPairs, LPKERNINGPAIR lpkrnpair) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetKerningPairs(m_hDC, nPairs, lpkrnpair); | 
 | 	} | 
 |  | 
 | 	UINT GetOutlineTextMetrics(UINT cbData, LPOUTLINETEXTMETRIC lpotm) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetOutlineTextMetrics(m_hDC, cbData, lpotm); | 
 | 	} | 
 |  | 
 | 	DWORD GetGlyphOutline(UINT nChar, UINT nFormat, LPGLYPHMETRICS lpgm, DWORD cbBuffer, LPVOID lpBuffer, const MAT2* lpmat2) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetGlyphOutline(m_hDC, nChar, nFormat, lpgm, cbBuffer, lpBuffer, lpmat2); | 
 | 	} | 
 |  | 
 | 	BOOL GetCharABCWidths(UINT nFirstChar, UINT nLastChar, LPABCFLOAT lpABCF) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetCharABCWidthsFloat(m_hDC, nFirstChar, nLastChar, lpABCF); | 
 | 	} | 
 |  | 
 | 	BOOL GetCharWidth(UINT nFirstChar, UINT nLastChar, float* lpFloatBuffer) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetCharWidthFloat(m_hDC, nFirstChar, nLastChar, lpFloatBuffer); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | // Printer/Device Escape Functions | 
 | #ifndef _WIN32_WCE | 
 | 	int Escape(int nEscape, int nCount, LPCSTR lpszInData, LPVOID lpOutData) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::Escape(m_hDC, nEscape, nCount, lpszInData, lpOutData); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	int Escape(int nEscape, int nInputSize, LPCSTR lpszInputData, | 
 | 		int nOutputSize, LPSTR lpszOutputData) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::ExtEscape(m_hDC, nEscape, nInputSize, lpszInputData, nOutputSize, lpszOutputData); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	int DrawEscape(int nEscape, int nInputSize, LPCSTR lpszInputData) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::DrawEscape(m_hDC, nEscape, nInputSize, lpszInputData); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	// Escape helpers | 
 | #if !defined(_WIN32_WCE) || ((_WIN32_WCE >= 200) && defined(StartDoc)) | 
 | 	int StartDoc(LPCTSTR lpszDocName)  // old Win3.0 version | 
 | 	{ | 
 | 		DOCINFO di = { 0 }; | 
 | 		di.cbSize = sizeof(DOCINFO); | 
 | 		di.lpszDocName = lpszDocName; | 
 | 		return StartDoc(&di); | 
 | 	} | 
 |  | 
 | 	int StartDoc(LPDOCINFO lpDocInfo) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::StartDoc(m_hDC, lpDocInfo); | 
 | 	} | 
 |  | 
 | 	int StartPage() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::StartPage(m_hDC); | 
 | 	} | 
 |  | 
 | 	int EndPage() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::EndPage(m_hDC); | 
 | 	} | 
 |  | 
 | 	int SetAbortProc(BOOL (CALLBACK* lpfn)(HDC, int)) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetAbortProc(m_hDC, (ABORTPROC)lpfn); | 
 | 	} | 
 |  | 
 | 	int AbortDoc() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::AbortDoc(m_hDC); | 
 | 	} | 
 |  | 
 | 	int EndDoc() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::EndDoc(m_hDC); | 
 | 	} | 
 | #endif // !defined(_WIN32_WCE) || ((_WIN32_WCE >= 200) && defined(StartDoc)) | 
 |  | 
 | // MetaFile Functions | 
 | #ifndef _WIN32_WCE | 
 | 	BOOL PlayMetaFile(HMETAFILE hMF) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		if(::GetDeviceCaps(m_hDC, TECHNOLOGY) == DT_METAFILE) | 
 | 		{ | 
 | 			// playing metafile in metafile, just use core windows API | 
 | 			return ::PlayMetaFile(m_hDC, hMF); | 
 | 		} | 
 |  | 
 | 		// for special playback, lParam == pDC | 
 | 		return ::EnumMetaFile(m_hDC, hMF, EnumMetaFileProc, (LPARAM)this); | 
 | 	} | 
 |  | 
 | 	BOOL PlayMetaFile(HENHMETAFILE hEnhMetaFile, LPCRECT lpBounds) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::PlayEnhMetaFile(m_hDC, hEnhMetaFile, lpBounds); | 
 | 	} | 
 |  | 
 | 	BOOL AddMetaFileComment(UINT nDataSize, const BYTE* pCommentData) // can be used for enhanced metafiles only | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GdiComment(m_hDC, nDataSize, pCommentData); | 
 | 	} | 
 |  | 
 | 	// Special handling for metafile playback | 
 | 	static int CALLBACK EnumMetaFileProc(HDC hDC, HANDLETABLE* pHandleTable, METARECORD* pMetaRec, int nHandles, LPARAM lParam) | 
 | 	{ | 
 | 		CDCHandle* pDC = (CDCHandle*)lParam; | 
 |  | 
 | 		switch (pMetaRec->rdFunction) | 
 | 		{ | 
 | 		case META_SETMAPMODE: | 
 | 			pDC->SetMapMode((int)(short)pMetaRec->rdParm[0]); | 
 | 			break; | 
 | 		case META_SETWINDOWEXT: | 
 | 			pDC->SetWindowExt((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); | 
 | 			break; | 
 | 		case META_SETWINDOWORG: | 
 | 			pDC->SetWindowOrg((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); | 
 | 			break; | 
 | 		case META_SETVIEWPORTEXT: | 
 | 			pDC->SetViewportExt((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); | 
 | 			break; | 
 | 		case META_SETVIEWPORTORG: | 
 | 			pDC->SetViewportOrg((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); | 
 | 			break; | 
 | 		case META_SCALEWINDOWEXT: | 
 | 			pDC->ScaleWindowExt((int)(short)pMetaRec->rdParm[3], (int)(short)pMetaRec->rdParm[2],  | 
 | 				(int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); | 
 | 			break; | 
 | 		case META_SCALEVIEWPORTEXT: | 
 | 			pDC->ScaleViewportExt((int)(short)pMetaRec->rdParm[3], (int)(short)pMetaRec->rdParm[2], | 
 | 				(int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); | 
 | 			break; | 
 | 		case META_OFFSETVIEWPORTORG: | 
 | 			pDC->OffsetViewportOrg((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); | 
 | 			break; | 
 | 		case META_SAVEDC: | 
 | 			pDC->SaveDC(); | 
 | 			break; | 
 | 		case META_RESTOREDC: | 
 | 			pDC->RestoreDC((int)(short)pMetaRec->rdParm[0]); | 
 | 			break; | 
 | 		case META_SETBKCOLOR: | 
 | 			pDC->SetBkColor(*(UNALIGNED COLORREF*)&pMetaRec->rdParm[0]); | 
 | 			break; | 
 | 		case META_SETTEXTCOLOR: | 
 | 			pDC->SetTextColor(*(UNALIGNED COLORREF*)&pMetaRec->rdParm[0]); | 
 | 			break; | 
 |  | 
 | 		// need to watch out for SelectObject(HFONT), for custom font mapping | 
 | 		case META_SELECTOBJECT: | 
 | 			{ | 
 | 				HGDIOBJ hObject = pHandleTable->objectHandle[pMetaRec->rdParm[0]]; | 
 | 				UINT nObjType = ::GetObjectType(hObject); | 
 | 				if(nObjType == 0) | 
 | 				{ | 
 | 					// object type is unknown, determine if it is a font | 
 | 					HFONT hStockFont = (HFONT)::GetStockObject(SYSTEM_FONT); | 
 | 					HFONT hFontOld = (HFONT)::SelectObject(pDC->m_hDC, hStockFont); | 
 | 					HGDIOBJ hObjOld = ::SelectObject(pDC->m_hDC, hObject); | 
 | 					if(hObjOld == hStockFont) | 
 | 					{ | 
 | 						// got the stock object back, so must be selecting a font | 
 | 						pDC->SelectFont((HFONT)hObject); | 
 | 						break;  // don't play the default record | 
 | 					} | 
 | 					else | 
 | 					{ | 
 | 						// didn't get the stock object back, so restore everything | 
 | 						::SelectObject(pDC->m_hDC, hFontOld); | 
 | 						::SelectObject(pDC->m_hDC, hObjOld); | 
 | 					} | 
 | 					// and fall through to PlayMetaFileRecord... | 
 | 				} | 
 | 				else if(nObjType == OBJ_FONT) | 
 | 				{ | 
 | 					// play back as CDCHandle::SelectFont(HFONT) | 
 | 					pDC->SelectFont((HFONT)hObject); | 
 | 					break;  // don't play the default record | 
 | 				} | 
 | 			} | 
 | 			// fall through... | 
 |  | 
 | 		default: | 
 | 			::PlayMetaFileRecord(hDC, pHandleTable, pMetaRec, nHandles); | 
 | 			break; | 
 | 		} | 
 |  | 
 | 		return 1; | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | // Path Functions | 
 | #ifndef _WIN32_WCE | 
 | 	BOOL AbortPath() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::AbortPath(m_hDC); | 
 | 	} | 
 |  | 
 | 	BOOL BeginPath() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::BeginPath(m_hDC); | 
 | 	} | 
 |  | 
 | 	BOOL CloseFigure() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::CloseFigure(m_hDC); | 
 | 	} | 
 |  | 
 | 	BOOL EndPath() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::EndPath(m_hDC); | 
 | 	} | 
 |  | 
 | 	BOOL FillPath() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::FillPath(m_hDC); | 
 | 	} | 
 |  | 
 | 	BOOL FlattenPath() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::FlattenPath(m_hDC); | 
 | 	} | 
 |  | 
 | 	BOOL StrokeAndFillPath() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::StrokeAndFillPath(m_hDC); | 
 | 	} | 
 |  | 
 | 	BOOL StrokePath() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::StrokePath(m_hDC); | 
 | 	} | 
 |  | 
 | 	BOOL WidenPath() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::WidenPath(m_hDC); | 
 | 	} | 
 |  | 
 | 	BOOL GetMiterLimit(PFLOAT pfMiterLimit) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetMiterLimit(m_hDC, pfMiterLimit); | 
 | 	} | 
 |  | 
 | 	BOOL SetMiterLimit(float fMiterLimit) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetMiterLimit(m_hDC, fMiterLimit, NULL); | 
 | 	} | 
 |  | 
 | 	int GetPath(LPPOINT lpPoints, LPBYTE lpTypes, int nCount) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetPath(m_hDC, lpPoints, lpTypes, nCount); | 
 | 	} | 
 |  | 
 | 	BOOL SelectClipPath(int nMode) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SelectClipPath(m_hDC, nMode); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | // Misc Helper Functions | 
 | 	static CBrushHandle PASCAL GetHalftoneBrush() | 
 | 	{ | 
 | 		HBRUSH halftoneBrush = NULL; | 
 | 		WORD grayPattern[8]; | 
 | 		for(int i = 0; i < 8; i++) | 
 | 			grayPattern[i] = (WORD)(0x5555 << (i & 1)); | 
 | 		HBITMAP grayBitmap = CreateBitmap(8, 8, 1, 1, &grayPattern); | 
 | 		if(grayBitmap != NULL) | 
 | 		{ | 
 | 			halftoneBrush = ::CreatePatternBrush(grayBitmap); | 
 | 			DeleteObject(grayBitmap); | 
 | 		} | 
 | 		return CBrushHandle(halftoneBrush); | 
 | 	} | 
 |  | 
 | 	void DrawDragRect(LPCRECT lpRect, SIZE size, LPCRECT lpRectLast, SIZE sizeLast, HBRUSH hBrush = NULL, HBRUSH hBrushLast = NULL) | 
 | 	{ | 
 | 		// first, determine the update region and select it | 
 | 		CRgn rgnOutside; | 
 | 		rgnOutside.CreateRectRgnIndirect(lpRect); | 
 | 		RECT rect = *lpRect; | 
 | 		::InflateRect(&rect, -size.cx, -size.cy); | 
 | 		::IntersectRect(&rect, &rect, lpRect); | 
 | 		CRgn rgnInside; | 
 | 		rgnInside.CreateRectRgnIndirect(&rect); | 
 | 		CRgn rgnNew; | 
 | 		rgnNew.CreateRectRgn(0, 0, 0, 0); | 
 | 		rgnNew.CombineRgn(rgnOutside, rgnInside, RGN_XOR); | 
 |  | 
 | 		HBRUSH hBrushOld = NULL; | 
 | 		CBrush brushHalftone; | 
 | 		if(hBrush == NULL) | 
 | 			brushHalftone = hBrush = CDCHandle::GetHalftoneBrush(); | 
 | 		if(hBrushLast == NULL) | 
 | 			hBrushLast = hBrush; | 
 |  | 
 | 		CRgn rgnLast; | 
 | 		CRgn rgnUpdate; | 
 | 		if(lpRectLast != NULL) | 
 | 		{ | 
 | 			// find difference between new region and old region | 
 | 			rgnLast.CreateRectRgn(0, 0, 0, 0); | 
 | 			rgnOutside.SetRectRgn(lpRectLast->left, lpRectLast->top, lpRectLast->right, lpRectLast->bottom); | 
 | 			rect = *lpRectLast; | 
 | 			::InflateRect(&rect, -sizeLast.cx, -sizeLast.cy); | 
 | 			::IntersectRect(&rect, &rect, lpRectLast); | 
 | 			rgnInside.SetRectRgn(rect.left, rect.top, rect.right, rect.bottom); | 
 | 			rgnLast.CombineRgn(rgnOutside, rgnInside, RGN_XOR); | 
 |  | 
 | 			// only diff them if brushes are the same | 
 | 			if(hBrush == hBrushLast) | 
 | 			{ | 
 | 				rgnUpdate.CreateRectRgn(0, 0, 0, 0); | 
 | 				rgnUpdate.CombineRgn(rgnLast, rgnNew, RGN_XOR); | 
 | 			} | 
 | 		} | 
 | 		if(hBrush != hBrushLast && lpRectLast != NULL) | 
 | 		{ | 
 | 			// brushes are different -- erase old region first | 
 | 			SelectClipRgn(rgnLast); | 
 | 			GetClipBox(&rect); | 
 | 			hBrushOld = SelectBrush(hBrushLast); | 
 | 			PatBlt(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PATINVERT); | 
 | 			SelectBrush(hBrushOld); | 
 | 			hBrushOld = NULL; | 
 | 		} | 
 |  | 
 | 		// draw into the update/new region | 
 | 		SelectClipRgn(rgnUpdate.IsNull() ? rgnNew : rgnUpdate); | 
 | 		GetClipBox(&rect); | 
 | 		hBrushOld = SelectBrush(hBrush); | 
 | 		PatBlt(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PATINVERT); | 
 |  | 
 | 		// cleanup DC | 
 | 		if(hBrushOld != NULL) | 
 | 			SelectBrush(hBrushOld); | 
 | 		SelectClipRgn(NULL); | 
 | 	} | 
 |  | 
 | 	void FillSolidRect(LPCRECT lpRect, COLORREF clr) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 |  | 
 | 		COLORREF clrOld = ::SetBkColor(m_hDC, clr); | 
 | 		ATLASSERT(clrOld != CLR_INVALID); | 
 | 		if(clrOld != CLR_INVALID) | 
 | 		{ | 
 | 			::ExtTextOut(m_hDC, 0, 0, ETO_OPAQUE, lpRect, NULL, 0, NULL); | 
 | 			::SetBkColor(m_hDC, clrOld); | 
 | 		} | 
 | 	} | 
 |  | 
 | 	void FillSolidRect(int x, int y, int cx, int cy, COLORREF clr) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 |  | 
 | 		RECT rect = { x, y, x + cx, y + cy }; | 
 | 		FillSolidRect(&rect, clr); | 
 | 	} | 
 |  | 
 | 	void Draw3dRect(LPCRECT lpRect, COLORREF clrTopLeft, COLORREF clrBottomRight) | 
 | 	{ | 
 | 		Draw3dRect(lpRect->left, lpRect->top, lpRect->right - lpRect->left, | 
 | 			lpRect->bottom - lpRect->top, clrTopLeft, clrBottomRight); | 
 | 	} | 
 |  | 
 | 	void Draw3dRect(int x, int y, int cx, int cy, COLORREF clrTopLeft, COLORREF clrBottomRight) | 
 | 	{ | 
 | 		FillSolidRect(x, y, cx - 1, 1, clrTopLeft); | 
 | 		FillSolidRect(x, y, 1, cy - 1, clrTopLeft); | 
 | 		FillSolidRect(x + cx, y, -1, cy, clrBottomRight); | 
 | 		FillSolidRect(x, y + cy, cx, -1, clrBottomRight); | 
 | 	} | 
 |  | 
 | // DIB support | 
 | #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 410) | 
 | 	int SetDIBitsToDevice(int x, int y, DWORD dwWidth, DWORD dwHeight, int xSrc, int ySrc, UINT uStartScan, UINT cScanLines, CONST VOID* lpvBits, CONST BITMAPINFO* lpbmi, UINT uColorUse) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetDIBitsToDevice(m_hDC, x, y, dwWidth, dwHeight, xSrc, ySrc, uStartScan, cScanLines, lpvBits, lpbmi, uColorUse); | 
 | 	} | 
 | #endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 410) | 
 |  | 
 | #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) | 
 | 	int StretchDIBits(int x, int y, int nWidth, int nHeight, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, CONST VOID* lpvBits, CONST BITMAPINFO* lpbmi, UINT uColorUse, DWORD dwRop) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::StretchDIBits(m_hDC, x, y, nWidth, nHeight, xSrc, ySrc, nSrcWidth, nSrcHeight, lpvBits, lpbmi, uColorUse, dwRop); | 
 | 	} | 
 |  | 
 | 	UINT GetDIBColorTable(UINT uStartIndex, UINT cEntries, RGBQUAD* pColors) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetDIBColorTable(m_hDC, uStartIndex, cEntries, pColors); | 
 | 	} | 
 |  | 
 | 	UINT SetDIBColorTable(UINT uStartIndex, UINT cEntries, CONST RGBQUAD* pColors) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetDIBColorTable(m_hDC, uStartIndex, cEntries, pColors); | 
 | 	} | 
 | #endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) | 
 |  | 
 | // OpenGL support | 
 | #if !defined(_ATL_NO_OPENGL) && !defined(_WIN32_WCE) | 
 | 	int ChoosePixelFormat(CONST PIXELFORMATDESCRIPTOR* ppfd) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::ChoosePixelFormat(m_hDC, ppfd); | 
 | 	} | 
 |  | 
 | 	int DescribePixelFormat(int iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::DescribePixelFormat(m_hDC, iPixelFormat, nBytes, ppfd); | 
 | 	} | 
 |  | 
 | 	int GetPixelFormat() const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetPixelFormat(m_hDC); | 
 | 	} | 
 |  | 
 | 	BOOL SetPixelFormat(int iPixelFormat, CONST PIXELFORMATDESCRIPTOR* ppfd) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetPixelFormat(m_hDC, iPixelFormat, ppfd); | 
 | 	} | 
 |  | 
 | 	BOOL SwapBuffers() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SwapBuffers(m_hDC); | 
 | 	} | 
 |  | 
 | 	HGLRC wglCreateContext() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::wglCreateContext(m_hDC); | 
 | 	} | 
 |  | 
 | 	HGLRC wglCreateLayerContext(int iLayerPlane) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::wglCreateLayerContext(m_hDC, iLayerPlane); | 
 | 	} | 
 |  | 
 | 	BOOL wglMakeCurrent(HGLRC hglrc) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::wglMakeCurrent(m_hDC, hglrc); | 
 | 	} | 
 |  | 
 | 	BOOL wglUseFontBitmaps(DWORD dwFirst, DWORD dwCount, DWORD listBase) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::wglUseFontBitmaps(m_hDC, dwFirst, dwCount, listBase); | 
 | 	} | 
 |  | 
 | 	BOOL wglUseFontOutlines(DWORD dwFirst, DWORD dwCount, DWORD listBase, FLOAT deviation, FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::wglUseFontOutlines(m_hDC, dwFirst, dwCount, listBase, deviation, extrusion, format, lpgmf); | 
 | 	} | 
 |  | 
 | 	BOOL wglDescribeLayerPlane(int iPixelFormat, int iLayerPlane, UINT nBytes, LPLAYERPLANEDESCRIPTOR plpd) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::wglDescribeLayerPlane(m_hDC, iPixelFormat, iLayerPlane, nBytes, plpd); | 
 | 	} | 
 |  | 
 | 	int wglSetLayerPaletteEntries(int iLayerPlane, int iStart, int cEntries, CONST COLORREF* pclr) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::wglSetLayerPaletteEntries(m_hDC, iLayerPlane, iStart, cEntries, pclr); | 
 | 	} | 
 |  | 
 | 	int wglGetLayerPaletteEntries(int iLayerPlane, int iStart, int cEntries, COLORREF* pclr) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::wglGetLayerPaletteEntries(m_hDC, iLayerPlane, iStart, cEntries, pclr); | 
 | 	} | 
 |  | 
 | 	BOOL wglRealizeLayerPalette(int iLayerPlane, BOOL bRealize) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::wglRealizeLayerPalette(m_hDC, iLayerPlane, bRealize); | 
 | 	} | 
 |  | 
 | 	BOOL wglSwapLayerBuffers(UINT uPlanes) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::wglSwapLayerBuffers(m_hDC, uPlanes); | 
 | 	} | 
 | #endif // !defined(_ATL_NO_OPENGL) && !defined(_WIN32_WCE) | 
 |  | 
 | // New for Windows 2000 only | 
 | #if (_WIN32_WINNT >= 0x0500) | 
 | 	COLORREF GetDCPenColor() const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetDCPenColor(m_hDC); | 
 | 	} | 
 |  | 
 | 	COLORREF SetDCPenColor(COLORREF clr) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetDCPenColor(m_hDC, clr); | 
 | 	} | 
 |  | 
 | 	COLORREF GetDCBrushColor() const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetDCBrushColor(m_hDC); | 
 | 	} | 
 |  | 
 | 	COLORREF SetDCBrushColor(COLORREF clr) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::SetDCBrushColor(m_hDC, clr); | 
 | 	} | 
 |  | 
 | #ifndef _WIN32_WCE | 
 | 	DWORD GetFontUnicodeRanges(LPGLYPHSET lpgs) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetFontUnicodeRanges(m_hDC, lpgs); | 
 | 	} | 
 | #endif // !_WIN32_WCE | 
 |  | 
 | 	DWORD GetGlyphIndices(LPCTSTR lpstr, int cch, LPWORD pgi, DWORD dwFlags) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetGlyphIndices(m_hDC, lpstr, cch, pgi, dwFlags); | 
 | 	} | 
 |  | 
 | 	BOOL GetTextExtentPointI(LPWORD pgiIn, int cgi, LPSIZE lpSize) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetTextExtentPointI(m_hDC, pgiIn, cgi, lpSize); | 
 | 	} | 
 |  | 
 | 	BOOL GetTextExtentExPointI(LPWORD pgiIn, int cgi, int nMaxExtent, LPINT lpnFit, LPINT alpDx, LPSIZE lpSize) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetTextExtentExPointI(m_hDC, pgiIn, cgi, nMaxExtent, lpnFit, alpDx, lpSize); | 
 | 	} | 
 |  | 
 | 	BOOL GetCharWidthI(UINT giFirst, UINT cgi, LPWORD pgi, LPINT lpBuffer) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetCharWidthI(m_hDC, giFirst, cgi, pgi, lpBuffer); | 
 | 	} | 
 |  | 
 | 	BOOL GetCharABCWidthsI(UINT giFirst, UINT cgi, LPWORD pgi, LPABC lpabc) const | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::GetCharABCWidthsI(m_hDC, giFirst, cgi, pgi, lpabc); | 
 | 	} | 
 | #endif // (_WIN32_WINNT >= 0x0500) | 
 |  | 
 | // New for Windows 2000 and Windows 98 | 
 | #if (WINVER >= 0x0500) && !defined(_WIN32_WCE) | 
 | 	BOOL ColorCorrectPalette(HPALETTE hPalette, DWORD dwFirstEntry, DWORD dwNumOfEntries) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		return ::ColorCorrectPalette(m_hDC, hPalette, dwFirstEntry, dwNumOfEntries); | 
 | 	} | 
 | #endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE) | 
 | }; | 
 |  | 
 | typedef CDCT<false>   CDCHandle; | 
 | typedef CDCT<true>    CDC; | 
 |  | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 | // CDC Helpers | 
 |  | 
 | class CPaintDC : public CDC | 
 | { | 
 | public: | 
 | // Data members | 
 | 	HWND m_hWnd; | 
 | 	PAINTSTRUCT m_ps; | 
 |  | 
 | // Constructor/destructor | 
 | 	CPaintDC(HWND hWnd) | 
 | 	{ | 
 | 		ATLASSERT(::IsWindow(hWnd)); | 
 | 		m_hWnd = hWnd; | 
 | 		m_hDC = ::BeginPaint(hWnd, &m_ps); | 
 | 	} | 
 |  | 
 | 	~CPaintDC() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		ATLASSERT(::IsWindow(m_hWnd)); | 
 | 		::EndPaint(m_hWnd, &m_ps); | 
 | 		Detach(); | 
 | 	} | 
 | }; | 
 |  | 
 | class CClientDC : public CDC | 
 | { | 
 | public: | 
 | // Data members | 
 | 	HWND m_hWnd; | 
 |  | 
 | // Constructor/destructor | 
 | 	CClientDC(HWND hWnd) | 
 | 	{ | 
 | 		ATLASSERT(hWnd == NULL || ::IsWindow(hWnd)); | 
 | 		m_hWnd = hWnd; | 
 | 		m_hDC = ::GetDC(hWnd); | 
 | 	} | 
 |  | 
 | 	~CClientDC() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		::ReleaseDC(m_hWnd, Detach()); | 
 | 	} | 
 | }; | 
 |  | 
 | class CWindowDC : public CDC | 
 | { | 
 | public: | 
 | // Data members | 
 | 	HWND m_hWnd; | 
 |  | 
 | // Constructor/destructor | 
 | 	CWindowDC(HWND hWnd) | 
 | 	{ | 
 | 		ATLASSERT(hWnd == NULL || ::IsWindow(hWnd)); | 
 | 		m_hWnd = hWnd; | 
 | 		m_hDC = ::GetWindowDC(hWnd); | 
 | 	} | 
 |  | 
 | 	~CWindowDC() | 
 | 	{ | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		::ReleaseDC(m_hWnd, Detach()); | 
 | 	} | 
 | }; | 
 |  | 
 | class CMemoryDC : public CDC | 
 | { | 
 | public: | 
 | // Data members | 
 | 	HDC m_hDCOriginal; | 
 | 	RECT m_rcPaint; | 
 | 	CBitmap m_bmp; | 
 | 	HBITMAP m_hBmpOld; | 
 |  | 
 | // Constructor/destructor | 
 | 	CMemoryDC(HDC hDC, RECT& rcPaint) : m_hDCOriginal(hDC), m_hBmpOld(NULL) | 
 | 	{ | 
 | 		m_rcPaint = rcPaint; | 
 | 		CreateCompatibleDC(m_hDCOriginal); | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 		m_bmp.CreateCompatibleBitmap(m_hDCOriginal, m_rcPaint.right - m_rcPaint.left, m_rcPaint.bottom - m_rcPaint.top); | 
 | 		ATLASSERT(m_bmp.m_hBitmap != NULL); | 
 | 		m_hBmpOld = SelectBitmap(m_bmp); | 
 | 		SetViewportOrg(-m_rcPaint.left, -m_rcPaint.top); | 
 | 	} | 
 |  | 
 | 	~CMemoryDC() | 
 | 	{ | 
 | 		::BitBlt(m_hDCOriginal, m_rcPaint.left, m_rcPaint.top, m_rcPaint.right - m_rcPaint.left, m_rcPaint.bottom - m_rcPaint.top, m_hDC, m_rcPaint.left, m_rcPaint.top, SRCCOPY); | 
 | 		SelectBitmap(m_hBmpOld); | 
 | 	} | 
 | }; | 
 |  | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 | // Enhanced metafile support | 
 |  | 
 | #ifndef _WIN32_WCE | 
 |  | 
 | class CEnhMetaFileInfo | 
 | { | 
 | public: | 
 | // Data members | 
 | 	HENHMETAFILE m_hEMF; | 
 | 	BYTE* m_pBits; | 
 | 	TCHAR* m_pDesc; | 
 | 	ENHMETAHEADER m_header; | 
 | 	PIXELFORMATDESCRIPTOR m_pfd; | 
 |  | 
 | // Constructor/destructor | 
 | 	CEnhMetaFileInfo(HENHMETAFILE hEMF) : m_pBits(NULL), m_pDesc(NULL), m_hEMF(hEMF) | 
 | 	{ } | 
 |  | 
 | 	~CEnhMetaFileInfo() | 
 | 	{ | 
 | 		delete [] m_pBits; | 
 | 		delete [] m_pDesc; | 
 | 	} | 
 |  | 
 | // Operations | 
 | 	BYTE* GetEnhMetaFileBits() | 
 | 	{ | 
 | 		ATLASSERT(m_hEMF != NULL); | 
 | 		UINT nBytes = ::GetEnhMetaFileBits(m_hEMF, 0, NULL); | 
 | 		delete [] m_pBits; | 
 | 		m_pBits = NULL; | 
 | 		ATLTRY(m_pBits = new BYTE[nBytes]); | 
 | 		if (m_pBits != NULL) | 
 | 			::GetEnhMetaFileBits(m_hEMF, nBytes, m_pBits); | 
 | 		return m_pBits; | 
 | 	} | 
 |  | 
 | 	LPTSTR GetEnhMetaFileDescription() | 
 | 	{ | 
 | 		ATLASSERT(m_hEMF != NULL); | 
 | 		UINT nLen = ::GetEnhMetaFileDescription(m_hEMF, 0, NULL); | 
 | 		delete [] m_pDesc; | 
 | 		m_pDesc = NULL; | 
 | 		ATLTRY(m_pDesc = new TCHAR[nLen]); | 
 | 		if (m_pDesc != NULL) | 
 | 			nLen = ::GetEnhMetaFileDescription(m_hEMF, nLen, m_pDesc); | 
 | 		return m_pDesc; | 
 | 	} | 
 |  | 
 | 	ENHMETAHEADER* GetEnhMetaFileHeader() | 
 | 	{ | 
 | 		ATLASSERT(m_hEMF != NULL); | 
 | 		memset(&m_header, 0, sizeof(m_header)); | 
 | 		m_header.iType = EMR_HEADER; | 
 | 		m_header.nSize = sizeof(ENHMETAHEADER); | 
 | 		UINT n = ::GetEnhMetaFileHeader(m_hEMF, sizeof(ENHMETAHEADER), &m_header); | 
 | 		return (n != 0) ? &m_header : NULL; | 
 | 	} | 
 |  | 
 | 	PIXELFORMATDESCRIPTOR* GetEnhMetaFilePixelFormat() | 
 | 	{ | 
 | 		ATLASSERT(m_hEMF != NULL); | 
 | 		memset(&m_pfd, 0, sizeof(m_pfd)); | 
 | 		UINT n = ::GetEnhMetaFilePixelFormat(m_hEMF, sizeof(m_pfd), &m_pfd); | 
 | 		return (n != 0) ? &m_pfd : NULL; | 
 | 	} | 
 | }; | 
 |  | 
 |  | 
 | template <bool t_bManaged> | 
 | class CEnhMetaFileT | 
 | { | 
 | public: | 
 | // Data members | 
 | 	HENHMETAFILE m_hEMF; | 
 |  | 
 | // Constructor/destructor | 
 | 	CEnhMetaFileT(HENHMETAFILE hEMF = NULL) : m_hEMF(hEMF) | 
 | 	{ | 
 | 	} | 
 |  | 
 | 	~CEnhMetaFileT() | 
 | 	{ | 
 | 		if(t_bManaged && m_hEMF != NULL) | 
 | 			DeleteObject(); | 
 | 	} | 
 |  | 
 | // Operations | 
 | 	CEnhMetaFileT<t_bManaged>& operator =(HENHMETAFILE hEMF) | 
 | 	{ | 
 | 		Attach(hEMF); | 
 | 		return *this; | 
 | 	} | 
 |  | 
 | 	void Attach(HENHMETAFILE hEMF) | 
 | 	{ | 
 | 		if(t_bManaged && m_hEMF != NULL && m_hEMF != hEMF) | 
 | 			DeleteObject(); | 
 | 		m_hEMF = hEMF; | 
 | 	} | 
 |  | 
 | 	HENHMETAFILE Detach() | 
 | 	{ | 
 | 		HENHMETAFILE hEMF = m_hEMF; | 
 | 		m_hEMF = NULL; | 
 | 		return hEMF; | 
 | 	} | 
 |  | 
 | 	operator HENHMETAFILE() const { return m_hEMF; } | 
 |  | 
 | 	bool IsNull() const { return (m_hEMF == NULL); } | 
 |  | 
 | 	BOOL DeleteObject() | 
 | 	{ | 
 | 		ATLASSERT(m_hEMF != NULL); | 
 | 		BOOL bRet = ::DeleteEnhMetaFile(m_hEMF); | 
 | 		m_hEMF = NULL; | 
 | 		return bRet; | 
 | 	} | 
 |  | 
 | 	UINT GetEnhMetaFileBits(UINT cbBuffer, LPBYTE lpbBuffer) const | 
 | 	{ | 
 | 		ATLASSERT(m_hEMF != NULL); | 
 | 		return ::GetEnhMetaFileBits(m_hEMF, cbBuffer, lpbBuffer); | 
 | 	} | 
 |  | 
 | 	UINT GetEnhMetaFileDescription(UINT cchBuffer, LPTSTR lpszDescription) const | 
 | 	{ | 
 | 		ATLASSERT(m_hEMF != NULL); | 
 | 		return ::GetEnhMetaFileDescription(m_hEMF, cchBuffer, lpszDescription); | 
 | 	} | 
 |  | 
 | 	UINT GetEnhMetaFileHeader(LPENHMETAHEADER lpemh) const | 
 | 	{ | 
 | 		ATLASSERT(m_hEMF != NULL); | 
 | 		lpemh->iType = EMR_HEADER; | 
 | 		lpemh->nSize = sizeof(ENHMETAHEADER); | 
 | 		return ::GetEnhMetaFileHeader(m_hEMF, sizeof(ENHMETAHEADER), lpemh); | 
 | 	} | 
 |  | 
 | 	UINT GetEnhMetaFilePaletteEntries(UINT cEntries, LPPALETTEENTRY lppe) const | 
 | 	{ | 
 | 		ATLASSERT(m_hEMF != NULL); | 
 | 		return ::GetEnhMetaFilePaletteEntries(m_hEMF, cEntries, lppe); | 
 | 	} | 
 |  | 
 | 	UINT GetEnhMetaFilePixelFormat(DWORD cbBuffer, PIXELFORMATDESCRIPTOR* ppfd) const | 
 | 	{ | 
 | 		ATLASSERT(m_hEMF != NULL); | 
 | 		return ::GetEnhMetaFilePixelFormat(m_hEMF, cbBuffer, ppfd); | 
 | 	} | 
 | }; | 
 |  | 
 | typedef CEnhMetaFileT<false>   CEnhMetaFileHandle; | 
 | typedef CEnhMetaFileT<true>    CEnhMetaFile; | 
 |  | 
 |  | 
 | class CEnhMetaFileDC : public CDC | 
 | { | 
 | public: | 
 | // Constructor/destructor | 
 | 	CEnhMetaFileDC() | 
 | 	{ | 
 | 	} | 
 |  | 
 | 	CEnhMetaFileDC(HDC hdc, LPCRECT lpRect) | 
 | 	{ | 
 | 		Create(hdc, NULL, lpRect, NULL); | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 	} | 
 |  | 
 | 	CEnhMetaFileDC(HDC hdcRef, LPCTSTR lpFilename, LPCRECT lpRect, LPCTSTR lpDescription) | 
 | 	{ | 
 | 		Create(hdcRef, lpFilename, lpRect, lpDescription); | 
 | 		ATLASSERT(m_hDC != NULL); | 
 | 	} | 
 |  | 
 | 	~CEnhMetaFileDC() | 
 | 	{ | 
 | 		HENHMETAFILE hEMF = Close(); | 
 | 		if (hEMF != NULL) | 
 | 			::DeleteEnhMetaFile(hEMF); | 
 | 	} | 
 |  | 
 | // Operations | 
 | 	void Create(HDC hdcRef, LPCTSTR lpFilename, LPCRECT lpRect, LPCTSTR lpDescription) | 
 | 	{ | 
 | 		ATLASSERT(m_hDC == NULL); | 
 | 		m_hDC = ::CreateEnhMetaFile(hdcRef, lpFilename, lpRect, lpDescription); | 
 | 	} | 
 |  | 
 | 	HENHMETAFILE Close() | 
 | 	{ | 
 | 		HENHMETAFILE hEMF = NULL; | 
 | 		if (m_hDC != NULL) | 
 | 		{ | 
 | 			hEMF = ::CloseEnhMetaFile(m_hDC); | 
 | 			m_hDC = NULL; | 
 | 		} | 
 | 		return hEMF; | 
 | 	} | 
 | }; | 
 |  | 
 | #endif // !_WIN32_WCE | 
 |  | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 | // WinCE compatible clipboard CF_DIB format support functions | 
 |  | 
 | #ifndef _WTL_NO_DIB16 | 
 |  | 
 | #define DIBINFO16_BITFIELDS { 31744, 992, 31 } | 
 |  | 
 | // DIBINFO16 - To avoid color table problems in WinCE we only create this type of Dib | 
 | struct DIBINFO16 // a BITMAPINFO with 2 additional color bitfields | 
 | { | 
 |     BITMAPINFOHEADER    bmiHeader; | 
 |     RGBQUAD             bmiColors[3]; | 
 |  | 
 | 	DIBINFO16(SIZE size)  | 
 | 	{ | 
 | 		BITMAPINFOHEADER bmih = { sizeof(BITMAPINFOHEADER), size.cx, size.cy,  | 
 | 		                          1, 16, BI_BITFIELDS, 2 * size.cx * size.cy , 0, 0, 3 }; | 
 | 		DWORD dw[3] = DIBINFO16_BITFIELDS ; | 
 |  | 
 | 		bmiHeader = bmih; | 
 | 		memcpy(bmiColors, dw, 3 * sizeof(DWORD)); | 
 | 	} | 
 | }; | 
 |  | 
 |  | 
 | // AtlxxxDibxxx minimal packed DIB implementation and helpers to copy and paste CF_DIB | 
 |   | 
 | inline bool AtlIsDib16(LPBITMAPINFOHEADER pbmih) | 
 | { | 
 | 	return (pbmih->biBitCount == 16) && (pbmih->biCompression == BI_BITFIELDS); | 
 | } | 
 |  | 
 | inline int AtlGetDibColorTableSize(LPBITMAPINFOHEADER pbmih) | 
 | { | 
 | 	switch (pbmih->biBitCount)  | 
 | 	{ | 
 | 		case  2: | 
 | 		case  4: | 
 | 		case  8: | 
 | 			return pbmih->biClrUsed ? pbmih->biClrUsed : 1 << pbmih->biBitCount; | 
 | 		case 24: | 
 | 			break; | 
 | 		case 16: | 
 | 		case 32: | 
 | 			return pbmih->biCompression == BI_BITFIELDS ? 3 : 0; | 
 | 		default: | 
 | 			ATLASSERT(FALSE);   // should never come here | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | inline int AtlGetDibNumColors(LPBITMAPINFOHEADER pbmih) | 
 | { | 
 | 	switch (pbmih->biBitCount)  | 
 | 	{ | 
 | 		case  2: | 
 | 		case  4: | 
 | 		case  8:  | 
 | 			if (pbmih->biClrUsed) | 
 | 				return pbmih->biClrUsed; | 
 | 			else | 
 | 				break; | 
 | 		case 16:  | 
 | 			if (pbmih->biCompression == BI_BITFIELDS ) | 
 | 				return 1 << 15; | 
 | 			else | 
 | 				break; | 
 | 		case 24: | 
 | 			break; | 
 | 		case 32:  | 
 | 			if (pbmih->biCompression == BI_BITFIELDS ) | 
 | 				return 1 << 24; | 
 | 			else | 
 | 				break; | 
 | 		default: | 
 | 			ATLASSERT(FALSE); | 
 | 	} | 
 |  | 
 | 	return 1 << pbmih->biBitCount; | 
 | } | 
 |  | 
 | inline HBITMAP AtlGetDibBitmap(LPBITMAPINFO pbmi) | 
 | { | 
 | 	HBITMAP hbm = NULL; | 
 | 	CDC dc(NULL); | 
 | 	void * pBits = NULL; | 
 |  | 
 | 	LPBYTE pDibBits = (LPBYTE)pbmi + sizeof(BITMAPINFOHEADER) + AtlGetDibColorTableSize(&pbmi->bmiHeader) * sizeof(RGBQUAD); | 
 | 	if (hbm = CreateDIBSection(dc, pbmi, DIB_RGB_COLORS, &pBits, NULL, NULL))  | 
 | 		memcpy(pBits, pDibBits, pbmi->bmiHeader.biSizeImage); | 
 |  | 
 | 	return hbm; | 
 | } | 
 | 	 | 
 | inline HBITMAP AtlCopyBitmap(HBITMAP hbm , SIZE sizeDst, bool bAsBitmap = false) | 
 | { | 
 | 	CDC hdcSrc = CreateCompatibleDC(NULL); | 
 | 	CDC hdcDst = CreateCompatibleDC(NULL); | 
 |  | 
 | 	CBitmapHandle hbmOld = NULL, hbmOld2 = NULL, bmSrc = hbm; | 
 |  | 
 | 	CBitmap bmNew = NULL; | 
 |  | 
 | 	SIZE sizeSrc = { 0 }; | 
 | 	bmSrc.GetSize(sizeSrc); | 
 |  | 
 | 	hbmOld = hdcSrc.SelectBitmap(bmSrc); | 
 |  | 
 | 	if (bAsBitmap) | 
 | 	{ | 
 | 		bmNew.CreateCompatibleBitmap(hdcSrc, sizeDst.cx, sizeDst.cy); | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		DIBINFO16 dib16(sizeDst); | 
 | 		LPVOID pBits = NULL; | 
 | 		bmNew = CreateDIBSection(hdcDst, (const BITMAPINFO*)&dib16, DIB_RGB_COLORS, &pBits, NULL, NULL); | 
 | 	} | 
 | 	 | 
 | 	ATLASSERT(!bmNew.IsNull()); | 
 |  | 
 | 	hbmOld2 = hdcDst.SelectBitmap(bmNew); | 
 | 	BOOL bOK = FALSE; | 
 |  | 
 | 	if ((sizeDst.cx == sizeSrc.cx) && (sizeDst.cy == sizeSrc.cy)) | 
 | 		bOK = hdcDst.BitBlt(0, 0, sizeDst.cx, sizeDst.cy, hdcSrc, 0, 0, SRCCOPY); | 
 | 	else | 
 | 		bOK = hdcDst.StretchBlt(0, 0, sizeDst.cx, sizeDst.cy, hdcSrc, 0, 0, sizeSrc.cx, sizeSrc.cy, SRCCOPY); | 
 |  | 
 | 	hdcSrc.SelectBitmap(hbmOld); | 
 | 	hdcDst.SelectBitmap(hbmOld2); | 
 |  | 
 | 	if (bOK == FALSE) | 
 | 		bmNew.DeleteObject(); | 
 |  | 
 | 	return bmNew.Detach(); | 
 | } | 
 |  | 
 | inline HLOCAL AtlCreatePackedDib16(HBITMAP hbm, SIZE size) | 
 | { | 
 | 	DIBSECTION ds = { 0 }; | 
 | 	LPBYTE pDib = NULL; | 
 | 	bool bCopied = false; | 
 |  | 
 | 	bool bOK = GetObject(hbm, sizeof(ds), &ds) == sizeof(ds); | 
 | 	if ((bOK == FALSE) || (ds.dsBm.bmBits == NULL) || (AtlIsDib16(&ds.dsBmih) == FALSE) ||  | 
 | 	    (ds.dsBmih.biWidth != size.cx ) || (ds.dsBmih.biHeight != size.cy )) | 
 | 	{ | 
 | 		if ((hbm = AtlCopyBitmap(hbm, size)) != NULL) | 
 | 		{ | 
 | 			bCopied = true; | 
 | 			bOK = GetObject(hbm, sizeof(ds), &ds) == sizeof(ds); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			bOK = FALSE; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	if((bOK == TRUE) && (AtlIsDib16(&ds.dsBmih) == TRUE) && (ds.dsBm.bmBits != NULL)) | 
 | 	{ | 
 | 		pDib = (LPBYTE)LocalAlloc(LMEM_ZEROINIT, sizeof(DIBINFO16) + ds.dsBmih.biSizeImage); | 
 | 		if (pDib != NULL) | 
 | 		{ | 
 | 			memcpy(pDib , &ds.dsBmih, sizeof(DIBINFO16)); | 
 | 			memcpy(pDib + sizeof(DIBINFO16), ds.dsBm.bmBits, ds.dsBmih.biSizeImage); | 
 | 		} | 
 | 	} | 
 |  | 
 | 	if (bCopied == true) | 
 | 		DeleteObject(hbm); | 
 |  | 
 | 	return (HLOCAL)pDib; | 
 | } | 
 |  | 
 | inline bool AtlSetClipboardDib16(HBITMAP hbm, SIZE size, HWND hWnd) | 
 | { | 
 | 	ATLASSERT(::IsWindow(hWnd)); | 
 | 	BOOL bOK = OpenClipboard(hWnd); | 
 | 	if (bOK == TRUE) | 
 | 	{ | 
 | 		if ((bOK = EmptyClipboard()) == TRUE) | 
 | 		{ | 
 | 			HLOCAL hDib = AtlCreatePackedDib16(hbm, size); | 
 | 			if (hDib != NULL) | 
 | 			{ | 
 | 				bOK = SetClipboardData(CF_DIB, hDib) != NULL; | 
 | 				if (bOK == FALSE)   | 
 | 					LocalFree(hDib); | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				bOK = FALSE; | 
 | 			} | 
 | 		} | 
 | 		CloseClipboard(); | 
 | 	} | 
 |  | 
 | 	return bOK == TRUE; | 
 | } | 
 |  | 
 | inline HBITMAP AtlGetClipboardDib(HWND hWnd) | 
 | { | 
 | 	ATLASSERT(::IsWindow(hWnd) == TRUE); | 
 | 	HBITMAP hbm = NULL; | 
 | 	if  (OpenClipboard(hWnd) == TRUE) | 
 | 	{ | 
 | 		LPBITMAPINFO pbmi = (LPBITMAPINFO)GetClipboardData(CF_DIB); | 
 | 		if (pbmi != NULL) | 
 | 			hbm = AtlGetDibBitmap(pbmi); | 
 | 		CloseClipboard(); | 
 | 	} | 
 |  | 
 | 	return hbm; | 
 | } | 
 |  | 
 | #endif // _WTL_NO_DIB16 | 
 |  | 
 | }; // namespace WTL | 
 |  | 
 | #endif // __ATLGDI_H__ |