yum-archive/TaSTT-Whisper

High-performance GPGPU inference of OpenAI's Whisper automatic speech recognition (ASR) model

git clone https://git.yummers.dev/yum-archive/TaSTT-Whisper

KonstantinSource codes8c4603c

master
83.1 KiB3445 linesraw
1// Windows Template Library - WTL version 10.0
2// Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
3//
4// This file is a part of the Windows Template Library.
5// The use and distribution terms for this software are covered by the
6// Microsoft Public License (http://opensource.org/licenses/MS-PL)
7// which can be found in the file MS-PL.txt at the root folder.
8
9#ifndef __ATLGDI_H__
10#define __ATLGDI_H__
11
12#pragma once
13
14#ifndef __ATLAPP_H__
15	#error atlgdi.h requires atlapp.h to be included first
16#endif
17
18
19// protect template members from windowsx.h macros
20#ifdef _INC_WINDOWSX
21  #undef CopyRgn
22  #undef CreateBrush
23  #undef CreatePen
24  #undef SelectBrush
25  #undef SelectPen
26  #undef SelectFont
27  #undef SelectBitmap
28#endif // _INC_WINDOWSX
29
30// required libraries
31#pragma comment(lib, "msimg32.lib")
32#if !defined(_ATL_NO_OPENGL)
33  #pragma comment(lib, "opengl32.lib")
34#endif
35
36
37///////////////////////////////////////////////////////////////////////////////
38// Classes in this file:
39//
40// CPenT<t_bManaged>
41// CBrushT<t_bManaged>
42// CLogFont
43// CFontT<t_bManaged>
44// CBitmapT<t_bManaged>
45// CPaletteT<t_bManaged>
46// CRgnT<t_bManaged>
47// CDCT<t_bManaged>
48// CPaintDC
49// CClientDC
50// CWindowDC
51// CMemoryDC
52// CEnhMetaFileInfo
53// CEnhMetaFileT<t_bManaged>
54// CEnhMetaFileDC
55
56
57namespace WTL
58{
59
60///////////////////////////////////////////////////////////////////////////////
61// Bitmap resource helpers to extract bitmap information for a bitmap resource
62
63inline LPBITMAPINFOHEADER AtlGetBitmapResourceInfo(HMODULE hModule, ATL::_U_STRINGorID image)
64{
65	HRSRC hResource = ::FindResource(hModule, image.m_lpstr, RT_BITMAP);
66	ATLASSERT(hResource != NULL);
67	HGLOBAL hGlobal = ::LoadResource(hModule, hResource);
68	ATLASSERT(hGlobal != NULL);
69	LPBITMAPINFOHEADER pBitmapInfoHeader = (LPBITMAPINFOHEADER)::LockResource(hGlobal);
70	ATLASSERT(pBitmapInfoHeader != NULL);
71	return pBitmapInfoHeader;
72}
73
74inline WORD AtlGetBitmapResourceBitsPerPixel(HMODULE hModule, ATL::_U_STRINGorID image)
75{
76	LPBITMAPINFOHEADER pBitmapInfoHeader = AtlGetBitmapResourceInfo(hModule, image);
77	ATLASSERT(pBitmapInfoHeader != NULL);
78	return pBitmapInfoHeader->biBitCount;
79}
80
81inline WORD AtlGetBitmapResourceBitsPerPixel(ATL::_U_STRINGorID image)
82{
83	return AtlGetBitmapResourceBitsPerPixel(ModuleHelper::GetResourceInstance(), image);
84}
85
86///////////////////////////////////////////////////////////////////////////////
87// 32-bit (alpha channel) bitmap resource helper
88
89// Note: 32-bit (alpha channel) images work only on Windows XP with Common Controls version 6.
90// If you want your app to work on older version of Windows, load non-alpha images if Common
91// Controls version is less than 6.
92
93inline bool AtlIsAlphaBitmapResource(ATL::_U_STRINGorID image)
94{
95	return (AtlGetBitmapResourceBitsPerPixel(image) == 32);
96}
97
98
99///////////////////////////////////////////////////////////////////////////////
100// CPen
101
102template <bool t_bManaged>
103class CPenT
104{
105public:
106// Data members
107	HPEN m_hPen;
108
109// Constructor/destructor/operators
110	CPenT(HPEN hPen = NULL) : m_hPen(hPen)
111	{ }
112
113	~CPenT()
114	{
115		if(t_bManaged && (m_hPen != NULL))
116			DeleteObject();
117	}
118
119	CPenT<t_bManaged>& operator =(HPEN hPen)
120	{
121		Attach(hPen);
122		return *this;
123	}
124
125	void Attach(HPEN hPen)
126	{
127		if(t_bManaged && (m_hPen != NULL) && (m_hPen != hPen))
128			::DeleteObject(m_hPen);
129		m_hPen = hPen;
130	}
131
132	HPEN Detach()
133	{
134		HPEN hPen = m_hPen;
135		m_hPen = NULL;
136		return hPen;
137	}
138
139	operator HPEN() const { return m_hPen; }
140
141	bool IsNull() const { return (m_hPen == NULL); }
142
143// Create methods
144	HPEN CreatePen(int nPenStyle, int nWidth, COLORREF crColor)
145	{
146		ATLASSERT(m_hPen == NULL);
147		m_hPen = ::CreatePen(nPenStyle, nWidth, crColor);
148		return m_hPen;
149	}
150
151	HPEN CreatePen(int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush, int nStyleCount = 0, const DWORD* lpStyle = NULL)
152	{
153		ATLASSERT(m_hPen == NULL);
154		m_hPen = ::ExtCreatePen(nPenStyle, nWidth, pLogBrush, nStyleCount, lpStyle);
155		return m_hPen;
156	}
157
158	HPEN CreatePenIndirect(LPLOGPEN lpLogPen)
159	{
160		ATLASSERT(m_hPen == NULL);
161		m_hPen = ::CreatePenIndirect(lpLogPen);
162		return m_hPen;
163	}
164
165	BOOL DeleteObject()
166	{
167		ATLASSERT(m_hPen != NULL);
168		BOOL bRet = ::DeleteObject(m_hPen);
169		if(bRet)
170			m_hPen = NULL;
171		return bRet;
172	}
173
174// Attributes
175	int GetLogPen(LOGPEN* pLogPen) const
176	{
177		ATLASSERT(m_hPen != NULL);
178		return ::GetObject(m_hPen, sizeof(LOGPEN), pLogPen);
179	}
180
181	bool GetLogPen(LOGPEN& LogPen) const
182	{
183		ATLASSERT(m_hPen != NULL);
184		return (::GetObject(m_hPen, sizeof(LOGPEN), &LogPen) == sizeof(LOGPEN));
185	}
186
187	int GetExtLogPen(EXTLOGPEN* pLogPen, int nSize = sizeof(EXTLOGPEN)) const
188	{
189		ATLASSERT(m_hPen != NULL);
190		return ::GetObject(m_hPen, nSize, pLogPen);
191	}
192
193	bool GetExtLogPen(EXTLOGPEN& ExtLogPen, int nSize = sizeof(EXTLOGPEN)) const
194	{
195		ATLASSERT(m_hPen != NULL);
196		int nRet = ::GetObject(m_hPen, nSize, &ExtLogPen);
197		return ((nRet > 0) && (nRet <= nSize));
198	}
199};
200
201typedef CPenT<false>   CPenHandle;
202typedef CPenT<true>    CPen;
203
204
205///////////////////////////////////////////////////////////////////////////////
206// CBrush
207
208template <bool t_bManaged>
209class CBrushT
210{
211public:
212// Data members
213	HBRUSH m_hBrush;
214
215// Constructor/destructor/operators
216	CBrushT(HBRUSH hBrush = NULL) : m_hBrush(hBrush)
217	{ }
218
219	~CBrushT()
220	{
221		if(t_bManaged && (m_hBrush != NULL))
222			DeleteObject();
223	}
224
225	CBrushT<t_bManaged>& operator =(HBRUSH hBrush)
226	{
227		Attach(hBrush);
228		return *this;
229	}
230
231	void Attach(HBRUSH hBrush)
232	{
233		if(t_bManaged && (m_hBrush != NULL) && (m_hBrush != hBrush))
234			::DeleteObject(m_hBrush);
235		m_hBrush = hBrush;
236	}
237
238	HBRUSH Detach()
239	{
240		HBRUSH hBrush = m_hBrush;
241		m_hBrush = NULL;
242		return hBrush;
243	}
244
245	operator HBRUSH() const { return m_hBrush; }
246
247	bool IsNull() const { return (m_hBrush == NULL); }
248
249// Create methods
250	HBRUSH CreateSolidBrush(COLORREF crColor)
251	{
252		ATLASSERT(m_hBrush == NULL);
253		m_hBrush = ::CreateSolidBrush(crColor);
254		return m_hBrush;
255	}
256
257	HBRUSH CreateHatchBrush(int nIndex, COLORREF crColor)
258	{
259		ATLASSERT(m_hBrush == NULL);
260		m_hBrush = ::CreateHatchBrush(nIndex, crColor);
261		return m_hBrush;
262	}
263
264	HBRUSH CreateBrushIndirect(const LOGBRUSH* lpLogBrush)
265	{
266		ATLASSERT(m_hBrush == NULL);
267		m_hBrush = ::CreateBrushIndirect(lpLogBrush);
268		return m_hBrush;
269	}
270
271	HBRUSH CreatePatternBrush(HBITMAP hBitmap)
272	{
273		ATLASSERT(m_hBrush == NULL);
274		m_hBrush = ::CreatePatternBrush(hBitmap);
275		return m_hBrush;
276	}
277
278	HBRUSH CreateDIBPatternBrush(HGLOBAL hPackedDIB, UINT nUsage)
279	{
280		ATLASSERT(hPackedDIB != NULL);
281		const void* lpPackedDIB = GlobalLock(hPackedDIB);
282		ATLASSERT(lpPackedDIB != NULL);
283		m_hBrush = ::CreateDIBPatternBrushPt(lpPackedDIB, nUsage);
284		GlobalUnlock(hPackedDIB);
285		return m_hBrush;
286	}
287
288	HBRUSH CreateDIBPatternBrush(const void* lpPackedDIB, UINT nUsage)
289	{
290		ATLASSERT(m_hBrush == NULL);
291		m_hBrush = ::CreateDIBPatternBrushPt(lpPackedDIB, nUsage);
292		return m_hBrush;
293	}
294
295	HBRUSH CreateSysColorBrush(int nIndex)
296	{
297		ATLASSERT(m_hBrush == NULL);
298		m_hBrush = ::GetSysColorBrush(nIndex);
299		return m_hBrush;
300	}
301
302	BOOL DeleteObject()
303	{
304		ATLASSERT(m_hBrush != NULL);
305		BOOL bRet = ::DeleteObject(m_hBrush);
306		if(bRet)
307			m_hBrush = NULL;
308		return bRet;
309	}
310
311// Attributes
312	int GetLogBrush(LOGBRUSH* pLogBrush) const
313	{
314		ATLASSERT(m_hBrush != NULL);
315		return ::GetObject(m_hBrush, sizeof(LOGBRUSH), pLogBrush);
316	}
317
318	bool GetLogBrush(LOGBRUSH& LogBrush) const
319	{
320		ATLASSERT(m_hBrush != NULL);
321		return (::GetObject(m_hBrush, sizeof(LOGBRUSH), &LogBrush) == sizeof(LOGBRUSH));
322	}
323};
324
325typedef CBrushT<false>   CBrushHandle;
326typedef CBrushT<true>    CBrush;
327
328
329///////////////////////////////////////////////////////////////////////////////
330// CFont
331
332class CLogFont : public LOGFONT
333{
334public:
335	CLogFont()
336	{
337		memset(this, 0, sizeof(LOGFONT));
338	}
339
340	CLogFont(const LOGFONT& lf)
341	{
342		Copy(&lf);
343	}
344
345	CLogFont(HFONT hFont)
346	{
347		ATLASSERT(::GetObjectType(hFont) == OBJ_FONT);
348		::GetObject(hFont, sizeof(LOGFONT), (LOGFONT*)this);
349	}
350
351	HFONT CreateFontIndirect()
352	{
353		return ::CreateFontIndirect(this);
354	}
355
356	void SetBold()
357	{
358		lfWeight = FW_BOLD;
359	}
360
361	bool IsBold() const
362	{
363		return (lfWeight >= FW_BOLD);
364	}
365
366	void MakeBolder(int iScale = 1)
367	{
368		lfWeight += FW_BOLD * iScale;
369	}
370
371	void MakeLarger(int iScale)
372	{
373		if(lfHeight > 0)
374			lfHeight += iScale;
375		else
376			lfHeight -= iScale;
377	}
378
379	void SetHeight(LONG nPointSize, HDC hDC = NULL)
380	{
381		HDC hDC1 = (hDC != NULL) ? hDC : ::GetDC(NULL);
382		// For MM_TEXT mapping mode
383		lfHeight = -::MulDiv(nPointSize, ::GetDeviceCaps(hDC1, LOGPIXELSY), 72);
384		if(hDC == NULL)
385			::ReleaseDC(NULL, hDC1);
386	}
387
388	LONG GetHeight(HDC hDC = NULL) const
389	{
390		HDC hDC1 = (hDC != NULL) ? hDC : ::GetDC(NULL);
391		// For MM_TEXT mapping mode
392		LONG nPointSize = ::MulDiv(-lfHeight, 72, ::GetDeviceCaps(hDC1, LOGPIXELSY));
393		if(hDC == NULL)
394			::ReleaseDC(NULL, hDC1);
395
396		return nPointSize;
397	}
398
399	LONG GetDeciPointHeight(HDC hDC = NULL) const
400	{
401		HDC hDC1 = (hDC != NULL) ? hDC : ::GetDC(NULL);
402		POINT ptOrg = { 0, 0 };
403		::DPtoLP(hDC1, &ptOrg, 1);
404		POINT pt = { 0, 0 };
405		pt.y = abs(lfHeight) + ptOrg.y;
406		::LPtoDP(hDC1, &pt, 1);
407		LONG nDeciPoint = ::MulDiv(pt.y, 720, ::GetDeviceCaps(hDC1, LOGPIXELSY));   // 72 points/inch, 10 decipoints/point
408		if(hDC == NULL)
409			::ReleaseDC(NULL, hDC1);
410
411		return nDeciPoint;
412	}
413
414	void SetHeightFromDeciPoint(LONG nDeciPtHeight, HDC hDC = NULL)
415	{
416		HDC hDC1 = (hDC != NULL) ? hDC : ::GetDC(NULL);
417		POINT pt = { 0, 0 };
418		pt.y = ::MulDiv(::GetDeviceCaps(hDC1, LOGPIXELSY), nDeciPtHeight, 720);   // 72 points/inch, 10 decipoints/point
419		::DPtoLP(hDC1, &pt, 1);
420		POINT ptOrg = { 0, 0 };
421		::DPtoLP(hDC1, &ptOrg, 1);
422		lfHeight = -abs(pt.y - ptOrg.y);
423		if(hDC == NULL)
424			::ReleaseDC(NULL, hDC1);
425	}
426
427	void SetCaptionFont()
428	{
429		NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() };
430		ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0));
431		Copy(&ncm.lfCaptionFont);
432	}
433
434	void SetMenuFont()
435	{
436		NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() };
437		ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0));
438		Copy(&ncm.lfMenuFont);
439	}
440
441	void SetStatusFont()
442	{
443		NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() };
444		ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0));
445		Copy(&ncm.lfStatusFont);
446	}
447
448	void SetMessageBoxFont()
449	{
450		NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() };
451		ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0));
452		Copy(&ncm.lfMessageFont);
453	}
454
455	void Copy(const LOGFONT* pLogFont)
456	{
457		ATLASSERT(pLogFont != NULL);
458		*(LOGFONT*)this = *pLogFont;
459	}
460
461	CLogFont& operator =(const CLogFont& src)
462	{
463		Copy(&src);
464		return *this;
465	}
466
467	CLogFont& operator =(const LOGFONT& src)
468	{
469		Copy(&src);
470		return *this;
471	}
472
473	CLogFont& operator =(HFONT hFont)
474	{
475		ATLASSERT(::GetObjectType(hFont) == OBJ_FONT);
476		::GetObject(hFont, sizeof(LOGFONT), (LOGFONT*)this);
477		return *this;
478	}
479
480	bool operator ==(const LOGFONT& logfont) const
481	{
482		return((logfont.lfHeight == lfHeight) &&
483		       (logfont.lfWidth == lfWidth) &&
484		       (logfont.lfEscapement == lfEscapement) &&
485		       (logfont.lfOrientation == lfOrientation) &&
486		       (logfont.lfWeight == lfWeight) &&
487		       (logfont.lfItalic == lfItalic) &&
488		       (logfont.lfUnderline == lfUnderline) &&
489		       (logfont.lfStrikeOut == lfStrikeOut) &&
490		       (logfont.lfCharSet == lfCharSet) &&
491		       (logfont.lfOutPrecision == lfOutPrecision) &&
492		       (logfont.lfClipPrecision == lfClipPrecision) &&
493		       (logfont.lfQuality == lfQuality) &&
494		       (logfont.lfPitchAndFamily == lfPitchAndFamily) &&
495		       (lstrcmp(logfont.lfFaceName, lfFaceName) == 0));
496	}
497};
498
499
500template <bool t_bManaged>
501class CFontT
502{
503public:
504// Data members
505	HFONT m_hFont;
506
507// Constructor/destructor/operators
508	CFontT(HFONT hFont = NULL) : m_hFont(hFont)
509	{ }
510
511	~CFontT()
512	{
513		if(t_bManaged && (m_hFont != NULL))
514			DeleteObject();
515	}
516
517	CFontT<t_bManaged>& operator =(HFONT hFont)
518	{
519		Attach(hFont);
520		return *this;
521	}
522
523	void Attach(HFONT hFont)
524	{
525		if(t_bManaged && (m_hFont != NULL) && (m_hFont != hFont))
526			::DeleteObject(m_hFont);
527		m_hFont = hFont;
528	}
529
530	HFONT Detach()
531	{
532		HFONT hFont = m_hFont;
533		m_hFont = NULL;
534		return hFont;
535	}
536
537	operator HFONT() const { return m_hFont; }
538
539	bool IsNull() const { return (m_hFont == NULL); }
540
541// Create methods
542	HFONT CreateFontIndirect(const LOGFONT* lpLogFont)
543	{
544		ATLASSERT(m_hFont == NULL);
545		m_hFont = ::CreateFontIndirect(lpLogFont);
546		return m_hFont;
547	}
548
549	HFONT CreateFontIndirectEx(CONST ENUMLOGFONTEXDV* penumlfex)
550	{
551		ATLASSERT(m_hFont == NULL);
552		m_hFont = ::CreateFontIndirectEx(penumlfex);
553		return m_hFont;
554	}
555
556	HFONT CreateFont(int nHeight, int nWidth, int nEscapement,
557			int nOrientation, int nWeight, BYTE bItalic, BYTE bUnderline,
558			BYTE cStrikeOut, BYTE nCharSet, BYTE nOutPrecision,
559			BYTE nClipPrecision, BYTE nQuality, BYTE nPitchAndFamily,
560			LPCTSTR lpszFacename)
561	{
562		ATLASSERT(m_hFont == NULL);
563		m_hFont = ::CreateFont(nHeight, nWidth, nEscapement,
564			nOrientation, nWeight, bItalic, bUnderline, cStrikeOut,
565			nCharSet, nOutPrecision, nClipPrecision, nQuality,
566			nPitchAndFamily, lpszFacename);
567		return m_hFont;
568	}
569
570	HFONT CreatePointFont(int nPointSize, LPCTSTR lpszFaceName, HDC hDC = NULL, bool bBold = false, bool bItalic = false)
571	{
572		LOGFONT logFont = {};
573		logFont.lfCharSet = DEFAULT_CHARSET;
574		logFont.lfHeight = nPointSize;
575		ATL::Checked::tcsncpy_s(logFont.lfFaceName, _countof(logFont.lfFaceName), lpszFaceName, _TRUNCATE);
576
577		if(bBold)
578			logFont.lfWeight = FW_BOLD;
579		if(bItalic)
580			logFont.lfItalic = (BYTE)TRUE;
581
582		return CreatePointFontIndirect(&logFont, hDC);
583	}
584
585	HFONT CreatePointFontIndirect(const LOGFONT* lpLogFont, HDC hDC = NULL)
586	{
587		HDC hDC1 = (hDC != NULL) ? hDC : ::GetDC(NULL);
588
589		// convert nPointSize to logical units based on hDC
590		LOGFONT logFont = *lpLogFont;
591		POINT pt = { 0, 0 };
592		pt.y = ::MulDiv(::GetDeviceCaps(hDC1, LOGPIXELSY), logFont.lfHeight, 720);   // 72 points/inch, 10 decipoints/point
593		::DPtoLP(hDC1, &pt, 1);
594		POINT ptOrg = { 0, 0 };
595		::DPtoLP(hDC1, &ptOrg, 1);
596		logFont.lfHeight = -abs(pt.y - ptOrg.y);
597
598		if(hDC == NULL)
599			::ReleaseDC(NULL, hDC1);
600
601		return CreateFontIndirect(&logFont);
602	}
603
604	BOOL DeleteObject()
605	{
606		ATLASSERT(m_hFont != NULL);
607		BOOL bRet = ::DeleteObject(m_hFont);
608		if(bRet)
609			m_hFont = NULL;
610		return bRet;
611	}
612
613// Attributes
614	int GetLogFont(LOGFONT* pLogFont) const
615	{
616		ATLASSERT(m_hFont != NULL);
617		return ::GetObject(m_hFont, sizeof(LOGFONT), pLogFont);
618	}
619
620	bool GetLogFont(LOGFONT& LogFont) const
621	{
622		ATLASSERT(m_hFont != NULL);
623		return (::GetObject(m_hFont, sizeof(LOGFONT), &LogFont) == sizeof(LOGFONT));
624	}
625};
626
627typedef CFontT<false>   CFontHandle;
628typedef CFontT<true>    CFont;
629
630
631///////////////////////////////////////////////////////////////////////////////
632// CBitmap
633
634template <bool t_bManaged>
635class CBitmapT
636{
637public:
638// Data members
639	HBITMAP m_hBitmap;
640
641// Constructor/destructor/operators
642	CBitmapT(HBITMAP hBitmap = NULL) : m_hBitmap(hBitmap)
643	{ }
644
645	~CBitmapT()
646	{
647		if(t_bManaged && (m_hBitmap != NULL))
648			DeleteObject();
649	}
650
651	CBitmapT<t_bManaged>& operator =(HBITMAP hBitmap)
652	{
653		Attach(hBitmap);
654		return *this;
655	}
656
657	void Attach(HBITMAP hBitmap)
658	{
659		if(t_bManaged && (m_hBitmap != NULL) && (m_hBitmap != hBitmap))
660			::DeleteObject(m_hBitmap);
661		m_hBitmap = hBitmap;
662	}
663
664	HBITMAP Detach()
665	{
666		HBITMAP hBitmap = m_hBitmap;
667		m_hBitmap = NULL;
668		return hBitmap;
669	}
670
671	operator HBITMAP() const { return m_hBitmap; }
672
673	bool IsNull() const { return (m_hBitmap == NULL); }
674
675// Create and load methods
676	HBITMAP LoadBitmap(ATL::_U_STRINGorID bitmap)
677	{
678		ATLASSERT(m_hBitmap == NULL);
679		m_hBitmap = ::LoadBitmap(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr);
680		return m_hBitmap;
681	}
682
683	HBITMAP LoadOEMBitmap(UINT nIDBitmap) // for OBM_/OCR_/OIC_
684	{
685		ATLASSERT(m_hBitmap == NULL);
686		m_hBitmap = ::LoadBitmap(NULL, MAKEINTRESOURCE(nIDBitmap));
687		return m_hBitmap;
688	}
689
690	HBITMAP LoadMappedBitmap(UINT nIDBitmap, UINT nFlags = 0, LPCOLORMAP lpColorMap = NULL, int nMapSize = 0)
691	{
692		ATLASSERT(m_hBitmap == NULL);
693		m_hBitmap = ::CreateMappedBitmap(ModuleHelper::GetResourceInstance(), nIDBitmap, (WORD)nFlags, lpColorMap, nMapSize);
694		return m_hBitmap;
695	}
696
697	HBITMAP CreateBitmap(int nWidth, int nHeight, UINT nPlanes, UINT nBitsPerPixel, const void* lpBits)
698	{
699		ATLASSERT(m_hBitmap == NULL);
700		m_hBitmap = ::CreateBitmap(nWidth, nHeight, nPlanes, nBitsPerPixel, lpBits);
701		return m_hBitmap;
702	}
703
704	HBITMAP CreateBitmapIndirect(LPBITMAP lpBitmap)
705	{
706		ATLASSERT(m_hBitmap == NULL);
707		m_hBitmap = ::CreateBitmapIndirect(lpBitmap);
708		return m_hBitmap;
709	}
710
711	HBITMAP CreateCompatibleBitmap(HDC hDC, int nWidth, int nHeight)
712	{
713		ATLASSERT(m_hBitmap == NULL);
714		m_hBitmap = ::CreateCompatibleBitmap(hDC, nWidth, nHeight);
715		return m_hBitmap;
716	}
717
718	HBITMAP CreateDiscardableBitmap(HDC hDC, int nWidth, int nHeight)
719	{
720		ATLASSERT(m_hBitmap == NULL);
721		m_hBitmap = ::CreateDiscardableBitmap(hDC, nWidth, nHeight);
722		return m_hBitmap;
723	}
724
725	BOOL DeleteObject()
726	{
727		ATLASSERT(m_hBitmap != NULL);
728		BOOL bRet = ::DeleteObject(m_hBitmap);
729		if(bRet)
730			m_hBitmap = NULL;
731		return bRet;
732	}
733
734// Attributes
735	int GetBitmap(BITMAP* pBitMap) const
736	{
737		ATLASSERT(m_hBitmap != NULL);
738		return ::GetObject(m_hBitmap, sizeof(BITMAP), pBitMap);
739	}
740
741	bool GetBitmap(BITMAP& bm) const
742	{
743		ATLASSERT(m_hBitmap != NULL);
744		return (::GetObject(m_hBitmap, sizeof(BITMAP), &bm) == sizeof(BITMAP));
745	}
746
747	bool GetSize(SIZE& size) const
748	{
749		ATLASSERT(m_hBitmap != NULL);
750		BITMAP bm = {};
751		if(!GetBitmap(&bm))
752			return false;
753		size.cx = bm.bmWidth;
754		size.cy = bm.bmHeight;
755		return true;
756	}
757
758	DWORD GetBitmapBits(DWORD dwCount, LPVOID lpBits) const
759	{
760		ATLASSERT(m_hBitmap != NULL);
761		return ::GetBitmapBits(m_hBitmap, dwCount, lpBits);
762	}
763
764	DWORD SetBitmapBits(DWORD dwCount, const void* lpBits)
765	{
766		ATLASSERT(m_hBitmap != NULL);
767		return ::SetBitmapBits(m_hBitmap, dwCount, lpBits);
768	}
769
770	BOOL GetBitmapDimension(LPSIZE lpSize) const
771	{
772		ATLASSERT(m_hBitmap != NULL);
773		return ::GetBitmapDimensionEx(m_hBitmap, lpSize);
774	}
775
776	BOOL SetBitmapDimension(int nWidth, int nHeight, LPSIZE lpSize = NULL)
777	{
778		ATLASSERT(m_hBitmap != NULL);
779		return ::SetBitmapDimensionEx(m_hBitmap, nWidth, nHeight, lpSize);
780	}
781
782// DIB support
783	HBITMAP CreateDIBitmap(HDC hDC, CONST BITMAPINFOHEADER* lpbmih, DWORD dwInit, CONST VOID* lpbInit, CONST BITMAPINFO* lpbmi, UINT uColorUse)
784	{
785		ATLASSERT(m_hBitmap == NULL);
786		m_hBitmap = ::CreateDIBitmap(hDC, lpbmih, dwInit, lpbInit, lpbmi, uColorUse);
787		return m_hBitmap;
788	}
789
790	HBITMAP CreateDIBSection(HDC hDC, CONST BITMAPINFO* lpbmi, UINT uColorUse, VOID** ppvBits, HANDLE hSection, DWORD dwOffset)
791	{
792		ATLASSERT(m_hBitmap == NULL);
793		m_hBitmap = ::CreateDIBSection(hDC, lpbmi, uColorUse, ppvBits, hSection, dwOffset);
794		return m_hBitmap;
795	}
796
797	int GetDIBits(HDC hDC, UINT uStartScan, UINT cScanLines,  LPVOID lpvBits, LPBITMAPINFO lpbmi, UINT uColorUse) const
798	{
799		ATLASSERT(m_hBitmap != NULL);
800		return ::GetDIBits(hDC, m_hBitmap, uStartScan, cScanLines,  lpvBits, lpbmi, uColorUse);
801	}
802
803	int SetDIBits(HDC hDC, UINT uStartScan, UINT cScanLines, CONST VOID* lpvBits, CONST BITMAPINFO* lpbmi, UINT uColorUse)
804	{
805		ATLASSERT(m_hBitmap != NULL);
806		return ::SetDIBits(hDC, m_hBitmap, uStartScan, cScanLines, lpvBits, lpbmi, uColorUse);
807	}
808};
809
810typedef CBitmapT<false>   CBitmapHandle;
811typedef CBitmapT<true>    CBitmap;
812
813
814///////////////////////////////////////////////////////////////////////////////
815// CPalette
816
817template <bool t_bManaged>
818class CPaletteT
819{
820public:
821// Data members
822	HPALETTE m_hPalette;
823
824// Constructor/destructor/operators
825	CPaletteT(HPALETTE hPalette = NULL) : m_hPalette(hPalette)
826	{ }
827
828	~CPaletteT()
829	{
830		if(t_bManaged && (m_hPalette != NULL))
831			DeleteObject();
832	}
833
834	CPaletteT<t_bManaged>& operator =(HPALETTE hPalette)
835	{
836		Attach(hPalette);
837		return *this;
838	}
839
840	void Attach(HPALETTE hPalette)
841	{
842		if(t_bManaged && (m_hPalette != NULL) && (m_hPalette != hPalette))
843			::DeleteObject(m_hPalette);
844		m_hPalette = hPalette;
845	}
846
847	HPALETTE Detach()
848	{
849		HPALETTE hPalette = m_hPalette;
850		m_hPalette = NULL;
851		return hPalette;
852	}
853
854	operator HPALETTE() const { return m_hPalette; }
855
856	bool IsNull() const { return (m_hPalette == NULL); }
857
858// Create methods
859	HPALETTE CreatePalette(LPLOGPALETTE lpLogPalette)
860	{
861		ATLASSERT(m_hPalette == NULL);
862		m_hPalette = ::CreatePalette(lpLogPalette);
863		return m_hPalette;
864	}
865
866	HPALETTE CreateHalftonePalette(HDC hDC)
867	{
868		ATLASSERT(m_hPalette == NULL);
869		ATLASSERT(hDC != NULL);
870		m_hPalette = ::CreateHalftonePalette(hDC);
871		return m_hPalette;
872	}
873
874	BOOL DeleteObject()
875	{
876		ATLASSERT(m_hPalette != NULL);
877		BOOL bRet = ::DeleteObject(m_hPalette);
878		if(bRet)
879			m_hPalette = NULL;
880		return bRet;
881	}
882
883// Attributes
884	int GetEntryCount() const
885	{
886		ATLASSERT(m_hPalette != NULL);
887		WORD nEntries = 0;
888		::GetObject(m_hPalette, sizeof(WORD), &nEntries);
889		return (int)nEntries;
890	}
891
892	UINT GetPaletteEntries(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors) const
893	{
894		ATLASSERT(m_hPalette != NULL);
895		return ::GetPaletteEntries(m_hPalette, nStartIndex, nNumEntries, lpPaletteColors);
896	}
897
898	UINT SetPaletteEntries(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors)
899	{
900		ATLASSERT(m_hPalette != NULL);
901		return ::SetPaletteEntries(m_hPalette, nStartIndex, nNumEntries, lpPaletteColors);
902	}
903
904// Operations
905	void AnimatePalette(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors)
906	{
907		ATLASSERT(m_hPalette != NULL);
908		::AnimatePalette(m_hPalette, nStartIndex, nNumEntries, lpPaletteColors);
909	}
910
911	BOOL ResizePalette(UINT nNumEntries)
912	{
913		ATLASSERT(m_hPalette != NULL);
914		return ::ResizePalette(m_hPalette, nNumEntries);
915	}
916
917	UINT GetNearestPaletteIndex(COLORREF crColor) const
918	{
919		ATLASSERT(m_hPalette != NULL);
920		return ::GetNearestPaletteIndex(m_hPalette, crColor);
921	}
922};
923
924typedef CPaletteT<false>   CPaletteHandle;
925typedef CPaletteT<true>    CPalette;
926
927
928///////////////////////////////////////////////////////////////////////////////
929// CRgn
930
931template <bool t_bManaged>
932class CRgnT
933{
934public:
935// Data members
936	HRGN m_hRgn;
937
938// Constructor/destructor/operators
939	CRgnT(HRGN hRgn = NULL) : m_hRgn(hRgn)
940	{ }
941
942	~CRgnT()
943	{
944		if(t_bManaged && (m_hRgn != NULL))
945			DeleteObject();
946	}
947
948	CRgnT<t_bManaged>& operator =(HRGN hRgn)
949	{
950		Attach(hRgn);
951		return *this;
952	}
953
954	void Attach(HRGN hRgn)
955	{
956		if(t_bManaged && (m_hRgn != NULL) && (m_hRgn != hRgn))
957			::DeleteObject(m_hRgn);
958		m_hRgn = hRgn;
959	}
960
961	HRGN Detach()
962	{
963		HRGN hRgn = m_hRgn;
964		m_hRgn = NULL;
965		return hRgn;
966	}
967
968	operator HRGN() const { return m_hRgn; }
969
970	bool IsNull() const { return (m_hRgn == NULL); }
971
972// Create methods
973	HRGN CreateRectRgn(int x1, int y1, int x2, int y2)
974	{
975		ATLASSERT(m_hRgn == NULL);
976		m_hRgn = ::CreateRectRgn(x1, y1, x2, y2);
977		return m_hRgn;
978	}
979
980	HRGN CreateRectRgnIndirect(LPCRECT lpRect)
981	{
982		ATLASSERT(m_hRgn == NULL);
983		m_hRgn = ::CreateRectRgnIndirect(lpRect);
984		return m_hRgn;
985	}
986
987	HRGN CreateEllipticRgn(int x1, int y1, int x2, int y2)
988	{
989		ATLASSERT(m_hRgn == NULL);
990		m_hRgn = ::CreateEllipticRgn(x1, y1, x2, y2);
991		return m_hRgn;
992	}
993
994	HRGN CreateEllipticRgnIndirect(LPCRECT lpRect)
995	{
996		ATLASSERT(m_hRgn == NULL);
997		m_hRgn = ::CreateEllipticRgnIndirect(lpRect);
998		return m_hRgn;
999	}
1000
1001	HRGN CreatePolygonRgn(const POINT* lpPoints, int nCount, int nMode)
1002	{
1003		ATLASSERT(m_hRgn == NULL);
1004		m_hRgn = ::CreatePolygonRgn(lpPoints, nCount, nMode);
1005		return m_hRgn;
1006	}
1007
1008	HRGN CreatePolyPolygonRgn(const POINT* lpPoints, const INT* lpPolyCounts, int nCount, int nPolyFillMode)
1009	{
1010		ATLASSERT(m_hRgn == NULL);
1011		m_hRgn = ::CreatePolyPolygonRgn(lpPoints, lpPolyCounts, nCount, nPolyFillMode);
1012		return m_hRgn;
1013	}
1014
1015	HRGN CreateRoundRectRgn(int x1, int y1, int x2, int y2, int x3, int y3)
1016	{
1017		ATLASSERT(m_hRgn == NULL);
1018		m_hRgn = ::CreateRoundRectRgn(x1, y1, x2, y2, x3, y3);
1019		return m_hRgn;
1020	}
1021
1022	HRGN CreateFromPath(HDC hDC)
1023	{
1024		ATLASSERT(m_hRgn == NULL);
1025		ATLASSERT(hDC != NULL);
1026		m_hRgn = ::PathToRegion(hDC);
1027		return m_hRgn;
1028	}
1029
1030	HRGN CreateFromData(const XFORM* lpXForm, int nCount, const RGNDATA* pRgnData)
1031	{
1032		ATLASSERT(m_hRgn == NULL);
1033		m_hRgn = ::ExtCreateRegion(lpXForm, nCount, pRgnData);
1034		return m_hRgn;
1035	}
1036
1037	BOOL DeleteObject()
1038	{
1039		ATLASSERT(m_hRgn != NULL);
1040		BOOL bRet = ::DeleteObject(m_hRgn);
1041		if(bRet)
1042			m_hRgn = NULL;
1043		return bRet;
1044	}
1045
1046// Operations
1047	void SetRectRgn(int x1, int y1, int x2, int y2)
1048	{
1049		ATLASSERT(m_hRgn != NULL);
1050		::SetRectRgn(m_hRgn, x1, y1, x2, y2);
1051	}
1052
1053	void SetRectRgn(LPCRECT lpRect)
1054	{
1055		ATLASSERT(m_hRgn != NULL);
1056		::SetRectRgn(m_hRgn, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
1057	}
1058
1059	int CombineRgn(HRGN hRgnSrc1, HRGN hRgnSrc2, int nCombineMode)
1060	{
1061		ATLASSERT(m_hRgn != NULL);
1062		return ::CombineRgn(m_hRgn, hRgnSrc1, hRgnSrc2, nCombineMode);
1063	}
1064
1065	int CombineRgn(HRGN hRgnSrc, int nCombineMode)
1066	{
1067		ATLASSERT(m_hRgn != NULL);
1068		return ::CombineRgn(m_hRgn, m_hRgn, hRgnSrc, nCombineMode);
1069	}
1070
1071	int CopyRgn(HRGN hRgnSrc)
1072	{
1073		ATLASSERT(m_hRgn != NULL);
1074		return ::CombineRgn(m_hRgn, hRgnSrc, NULL, RGN_COPY);
1075	}
1076
1077	BOOL EqualRgn(HRGN hRgn) const
1078	{
1079		ATLASSERT(m_hRgn != NULL);
1080		return ::EqualRgn(m_hRgn, hRgn);
1081	}
1082
1083	int OffsetRgn(int x, int y)
1084	{
1085		ATLASSERT(m_hRgn != NULL);
1086		return ::OffsetRgn(m_hRgn, x, y);
1087	}
1088
1089	int OffsetRgn(POINT point)
1090	{
1091		ATLASSERT(m_hRgn != NULL);
1092		return ::OffsetRgn(m_hRgn, point.x, point.y);
1093	}
1094
1095	int GetRgnBox(LPRECT lpRect) const
1096	{
1097		ATLASSERT(m_hRgn != NULL);
1098		return ::GetRgnBox(m_hRgn, lpRect);
1099	}
1100
1101	BOOL PtInRegion(int x, int y) const
1102	{
1103		ATLASSERT(m_hRgn != NULL);
1104		return ::PtInRegion(m_hRgn, x, y);
1105	}
1106
1107	BOOL PtInRegion(POINT point) const
1108	{
1109		ATLASSERT(m_hRgn != NULL);
1110		return ::PtInRegion(m_hRgn, point.x, point.y);
1111	}
1112
1113	BOOL RectInRegion(LPCRECT lpRect) const
1114	{
1115		ATLASSERT(m_hRgn != NULL);
1116		return ::RectInRegion(m_hRgn, lpRect);
1117	}
1118
1119	int GetRegionData(LPRGNDATA lpRgnData, int nDataSize) const
1120	{
1121		ATLASSERT(m_hRgn != NULL);
1122		return (int)::GetRegionData(m_hRgn, nDataSize, lpRgnData);
1123	}
1124};
1125
1126typedef CRgnT<false>   CRgnHandle;
1127typedef CRgnT<true>    CRgn;
1128
1129
1130///////////////////////////////////////////////////////////////////////////////
1131// CDC - The device context class
1132
1133template <bool t_bManaged>
1134class CDCT;
1135typedef CDCT<false>   CDCHandle;
1136typedef CDCT<true>    CDC;
1137
1138template <bool t_bManaged>
1139class CDCT
1140{
1141public:
1142// Data members
1143	HDC m_hDC;
1144
1145// Constructor/destructor/operators
1146	CDCT(HDC hDC = NULL) : m_hDC(hDC)
1147	{
1148	}
1149
1150	~CDCT()
1151	{
1152		if(t_bManaged && (m_hDC != NULL))
1153			::DeleteDC(Detach());
1154	}
1155
1156	CDCT<t_bManaged>& operator =(HDC hDC)
1157	{
1158		Attach(hDC);
1159		return *this;
1160	}
1161
1162	void Attach(HDC hDC)
1163	{
1164		if(t_bManaged && (m_hDC != NULL) && (m_hDC != hDC))
1165			::DeleteDC(m_hDC);
1166		m_hDC = hDC;
1167	}
1168
1169	HDC Detach()
1170	{
1171		HDC hDC = m_hDC;
1172		m_hDC = NULL;
1173		return hDC;
1174	}
1175
1176	operator HDC() const { return m_hDC; }
1177
1178	bool IsNull() const { return (m_hDC == NULL); }
1179
1180// Operations
1181	HWND WindowFromDC() const
1182	{
1183		ATLASSERT(m_hDC != NULL);
1184		return ::WindowFromDC(m_hDC);
1185	}
1186
1187	CPenHandle GetCurrentPen() const
1188	{
1189		ATLASSERT(m_hDC != NULL);
1190		return CPenHandle((HPEN)::GetCurrentObject(m_hDC, OBJ_PEN));
1191	}
1192
1193	CBrushHandle GetCurrentBrush() const
1194	{
1195		ATLASSERT(m_hDC != NULL);
1196		return CBrushHandle((HBRUSH)::GetCurrentObject(m_hDC, OBJ_BRUSH));
1197	}
1198
1199	CPaletteHandle GetCurrentPalette() const
1200	{
1201		ATLASSERT(m_hDC != NULL);
1202		return CPaletteHandle((HPALETTE)::GetCurrentObject(m_hDC, OBJ_PAL));
1203	}
1204
1205	CFontHandle GetCurrentFont() const
1206	{
1207		ATLASSERT(m_hDC != NULL);
1208		return CFontHandle((HFONT)::GetCurrentObject(m_hDC, OBJ_FONT));
1209	}
1210
1211	CBitmapHandle GetCurrentBitmap() const
1212	{
1213		ATLASSERT(m_hDC != NULL);
1214		return CBitmapHandle((HBITMAP)::GetCurrentObject(m_hDC, OBJ_BITMAP));
1215	}
1216
1217	HDC CreateDC(LPCTSTR lpszDriverName, LPCTSTR lpszDeviceName, LPCTSTR lpszOutput, const DEVMODE* lpInitData)
1218	{
1219		ATLASSERT(m_hDC == NULL);
1220		m_hDC = ::CreateDC(lpszDriverName, lpszDeviceName, lpszOutput, lpInitData);
1221		return m_hDC;
1222	}
1223
1224	HDC CreateCompatibleDC(HDC hDC = NULL)
1225	{
1226		ATLASSERT(m_hDC == NULL);
1227		m_hDC = ::CreateCompatibleDC(hDC);
1228		return m_hDC;
1229	}
1230
1231	BOOL DeleteDC()
1232	{
1233		if(m_hDC == NULL)
1234			return FALSE;
1235		BOOL bRet = ::DeleteDC(m_hDC);
1236		if(bRet)
1237			m_hDC = NULL;
1238		return bRet;
1239	}
1240
1241// Device-Context Functions
1242	int SaveDC()
1243	{
1244		ATLASSERT(m_hDC != NULL);
1245		return ::SaveDC(m_hDC);
1246	}
1247
1248	BOOL RestoreDC(int nSavedDC)
1249	{
1250		ATLASSERT(m_hDC != NULL);
1251		return ::RestoreDC(m_hDC, nSavedDC);
1252	}
1253
1254	int GetDeviceCaps(int nIndex) const
1255	{
1256		ATLASSERT(m_hDC != NULL);
1257		return ::GetDeviceCaps(m_hDC, nIndex);
1258	}
1259
1260	UINT SetBoundsRect(LPCRECT lpRectBounds, UINT flags)
1261	{
1262		ATLASSERT(m_hDC != NULL);
1263		return ::SetBoundsRect(m_hDC, lpRectBounds, flags);
1264	}
1265
1266	UINT GetBoundsRect(LPRECT lpRectBounds, UINT flags) const
1267	{
1268		ATLASSERT(m_hDC != NULL);
1269		return ::GetBoundsRect(m_hDC, lpRectBounds, flags);
1270	}
1271
1272	BOOL ResetDC(const DEVMODE* lpDevMode)
1273	{
1274		ATLASSERT(m_hDC != NULL);
1275		return ::ResetDC(m_hDC, lpDevMode) != NULL;
1276	}
1277
1278// Drawing-Tool Functions
1279	BOOL GetBrushOrg(LPPOINT lpPoint) const
1280	{
1281		ATLASSERT(m_hDC != NULL);
1282		return ::GetBrushOrgEx(m_hDC, lpPoint);
1283	}
1284
1285	BOOL SetBrushOrg(int x, int y, LPPOINT lpPoint = NULL)
1286	{
1287		ATLASSERT(m_hDC != NULL);
1288		return ::SetBrushOrgEx(m_hDC, x, y, lpPoint);
1289	}
1290
1291	BOOL SetBrushOrg(POINT point, LPPOINT lpPointRet = NULL)
1292	{
1293		ATLASSERT(m_hDC != NULL);
1294		return ::SetBrushOrgEx(m_hDC, point.x, point.y, lpPointRet);
1295	}
1296
1297	int EnumObjects(int nObjectType, int (CALLBACK* lpfn)(LPVOID, LPARAM), LPARAM lpData)
1298	{
1299		ATLASSERT(m_hDC != NULL);
1300#ifdef STRICT
1301		return ::EnumObjects(m_hDC, nObjectType, (GOBJENUMPROC)lpfn, lpData);
1302#else
1303		return ::EnumObjects(m_hDC, nObjectType, (GOBJENUMPROC)lpfn, (LPVOID)lpData);
1304#endif
1305	}
1306
1307// Type-safe selection helpers
1308	HPEN SelectPen(HPEN hPen)
1309	{
1310		ATLASSERT(m_hDC != NULL);
1311		ATLASSERT((hPen == NULL) || (::GetObjectType(hPen) == OBJ_PEN) || (::GetObjectType(hPen) == OBJ_EXTPEN));
1312		return (HPEN)::SelectObject(m_hDC, hPen);
1313	}
1314
1315	HBRUSH SelectBrush(HBRUSH hBrush)
1316	{
1317		ATLASSERT(m_hDC != NULL);
1318		ATLASSERT((hBrush == NULL) || (::GetObjectType(hBrush) == OBJ_BRUSH));
1319		return (HBRUSH)::SelectObject(m_hDC, hBrush);
1320	}
1321
1322	HFONT SelectFont(HFONT hFont)
1323	{
1324		ATLASSERT(m_hDC != NULL);
1325		ATLASSERT((hFont == NULL) || (::GetObjectType(hFont) == OBJ_FONT));
1326		return (HFONT)::SelectObject(m_hDC, hFont);
1327	}
1328
1329	HBITMAP SelectBitmap(HBITMAP hBitmap)
1330	{
1331		ATLASSERT(m_hDC != NULL);
1332		ATLASSERT((hBitmap == NULL) || (::GetObjectType(hBitmap) == OBJ_BITMAP));
1333		return (HBITMAP)::SelectObject(m_hDC, hBitmap);
1334	}
1335
1336	int SelectRgn(HRGN hRgn)       // special return for regions
1337	{
1338		ATLASSERT(m_hDC != NULL);
1339		ATLASSERT((hRgn == NULL) || (::GetObjectType(hRgn) == OBJ_REGION));
1340		return PtrToInt(::SelectObject(m_hDC, hRgn));
1341	}
1342
1343// Type-safe selection helpers for stock objects
1344	HPEN SelectStockPen(int nPen)
1345	{
1346		ATLASSERT(m_hDC != NULL);
1347		ATLASSERT((nPen == WHITE_PEN) || (nPen == BLACK_PEN) || (nPen == NULL_PEN) || (nPen == DC_PEN));
1348		return SelectPen((HPEN)::GetStockObject(nPen));
1349	}
1350
1351	HBRUSH SelectStockBrush(int nBrush)
1352	{
1353		ATLASSERT(((nBrush >= WHITE_BRUSH) && (nBrush <= HOLLOW_BRUSH)) || (nBrush == DC_BRUSH));
1354		return SelectBrush((HBRUSH)::GetStockObject(nBrush));
1355	}
1356
1357	HFONT SelectStockFont(int nFont)
1358	{
1359		ATLASSERT(((nFont >= OEM_FIXED_FONT) && (nFont <= SYSTEM_FIXED_FONT)) || (nFont == DEFAULT_GUI_FONT));
1360		return SelectFont((HFONT)::GetStockObject(nFont));
1361	}
1362
1363	HPALETTE SelectStockPalette(int nPalette, BOOL bForceBackground)
1364	{
1365		ATLASSERT(nPalette == DEFAULT_PALETTE); // the only one supported
1366		return SelectPalette((HPALETTE)::GetStockObject(nPalette), bForceBackground);
1367	}
1368
1369// Color and Color Palette Functions
1370	COLORREF GetNearestColor(COLORREF crColor) const
1371	{
1372		ATLASSERT(m_hDC != NULL);
1373		return ::GetNearestColor(m_hDC, crColor);
1374	}
1375
1376	HPALETTE SelectPalette(HPALETTE hPalette, BOOL bForceBackground)
1377	{
1378		ATLASSERT(m_hDC != NULL);
1379
1380		return ::SelectPalette(m_hDC, hPalette, bForceBackground);
1381	}
1382
1383	UINT RealizePalette()
1384	{
1385		ATLASSERT(m_hDC != NULL);
1386		return ::RealizePalette(m_hDC);
1387	}
1388
1389	void UpdateColors()
1390	{
1391		ATLASSERT(m_hDC != NULL);
1392		::UpdateColors(m_hDC);
1393	}
1394
1395// Drawing-Attribute Functions
1396	COLORREF GetBkColor() const
1397	{
1398		ATLASSERT(m_hDC != NULL);
1399		return ::GetBkColor(m_hDC);
1400	}
1401
1402	int GetBkMode() const
1403	{
1404		ATLASSERT(m_hDC != NULL);
1405		return ::GetBkMode(m_hDC);
1406	}
1407
1408	int GetPolyFillMode() const
1409	{
1410		ATLASSERT(m_hDC != NULL);
1411		return ::GetPolyFillMode(m_hDC);
1412	}
1413
1414	int GetROP2() const
1415	{
1416		ATLASSERT(m_hDC != NULL);
1417		return ::GetROP2(m_hDC);
1418	}
1419
1420	int GetStretchBltMode() const
1421	{
1422		ATLASSERT(m_hDC != NULL);
1423		return ::GetStretchBltMode(m_hDC);
1424	}
1425
1426	COLORREF GetTextColor() const
1427	{
1428		ATLASSERT(m_hDC != NULL);
1429		return ::GetTextColor(m_hDC);
1430	}
1431
1432	COLORREF SetBkColor(COLORREF crColor)
1433	{
1434		ATLASSERT(m_hDC != NULL);
1435		return ::SetBkColor(m_hDC, crColor);
1436	}
1437
1438	int SetBkMode(int nBkMode)
1439	{
1440		ATLASSERT(m_hDC != NULL);
1441		return ::SetBkMode(m_hDC, nBkMode);
1442	}
1443
1444	int SetPolyFillMode(int nPolyFillMode)
1445	{
1446		ATLASSERT(m_hDC != NULL);
1447		return ::SetPolyFillMode(m_hDC, nPolyFillMode);
1448	}
1449
1450	int SetROP2(int nDrawMode)
1451	{
1452		ATLASSERT(m_hDC != NULL);
1453		return ::SetROP2(m_hDC, nDrawMode);
1454	}
1455
1456	int SetStretchBltMode(int nStretchMode)
1457	{
1458		ATLASSERT(m_hDC != NULL);
1459		return ::SetStretchBltMode(m_hDC, nStretchMode);
1460	}
1461
1462	COLORREF SetTextColor(COLORREF crColor)
1463	{
1464		ATLASSERT(m_hDC != NULL);
1465		return ::SetTextColor(m_hDC, crColor);
1466	}
1467
1468	BOOL GetColorAdjustment(LPCOLORADJUSTMENT lpColorAdjust) const
1469	{
1470		ATLASSERT(m_hDC != NULL);
1471		return ::GetColorAdjustment(m_hDC, lpColorAdjust);
1472	}
1473
1474	BOOL SetColorAdjustment(const COLORADJUSTMENT* lpColorAdjust)
1475	{
1476		ATLASSERT(m_hDC != NULL);
1477		return ::SetColorAdjustment(m_hDC, lpColorAdjust);
1478	}
1479
1480// Mapping Functions
1481	int GetMapMode() const
1482	{
1483		ATLASSERT(m_hDC != NULL);
1484		return ::GetMapMode(m_hDC);
1485	}
1486
1487	BOOL GetViewportOrg(LPPOINT lpPoint) const
1488	{
1489		ATLASSERT(m_hDC != NULL);
1490		return ::GetViewportOrgEx(m_hDC, lpPoint);
1491	}
1492
1493	int SetMapMode(int nMapMode)
1494	{
1495		ATLASSERT(m_hDC != NULL);
1496		return ::SetMapMode(m_hDC, nMapMode);
1497	}
1498
1499	// Viewport Origin
1500	BOOL SetViewportOrg(int x, int y, LPPOINT lpPoint = NULL)
1501	{
1502		ATLASSERT(m_hDC != NULL);
1503		return ::SetViewportOrgEx(m_hDC, x, y, lpPoint);
1504	}
1505
1506	BOOL SetViewportOrg(POINT point, LPPOINT lpPointRet = NULL)
1507	{
1508		ATLASSERT(m_hDC != NULL);
1509		return SetViewportOrg(point.x, point.y, lpPointRet);
1510	}
1511
1512	BOOL OffsetViewportOrg(int nWidth, int nHeight, LPPOINT lpPoint = NULL)
1513	{
1514		ATLASSERT(m_hDC != NULL);
1515		return ::OffsetViewportOrgEx(m_hDC, nWidth, nHeight, lpPoint);
1516	}
1517
1518	// Viewport Extent
1519	BOOL GetViewportExt(LPSIZE lpSize) const
1520	{
1521		ATLASSERT(m_hDC != NULL);
1522		return ::GetViewportExtEx(m_hDC, lpSize);
1523	}
1524
1525	BOOL SetViewportExt(int x, int y, LPSIZE lpSize = NULL)
1526	{
1527		ATLASSERT(m_hDC != NULL);
1528		return ::SetViewportExtEx(m_hDC, x, y, lpSize);
1529	}
1530
1531	BOOL SetViewportExt(SIZE size, LPSIZE lpSizeRet = NULL)
1532	{
1533		ATLASSERT(m_hDC != NULL);
1534		return SetViewportExt(size.cx, size.cy, lpSizeRet);
1535	}
1536
1537	BOOL ScaleViewportExt(int xNum, int xDenom, int yNum, int yDenom, LPSIZE lpSize = NULL)
1538	{
1539		ATLASSERT(m_hDC != NULL);
1540		return ::ScaleViewportExtEx(m_hDC, xNum, xDenom, yNum, yDenom, lpSize);
1541	}
1542
1543	// Window Origin
1544	BOOL GetWindowOrg(LPPOINT lpPoint) const
1545	{
1546		ATLASSERT(m_hDC != NULL);
1547		return ::GetWindowOrgEx(m_hDC, lpPoint);
1548	}
1549
1550	BOOL SetWindowOrg(int x, int y, LPPOINT lpPoint = NULL)
1551	{
1552		ATLASSERT(m_hDC != NULL);
1553		return ::SetWindowOrgEx(m_hDC, x, y, lpPoint);
1554	}
1555
1556	BOOL SetWindowOrg(POINT point, LPPOINT lpPointRet = NULL)
1557	{
1558		ATLASSERT(m_hDC != NULL);
1559		return SetWindowOrg(point.x, point.y, lpPointRet);
1560	}
1561
1562	BOOL OffsetWindowOrg(int nWidth, int nHeight, LPPOINT lpPoint = NULL)
1563	{
1564		ATLASSERT(m_hDC != NULL);
1565		return ::OffsetWindowOrgEx(m_hDC, nWidth, nHeight, lpPoint);
1566	}
1567
1568	// Window extent
1569	BOOL GetWindowExt(LPSIZE lpSize) const
1570	{
1571		ATLASSERT(m_hDC != NULL);
1572		return ::GetWindowExtEx(m_hDC, lpSize);
1573	}
1574
1575	BOOL SetWindowExt(int x, int y, LPSIZE lpSize = NULL)
1576	{
1577		ATLASSERT(m_hDC != NULL);
1578		return ::SetWindowExtEx(m_hDC, x, y, lpSize);
1579	}
1580
1581	BOOL SetWindowExt(SIZE size, LPSIZE lpSizeRet = NULL)
1582	{
1583		ATLASSERT(m_hDC != NULL);
1584		return SetWindowExt(size.cx, size.cy, lpSizeRet);
1585	}
1586
1587	BOOL ScaleWindowExt(int xNum, int xDenom, int yNum, int yDenom, LPSIZE lpSize = NULL)
1588	{
1589		ATLASSERT(m_hDC != NULL);
1590		return ::ScaleWindowExtEx(m_hDC, xNum, xDenom, yNum, yDenom, lpSize);
1591	}
1592
1593// Coordinate Functions
1594	BOOL DPtoLP(LPPOINT lpPoints, int nCount = 1) const
1595	{
1596		ATLASSERT(m_hDC != NULL);
1597		return ::DPtoLP(m_hDC, lpPoints, nCount);
1598	}
1599
1600	BOOL DPtoLP(LPRECT lpRect) const
1601	{
1602		ATLASSERT(m_hDC != NULL);
1603		return ::DPtoLP(m_hDC, (LPPOINT)lpRect, 2);
1604	}
1605
1606	BOOL DPtoLP(LPSIZE lpSize) const
1607	{
1608		SIZE sizeWinExt = {};
1609		if(!GetWindowExt(&sizeWinExt))
1610			return FALSE;
1611		SIZE sizeVpExt = {};
1612		if(!GetViewportExt(&sizeVpExt))
1613			return FALSE;
1614		lpSize->cx = ::MulDiv(lpSize->cx, abs(sizeWinExt.cx), abs(sizeVpExt.cx));
1615		lpSize->cy = ::MulDiv(lpSize->cy, abs(sizeWinExt.cy), abs(sizeVpExt.cy));
1616		return TRUE;
1617	}
1618
1619	BOOL LPtoDP(LPPOINT lpPoints, int nCount = 1) const
1620	{
1621		ATLASSERT(m_hDC != NULL);
1622		return ::LPtoDP(m_hDC, lpPoints, nCount);
1623	}
1624
1625	BOOL LPtoDP(LPRECT lpRect) const
1626	{
1627		ATLASSERT(m_hDC != NULL);
1628		return ::LPtoDP(m_hDC, (LPPOINT)lpRect, 2);
1629	}
1630
1631	BOOL LPtoDP(LPSIZE lpSize) const
1632	{
1633		SIZE sizeWinExt = {};
1634		if(!GetWindowExt(&sizeWinExt))
1635			return FALSE;
1636		SIZE sizeVpExt = {};
1637		if(!GetViewportExt(&sizeVpExt))
1638			return FALSE;
1639		lpSize->cx = ::MulDiv(lpSize->cx, abs(sizeVpExt.cx), abs(sizeWinExt.cx));
1640		lpSize->cy = ::MulDiv(lpSize->cy, abs(sizeVpExt.cy), abs(sizeWinExt.cy));
1641		return TRUE;
1642	}
1643
1644// Special Coordinate Functions (useful for dealing with metafiles and OLE)
1645	#define HIMETRIC_INCH   2540    // HIMETRIC units per inch
1646
1647	void DPtoHIMETRIC(LPSIZE lpSize)
1648	{
1649		ATLASSERT(m_hDC != NULL);
1650		int nMapMode = GetMapMode();
1651		if((nMapMode < MM_ISOTROPIC) && (nMapMode != MM_TEXT))
1652		{
1653			// when using a constrained map mode, map against physical inch
1654			SetMapMode(MM_HIMETRIC);
1655			DPtoLP(lpSize);
1656			SetMapMode(nMapMode);
1657		}
1658		else
1659		{
1660			// map against logical inch for non-constrained mapping modes
1661			int cxPerInch = GetDeviceCaps(LOGPIXELSX);
1662			int cyPerInch = GetDeviceCaps(LOGPIXELSY);
1663			ATLASSERT((cxPerInch != 0) && (cyPerInch != 0));
1664			lpSize->cx = ::MulDiv(lpSize->cx, HIMETRIC_INCH, cxPerInch);
1665			lpSize->cy = ::MulDiv(lpSize->cy, HIMETRIC_INCH, cyPerInch);
1666		}
1667	}
1668
1669	void HIMETRICtoDP(LPSIZE lpSize)
1670	{
1671		ATLASSERT(m_hDC != NULL);
1672		int nMapMode = GetMapMode();
1673		if((nMapMode < MM_ISOTROPIC) && (nMapMode != MM_TEXT))
1674		{
1675			// when using a constrained map mode, map against physical inch
1676			SetMapMode(MM_HIMETRIC);
1677			LPtoDP(lpSize);
1678			SetMapMode(nMapMode);
1679		}
1680		else
1681		{
1682			// map against logical inch for non-constrained mapping modes
1683			int cxPerInch = GetDeviceCaps(LOGPIXELSX);
1684			int cyPerInch = GetDeviceCaps(LOGPIXELSY);
1685			ATLASSERT((cxPerInch != 0) && (cyPerInch != 0));
1686			lpSize->cx = ::MulDiv(lpSize->cx, cxPerInch, HIMETRIC_INCH);
1687			lpSize->cy = ::MulDiv(lpSize->cy, cyPerInch, HIMETRIC_INCH);
1688		}
1689	}
1690
1691	void LPtoHIMETRIC(LPSIZE lpSize)
1692	{
1693		LPtoDP(lpSize);
1694		DPtoHIMETRIC(lpSize);
1695	}
1696
1697	void HIMETRICtoLP(LPSIZE lpSize)
1698	{
1699		HIMETRICtoDP(lpSize);
1700		DPtoLP(lpSize);
1701	}
1702
1703// Region Functions
1704	BOOL FillRgn(HRGN hRgn, HBRUSH hBrush)
1705	{
1706		ATLASSERT(m_hDC != NULL);
1707		return ::FillRgn(m_hDC, hRgn, hBrush);
1708	}
1709
1710	BOOL FrameRgn(HRGN hRgn, HBRUSH hBrush, int nWidth, int nHeight)
1711	{
1712		ATLASSERT(m_hDC != NULL);
1713		return ::FrameRgn(m_hDC, hRgn, hBrush, nWidth, nHeight);
1714	}
1715
1716	BOOL InvertRgn(HRGN hRgn)
1717	{
1718		ATLASSERT(m_hDC != NULL);
1719		return ::InvertRgn(m_hDC, hRgn);
1720	}
1721
1722	BOOL PaintRgn(HRGN hRgn)
1723	{
1724		ATLASSERT(m_hDC != NULL);
1725		return ::PaintRgn(m_hDC, hRgn);
1726	}
1727
1728// Clipping Functions
1729	int GetClipBox(LPRECT lpRect) const
1730	{
1731		ATLASSERT(m_hDC != NULL);
1732		return ::GetClipBox(m_hDC, lpRect);
1733	}
1734
1735	int GetClipRgn(CRgn& region) const
1736	{
1737		ATLASSERT(m_hDC != NULL);
1738		if(region.IsNull())
1739			region.CreateRectRgn(0, 0, 0, 0);
1740
1741		int nRet = ::GetClipRgn(m_hDC, region);
1742		if(nRet != 1)
1743			region.DeleteObject();
1744
1745		return nRet;
1746	}
1747
1748	BOOL PtVisible(int x, int y) const
1749	{
1750		ATLASSERT(m_hDC != NULL);
1751		return ::PtVisible(m_hDC, x, y);
1752	}
1753
1754	BOOL PtVisible(POINT point) const
1755	{
1756		ATLASSERT(m_hDC != NULL);
1757		return ::PtVisible(m_hDC, point.x, point.y);
1758	}
1759
1760	BOOL RectVisible(LPCRECT lpRect) const
1761	{
1762		ATLASSERT(m_hDC != NULL);
1763		return ::RectVisible(m_hDC, lpRect);
1764	}
1765
1766	int SelectClipRgn(HRGN hRgn)
1767	{
1768		ATLASSERT(m_hDC != NULL);
1769		return ::SelectClipRgn(m_hDC, (HRGN)hRgn);
1770	}
1771
1772	int ExcludeClipRect(int x1, int y1, int x2, int y2)
1773	{
1774		ATLASSERT(m_hDC != NULL);
1775		return ::ExcludeClipRect(m_hDC, x1, y1, x2, y2);
1776	}
1777
1778	int ExcludeClipRect(LPCRECT lpRect)
1779	{
1780		ATLASSERT(m_hDC != NULL);
1781		return ::ExcludeClipRect(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
1782	}
1783
1784	int ExcludeUpdateRgn(HWND hWnd)
1785	{
1786		ATLASSERT(m_hDC != NULL);
1787		return ::ExcludeUpdateRgn(m_hDC, hWnd);
1788	}
1789
1790	int IntersectClipRect(int x1, int y1, int x2, int y2)
1791	{
1792		ATLASSERT(m_hDC != NULL);
1793		return ::IntersectClipRect(m_hDC, x1, y1, x2, y2);
1794	}
1795
1796	int IntersectClipRect(LPCRECT lpRect)
1797	{
1798		ATLASSERT(m_hDC != NULL);
1799		return ::IntersectClipRect(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
1800	}
1801
1802	int OffsetClipRgn(int x, int y)
1803	{
1804		ATLASSERT(m_hDC != NULL);
1805		return ::OffsetClipRgn(m_hDC, x, y);
1806	}
1807
1808	int OffsetClipRgn(SIZE size)
1809	{
1810		ATLASSERT(m_hDC != NULL);
1811		return ::OffsetClipRgn(m_hDC, size.cx, size.cy);
1812	}
1813
1814	int SelectClipRgn(HRGN hRgn, int nMode)
1815	{
1816		ATLASSERT(m_hDC != NULL);
1817		return ::ExtSelectClipRgn(m_hDC, hRgn, nMode);
1818	}
1819
1820// Line-Output Functions
1821	BOOL GetCurrentPosition(LPPOINT lpPoint) const
1822	{
1823		ATLASSERT(m_hDC != NULL);
1824		return ::GetCurrentPositionEx(m_hDC, lpPoint);
1825	}
1826
1827	BOOL MoveTo(int x, int y, LPPOINT lpPoint = NULL)
1828	{
1829		ATLASSERT(m_hDC != NULL);
1830		return ::MoveToEx(m_hDC, x, y, lpPoint);
1831	}
1832
1833	BOOL MoveTo(POINT point, LPPOINT lpPointRet = NULL)
1834	{
1835		ATLASSERT(m_hDC != NULL);
1836		return MoveTo(point.x, point.y, lpPointRet);
1837	}
1838
1839	BOOL LineTo(int x, int y)
1840	{
1841		ATLASSERT(m_hDC != NULL);
1842		return ::LineTo(m_hDC, x, y);
1843	}
1844
1845	BOOL LineTo(POINT point)
1846	{
1847		ATLASSERT(m_hDC != NULL);
1848		return LineTo(point.x, point.y);
1849	}
1850
1851	BOOL Arc(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
1852	{
1853		ATLASSERT(m_hDC != NULL);
1854		return ::Arc(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4);
1855	}
1856
1857	BOOL Arc(LPCRECT lpRect, POINT ptStart, POINT ptEnd)
1858	{
1859		ATLASSERT(m_hDC != NULL);
1860		return ::Arc(m_hDC, lpRect->left, lpRect->top,
1861			lpRect->right, lpRect->bottom, ptStart.x, ptStart.y,
1862			ptEnd.x, ptEnd.y);
1863	}
1864
1865	BOOL Polyline(const POINT* lpPoints, int nCount)
1866	{
1867		ATLASSERT(m_hDC != NULL);
1868		return ::Polyline(m_hDC, lpPoints, nCount);
1869	}
1870
1871	BOOL AngleArc(int x, int y, int nRadius, float fStartAngle, float fSweepAngle)
1872	{
1873		ATLASSERT(m_hDC != NULL);
1874		return ::AngleArc(m_hDC, x, y, nRadius, fStartAngle, fSweepAngle);
1875	}
1876
1877	BOOL ArcTo(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
1878	{
1879		ATLASSERT(m_hDC != NULL);
1880		return ::ArcTo(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4);
1881	}
1882
1883	BOOL ArcTo(LPCRECT lpRect, POINT ptStart, POINT ptEnd)
1884	{
1885		ATLASSERT(m_hDC != NULL);
1886		return ArcTo(lpRect->left, lpRect->top, lpRect->right,
1887		lpRect->bottom, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y);
1888	}
1889
1890	int GetArcDirection() const
1891	{
1892		ATLASSERT(m_hDC != NULL);
1893		return ::GetArcDirection(m_hDC);
1894	}
1895
1896	int SetArcDirection(int nArcDirection)
1897	{
1898		ATLASSERT(m_hDC != NULL);
1899		return ::SetArcDirection(m_hDC, nArcDirection);
1900	}
1901
1902	BOOL PolyDraw(const POINT* lpPoints, const BYTE* lpTypes, int nCount)
1903	{
1904		ATLASSERT(m_hDC != NULL);
1905		return ::PolyDraw(m_hDC, lpPoints, lpTypes, nCount);
1906	}
1907
1908	BOOL PolylineTo(const POINT* lpPoints, int nCount)
1909	{
1910		ATLASSERT(m_hDC != NULL);
1911		return ::PolylineTo(m_hDC, lpPoints, nCount);
1912	}
1913
1914	BOOL PolyPolyline(const POINT* lpPoints,
1915		const DWORD* lpPolyPoints, int nCount)
1916	{
1917		ATLASSERT(m_hDC != NULL);
1918		return ::PolyPolyline(m_hDC, lpPoints, lpPolyPoints, nCount);
1919	}
1920
1921	BOOL PolyBezier(const POINT* lpPoints, int nCount)
1922	{
1923		ATLASSERT(m_hDC != NULL);
1924		return ::PolyBezier(m_hDC, lpPoints, nCount);
1925	}
1926
1927	BOOL PolyBezierTo(const POINT* lpPoints, int nCount)
1928	{
1929		ATLASSERT(m_hDC != NULL);
1930		return ::PolyBezierTo(m_hDC, lpPoints, nCount);
1931	}
1932
1933// Simple Drawing Functions
1934	BOOL FillRect(LPCRECT lpRect, HBRUSH hBrush)
1935	{
1936		ATLASSERT(m_hDC != NULL);
1937		return ::FillRect(m_hDC, lpRect, hBrush);
1938	}
1939
1940	BOOL FillRect(LPCRECT lpRect, int nColorIndex)
1941	{
1942		ATLASSERT(m_hDC != NULL);
1943		return ::FillRect(m_hDC, lpRect, (HBRUSH)LongToPtr(nColorIndex + 1));
1944	}
1945
1946	BOOL FrameRect(LPCRECT lpRect, HBRUSH hBrush)
1947	{
1948		ATLASSERT(m_hDC != NULL);
1949		return ::FrameRect(m_hDC, lpRect, hBrush);
1950	}
1951
1952	BOOL InvertRect(LPCRECT lpRect)
1953	{
1954		ATLASSERT(m_hDC != NULL);
1955		return ::InvertRect(m_hDC, lpRect);
1956	}
1957
1958	BOOL DrawIcon(int x, int y, HICON hIcon)
1959	{
1960		ATLASSERT(m_hDC != NULL);
1961		return ::DrawIcon(m_hDC, x, y, hIcon);
1962	}
1963
1964	BOOL DrawIcon(POINT point, HICON hIcon)
1965	{
1966		ATLASSERT(m_hDC != NULL);
1967		return ::DrawIcon(m_hDC, point.x, point.y, hIcon);
1968	}
1969
1970	BOOL DrawIconEx(int x, int y, HICON hIcon, int cxWidth, int cyWidth, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL)
1971	{
1972		ATLASSERT(m_hDC != NULL);
1973		return ::DrawIconEx(m_hDC, x, y, hIcon, cxWidth, cyWidth, uStepIfAniCur, hbrFlickerFreeDraw, uFlags);
1974	}
1975
1976	BOOL DrawIconEx(POINT point, HICON hIcon, SIZE size, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL)
1977	{
1978		ATLASSERT(m_hDC != NULL);
1979		return ::DrawIconEx(m_hDC, point.x, point.y, hIcon, size.cx, size.cy, uStepIfAniCur, hbrFlickerFreeDraw, uFlags);
1980	}
1981
1982	BOOL DrawState(POINT pt, SIZE size, HBITMAP hBitmap, UINT nFlags, HBRUSH hBrush = NULL)
1983	{
1984		ATLASSERT(m_hDC != NULL);
1985		return ::DrawState(m_hDC, hBrush, NULL, (LPARAM)hBitmap, 0, pt.x, pt.y, size.cx, size.cy, nFlags | DST_BITMAP);
1986	}
1987
1988	BOOL DrawState(POINT pt, SIZE size, HICON hIcon, UINT nFlags, HBRUSH hBrush = NULL)
1989	{
1990		ATLASSERT(m_hDC != NULL);
1991		return ::DrawState(m_hDC, hBrush, NULL, (LPARAM)hIcon, 0, pt.x, pt.y, size.cx, size.cy, nFlags | DST_ICON);
1992	}
1993
1994	BOOL DrawState(POINT pt, SIZE size, LPCTSTR lpszText, UINT nFlags, BOOL bPrefixText = TRUE, int nTextLen = 0, HBRUSH hBrush = NULL)
1995	{
1996		ATLASSERT(m_hDC != NULL);
1997		return ::DrawState(m_hDC, hBrush, NULL, (LPARAM)lpszText, (WPARAM)nTextLen, pt.x, pt.y, size.cx, size.cy, nFlags | (bPrefixText ? DST_PREFIXTEXT : DST_TEXT));
1998	}
1999
2000	BOOL DrawState(POINT pt, SIZE size, DRAWSTATEPROC lpDrawProc, LPARAM lData, UINT nFlags, HBRUSH hBrush = NULL)
2001	{
2002		ATLASSERT(m_hDC != NULL);
2003		return ::DrawState(m_hDC, hBrush, lpDrawProc, lData, 0, pt.x, pt.y, size.cx, size.cy, nFlags | DST_COMPLEX);
2004	}
2005
2006// Ellipse and Polygon Functions
2007	BOOL Chord(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
2008	{
2009		ATLASSERT(m_hDC != NULL);
2010		return ::Chord(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4);
2011	}
2012
2013	BOOL Chord(LPCRECT lpRect, POINT ptStart, POINT ptEnd)
2014	{
2015		ATLASSERT(m_hDC != NULL);
2016		return ::Chord(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y);
2017	}
2018
2019	void DrawFocusRect(LPCRECT lpRect)
2020	{
2021		ATLASSERT(m_hDC != NULL);
2022		::DrawFocusRect(m_hDC, lpRect);
2023	}
2024
2025	BOOL Ellipse(int x1, int y1, int x2, int y2)
2026	{
2027		ATLASSERT(m_hDC != NULL);
2028		return ::Ellipse(m_hDC, x1, y1, x2, y2);
2029	}
2030
2031	BOOL Ellipse(LPCRECT lpRect)
2032	{
2033		ATLASSERT(m_hDC != NULL);
2034		return ::Ellipse(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
2035	}
2036
2037	BOOL Pie(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
2038	{
2039		ATLASSERT(m_hDC != NULL);
2040		return ::Pie(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4);
2041	}
2042
2043	BOOL Pie(LPCRECT lpRect, POINT ptStart, POINT ptEnd)
2044	{
2045		ATLASSERT(m_hDC != NULL);
2046		return ::Pie(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y);
2047	}
2048
2049	BOOL Polygon(const POINT* lpPoints, int nCount)
2050	{
2051		ATLASSERT(m_hDC != NULL);
2052		return ::Polygon(m_hDC, lpPoints, nCount);
2053	}
2054
2055	BOOL PolyPolygon(const POINT* lpPoints, const INT* lpPolyCounts, int nCount)
2056	{
2057		ATLASSERT(m_hDC != NULL);
2058		return ::PolyPolygon(m_hDC, lpPoints, lpPolyCounts, nCount);
2059	}
2060
2061	BOOL Rectangle(int x1, int y1, int x2, int y2)
2062	{
2063		ATLASSERT(m_hDC != NULL);
2064		return ::Rectangle(m_hDC, x1, y1, x2, y2);
2065	}
2066
2067	BOOL Rectangle(LPCRECT lpRect)
2068	{
2069		ATLASSERT(m_hDC != NULL);
2070		return ::Rectangle(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
2071	}
2072
2073	BOOL RoundRect(int x1, int y1, int x2, int y2, int x3, int y3)
2074	{
2075		ATLASSERT(m_hDC != NULL);
2076		return ::RoundRect(m_hDC, x1, y1, x2, y2, x3, y3);
2077	}
2078
2079	BOOL RoundRect(LPCRECT lpRect, POINT point)
2080	{
2081		ATLASSERT(m_hDC != NULL);
2082		return ::RoundRect(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, point.x, point.y);
2083	}
2084
2085// Bitmap Functions
2086	BOOL PatBlt(int x, int y, int nWidth, int nHeight, DWORD dwRop)
2087	{
2088		ATLASSERT(m_hDC != NULL);
2089		return ::PatBlt(m_hDC, x, y, nWidth, nHeight, dwRop);
2090	}
2091
2092	BOOL BitBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC,
2093		int xSrc, int ySrc, DWORD dwRop)
2094	{
2095		ATLASSERT(m_hDC != NULL);
2096		return ::BitBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, dwRop);
2097	}
2098
2099	BOOL StretchBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop)
2100	{
2101		ATLASSERT(m_hDC != NULL);
2102		return ::StretchBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, dwRop);
2103	}
2104
2105	COLORREF GetPixel(int x, int y) const
2106	{
2107		ATLASSERT(m_hDC != NULL);
2108		return ::GetPixel(m_hDC, x, y);
2109	}
2110
2111	COLORREF GetPixel(POINT point) const
2112	{
2113		ATLASSERT(m_hDC != NULL);
2114		return ::GetPixel(m_hDC, point.x, point.y);
2115	}
2116
2117	COLORREF SetPixel(int x, int y, COLORREF crColor)
2118	{
2119		ATLASSERT(m_hDC != NULL);
2120		return ::SetPixel(m_hDC, x, y, crColor);
2121	}
2122
2123	COLORREF SetPixel(POINT point, COLORREF crColor)
2124	{
2125		ATLASSERT(m_hDC != NULL);
2126		return ::SetPixel(m_hDC, point.x, point.y, crColor);
2127	}
2128
2129	BOOL FloodFill(int x, int y, COLORREF crColor)
2130	{
2131		ATLASSERT(m_hDC != NULL);
2132		return ::FloodFill(m_hDC, x, y, crColor);
2133	}
2134
2135	BOOL ExtFloodFill(int x, int y, COLORREF crColor, UINT nFillType)
2136	{
2137		ATLASSERT(m_hDC != NULL);
2138		return ::ExtFloodFill(m_hDC, x, y, crColor, nFillType);
2139	}
2140
2141	BOOL MaskBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, HBITMAP hMaskBitmap, int xMask, int yMask, DWORD dwRop)
2142	{
2143		ATLASSERT(m_hDC != NULL);
2144		return ::MaskBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, hMaskBitmap, xMask, yMask, dwRop);
2145	}
2146
2147	BOOL PlgBlt(LPPOINT lpPoint, HDC hSrcDC, int xSrc, int ySrc, int nWidth, int nHeight, HBITMAP hMaskBitmap, int xMask, int yMask)
2148	{
2149		ATLASSERT(m_hDC != NULL);
2150		return ::PlgBlt(m_hDC, lpPoint, hSrcDC, xSrc, ySrc, nWidth, nHeight, hMaskBitmap, xMask, yMask);
2151	}
2152
2153	BOOL SetPixelV(int x, int y, COLORREF crColor)
2154	{
2155		ATLASSERT(m_hDC != NULL);
2156		return ::SetPixelV(m_hDC, x, y, crColor);
2157	}
2158
2159	BOOL SetPixelV(POINT point, COLORREF crColor)
2160	{
2161		ATLASSERT(m_hDC != NULL);
2162		return ::SetPixelV(m_hDC, point.x, point.y, crColor);
2163	}
2164
2165	BOOL TransparentBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, UINT crTransparent)
2166	{
2167		ATLASSERT(m_hDC != NULL);
2168		return ::TransparentBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, crTransparent);
2169	}
2170
2171	BOOL GradientFill(const PTRIVERTEX pVertices, DWORD nVertices, void* pMeshElements, DWORD nMeshElements, DWORD dwMode)
2172	{
2173		ATLASSERT(m_hDC != NULL);
2174		return ::GradientFill(m_hDC, pVertices, nVertices, pMeshElements, nMeshElements, dwMode);
2175	}
2176
2177	BOOL GradientFillRect(RECT& rect, COLORREF clr1, COLORREF clr2, bool bHorizontal)
2178	{
2179		ATLASSERT(m_hDC != NULL);
2180
2181		TRIVERTEX arrTvx[2] = { { 0 }, { 0 } };
2182
2183		arrTvx[0].x = rect.left;
2184		arrTvx[0].y = rect.top;
2185		arrTvx[0].Red = MAKEWORD(0, GetRValue(clr1));
2186		arrTvx[0].Green = MAKEWORD(0, GetGValue(clr1));
2187		arrTvx[0].Blue = MAKEWORD(0, GetBValue(clr1));
2188		arrTvx[0].Alpha = 0;
2189
2190		arrTvx[1].x = rect.right;
2191		arrTvx[1].y = rect.bottom;
2192		arrTvx[1].Red = MAKEWORD(0, GetRValue(clr2));
2193		arrTvx[1].Green = MAKEWORD(0, GetGValue(clr2));
2194		arrTvx[1].Blue = MAKEWORD(0, GetBValue(clr2));
2195		arrTvx[1].Alpha = 0;
2196
2197		GRADIENT_RECT gr = { 0, 1 };
2198
2199		return ::GradientFill(m_hDC, arrTvx, 2, &gr, 1, bHorizontal ? GRADIENT_FILL_RECT_H : GRADIENT_FILL_RECT_V);
2200	}
2201
2202	BOOL AlphaBlend(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, BLENDFUNCTION bf)
2203	{
2204		ATLASSERT(m_hDC != NULL);
2205		return ::AlphaBlend(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, bf);
2206	}
2207
2208// Extra bitmap functions
2209	// Helper function for painting a disabled toolbar or menu bitmap
2210	// This function can take either an HBITMAP (for SS) or a DC with 
2211	//           the bitmap already painted (for cmdbar)
2212	BOOL DitherBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, HBITMAP hBitmap, int xSrc, int ySrc,
2213			HBRUSH hBrushBackground = ::GetSysColorBrush(COLOR_3DFACE),
2214			HBRUSH hBrush3DEffect = ::GetSysColorBrush(COLOR_3DHILIGHT),
2215			HBRUSH hBrushDisabledImage = ::GetSysColorBrush(COLOR_3DSHADOW))
2216	{
2217		ATLASSERT((m_hDC != NULL) || (hBitmap != NULL));
2218		ATLASSERT((nWidth > 0) && (nHeight > 0));
2219		
2220		// Create a generic DC for all BitBlts
2221		CDCT<false> dc = (hSrcDC != NULL) ? hSrcDC : ::CreateCompatibleDC(m_hDC);
2222		ATLASSERT(dc.m_hDC != NULL);
2223		if(dc.m_hDC == NULL)
2224			return FALSE;
2225		
2226		// Create a DC for the monochrome DIB section
2227		CDCT<true> dcBW = ::CreateCompatibleDC(m_hDC);
2228		ATLASSERT(dcBW.m_hDC != NULL);
2229		if(dcBW.m_hDC == NULL)
2230		{
2231			if(hSrcDC == NULL)
2232				dc.DeleteDC();
2233			return FALSE;
2234		}
2235
2236		// Create the monochrome DIB section with a black and white palette
2237		struct RGBBWBITMAPINFO
2238		{
2239			BITMAPINFOHEADER bmiHeader; 
2240			RGBQUAD bmiColors[2]; 
2241		};
2242
2243		RGBBWBITMAPINFO rgbBWBitmapInfo = 
2244		{
2245			{ sizeof(BITMAPINFOHEADER), nWidth, nHeight, 1, 1, BI_RGB, 0, 0, 0, 0, 0 },
2246			{ { 0x00, 0x00, 0x00, 0x00 }, { 0xFF, 0xFF, 0xFF, 0x00 } }
2247		};
2248
2249		VOID* pbitsBW;
2250		CBitmap bmpBW = ::CreateDIBSection(dcBW, (LPBITMAPINFO)&rgbBWBitmapInfo, DIB_RGB_COLORS, &pbitsBW, NULL, 0);
2251		ATLASSERT(bmpBW.m_hBitmap != NULL);
2252		if(bmpBW.m_hBitmap == NULL)
2253		{
2254			if(hSrcDC == NULL)
2255				dc.DeleteDC();
2256			return FALSE;
2257		}
2258		
2259		// Attach the monochrome DIB section and the bitmap to the DCs
2260		HBITMAP hbmOldBW = dcBW.SelectBitmap(bmpBW);
2261		HBITMAP hbmOldDC = NULL;
2262		if(hBitmap != NULL)
2263			hbmOldDC = dc.SelectBitmap(hBitmap);
2264
2265		// Block: Dark gray removal: we want (128, 128, 128) pixels to become black and not white
2266		{
2267			CDCT<true> dcTemp1 = ::CreateCompatibleDC(m_hDC);
2268			CDCT<true> dcTemp2 = ::CreateCompatibleDC(m_hDC);
2269			CBitmap bmpTemp1;
2270			bmpTemp1.CreateCompatibleBitmap(dc, nWidth, nHeight);
2271			CBitmap bmpTemp2;
2272			bmpTemp2.CreateBitmap(nWidth, nHeight, 1, 1, NULL);
2273			HBITMAP hOldBmp1 = dcTemp1.SelectBitmap(bmpTemp1);
2274			HBITMAP hOldBmp2 = dcTemp2.SelectBitmap(bmpTemp2);
2275			// Let's copy our image, it will be altered
2276			dcTemp1.BitBlt(0, 0, nWidth, nHeight, dc, xSrc, ySrc, SRCCOPY);
2277
2278			// All dark gray pixels will become white, the others black
2279			dcTemp1.SetBkColor(RGB(128, 128, 128));
2280			dcTemp2.BitBlt(0, 0, nWidth, nHeight, dcTemp1, 0, 0, SRCCOPY);
2281			// Do an XOR to set to black these white pixels
2282			dcTemp1.BitBlt(0, 0, nWidth, nHeight, dcTemp2, 0, 0, SRCINVERT);
2283
2284			// BitBlt the bitmap into the monochrome DIB section
2285			// The DIB section will do a true monochrome conversion
2286			// The magenta background being closer to white will become white
2287			dcBW.BitBlt(0, 0, nWidth, nHeight, dcTemp1, 0, 0, SRCCOPY);
2288
2289			// Cleanup
2290			dcTemp1.SelectBitmap(hOldBmp1);
2291			dcTemp2.SelectBitmap(hOldBmp2);
2292		}
2293		
2294		// Paint the destination rectangle using hBrushBackground
2295		if(hBrushBackground != NULL)
2296		{
2297			RECT rc = { x, y, x + nWidth, y + nHeight };
2298			FillRect(&rc, hBrushBackground);
2299		}
2300
2301		// BitBlt the black bits in the monochrome bitmap into hBrush3DEffect color in the destination DC
2302		// The magic ROP comes from the Charles Petzold's book
2303		HBRUSH hOldBrush = SelectBrush(hBrush3DEffect);
2304		BitBlt(x + 1, y + 1, nWidth, nHeight, dcBW, 0, 0, 0xB8074A);
2305
2306		// BitBlt the black bits in the monochrome bitmap into hBrushDisabledImage color in the destination DC
2307		SelectBrush(hBrushDisabledImage);
2308		BitBlt(x, y, nWidth, nHeight, dcBW, 0, 0, 0xB8074A);
2309
2310		SelectBrush(hOldBrush);
2311		dcBW.SelectBitmap(hbmOldBW);
2312		dc.SelectBitmap(hbmOldDC);
2313
2314		if(hSrcDC == NULL)
2315			dc.DeleteDC();
2316
2317		return TRUE;
2318	}
2319
2320// Text Functions
2321	BOOL TextOut(int x, int y, LPCTSTR lpszString, int nCount = -1)
2322	{
2323		ATLASSERT(m_hDC != NULL);
2324		if(nCount == -1)
2325			nCount = lstrlen(lpszString);
2326		return ::TextOut(m_hDC, x, y, lpszString, nCount);
2327	}
2328
2329	BOOL ExtTextOut(int x, int y, UINT nOptions, LPCRECT lpRect, LPCTSTR lpszString, int nCount = -1, LPINT lpDxWidths = NULL)
2330	{
2331		ATLASSERT(m_hDC != NULL);
2332		if(nCount == -1)
2333			nCount = lstrlen(lpszString);
2334		ATLASSERT((nCount >= 0) && (nCount <= 8192));
2335		return ::ExtTextOut(m_hDC, x, y, nOptions, lpRect, lpszString, (UINT)nCount, lpDxWidths);
2336	}
2337
2338	SIZE TabbedTextOut(int x, int y, LPCTSTR lpszString, int nCount = -1, int nTabPositions = 0, LPINT lpnTabStopPositions = NULL, int nTabOrigin = 0)
2339	{
2340		ATLASSERT(m_hDC != NULL);
2341		if(nCount == -1)
2342			nCount = lstrlen(lpszString);
2343		LONG lRes = ::TabbedTextOut(m_hDC, x, y, lpszString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin);
2344		SIZE size = { GET_X_LPARAM(lRes), GET_Y_LPARAM(lRes) };
2345		return size;
2346	}
2347
2348	int DrawText(LPCTSTR lpstrText, int cchText, LPRECT lpRect, UINT uFormat)
2349	{
2350		ATLASSERT(m_hDC != NULL);
2351		ATLASSERT((uFormat & DT_MODIFYSTRING) == 0);
2352		return ::DrawText(m_hDC, lpstrText, cchText, lpRect, uFormat);
2353	}
2354
2355	int DrawText(LPTSTR lpstrText, int cchText, LPRECT lpRect, UINT uFormat)
2356	{
2357		ATLASSERT(m_hDC != NULL);
2358		return ::DrawText(m_hDC, lpstrText, cchText, lpRect, uFormat);
2359	}
2360
2361	int DrawTextEx(LPTSTR lpstrText, int cchText, LPRECT lpRect, UINT uFormat, LPDRAWTEXTPARAMS lpDTParams = NULL)
2362	{
2363		ATLASSERT(m_hDC != NULL);
2364		return ::DrawTextEx(m_hDC, lpstrText, cchText, lpRect, uFormat, lpDTParams);
2365	}
2366
2367	// Note - ::DrawShadowText() is present only if comctl32.dll version 6 is loaded
2368	int DrawShadowText(LPCWSTR lpstrText, int cchText, LPRECT lpRect, DWORD dwFlags, COLORREF clrText, COLORREF clrShadow, int xOffset, int yOffset)
2369	{
2370		ATLASSERT(m_hDC != NULL);
2371		ATLASSERT(lpRect != NULL);
2372		return ::DrawShadowText(m_hDC, lpstrText, cchText, lpRect, dwFlags, clrText, clrShadow, xOffset, yOffset);
2373	}
2374
2375	BOOL GetTextExtent(LPCTSTR lpszString, int nCount, LPSIZE lpSize) const
2376	{
2377		ATLASSERT(m_hDC != NULL);
2378		if(nCount == -1)
2379			nCount = lstrlen(lpszString);
2380		return ::GetTextExtentPoint32(m_hDC, lpszString, nCount, lpSize);
2381	}
2382
2383	BOOL GetTextExtentExPoint(LPCTSTR lpszString, int cchString, LPSIZE lpSize, int nMaxExtent, LPINT lpnFit = NULL, LPINT alpDx = NULL)
2384	{
2385		ATLASSERT(m_hDC != NULL);
2386		return ::GetTextExtentExPoint(m_hDC, lpszString, cchString, nMaxExtent, lpnFit, alpDx, lpSize);
2387	}
2388
2389	DWORD GetTabbedTextExtent(LPCTSTR lpszString, int nCount = -1, int nTabPositions = 0, LPINT lpnTabStopPositions = NULL) const
2390	{
2391		ATLASSERT(m_hDC != NULL);
2392		if(nCount == -1)
2393			nCount = lstrlen(lpszString);
2394		return ::GetTabbedTextExtent(m_hDC, lpszString, nCount, nTabPositions, lpnTabStopPositions);
2395	}
2396
2397	BOOL GrayString(HBRUSH hBrush, BOOL (CALLBACK* lpfnOutput)(HDC, LPARAM, int), LPARAM lpData, int nCount, int x, int y, int nWidth, int nHeight)
2398	{
2399		ATLASSERT(m_hDC != NULL);
2400		return ::GrayString(m_hDC, hBrush, (GRAYSTRINGPROC)lpfnOutput, lpData, nCount, x, y, nWidth, nHeight);
2401	}
2402
2403	UINT GetTextAlign() const
2404	{
2405		ATLASSERT(m_hDC != NULL);
2406		return ::GetTextAlign(m_hDC);
2407	}
2408
2409	UINT SetTextAlign(UINT nFlags)
2410	{
2411		ATLASSERT(m_hDC != NULL);
2412		return ::SetTextAlign(m_hDC, nFlags);
2413	}
2414
2415	int GetTextFace(LPTSTR lpszFacename, int nCount) const
2416	{
2417		ATLASSERT(m_hDC != NULL);
2418		return ::GetTextFace(m_hDC, nCount, lpszFacename);
2419	}
2420
2421	int GetTextFaceLen() const
2422	{
2423		ATLASSERT(m_hDC != NULL);
2424		return ::GetTextFace(m_hDC, 0, NULL);
2425	}
2426
2427#ifdef _OLEAUTO_H_
2428	BOOL GetTextFace(BSTR& bstrFace) const
2429	{
2430		USES_CONVERSION;
2431		ATLASSERT(m_hDC != NULL);
2432		ATLASSERT(bstrFace == NULL);
2433
2434		int nLen = GetTextFaceLen();
2435		if(nLen == 0)
2436			return FALSE;
2437
2438		ATL::CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
2439		LPTSTR lpszText = buff.Allocate(nLen);
2440		if(lpszText == NULL)
2441			return FALSE;
2442
2443		if(!GetTextFace(lpszText, nLen))
2444			return FALSE;
2445
2446		bstrFace = ::SysAllocString(T2OLE(lpszText));
2447		return (bstrFace != NULL) ? TRUE : FALSE;
2448	}
2449#endif
2450
2451#ifdef __ATLSTR_H__
2452	int GetTextFace(ATL::CString& strFace) const
2453	{
2454		ATLASSERT(m_hDC != NULL);
2455
2456		int nLen = GetTextFaceLen();
2457		if(nLen == 0)
2458			return 0;
2459
2460		LPTSTR lpstr = strFace.GetBufferSetLength(nLen);
2461		if(lpstr == NULL)
2462			return 0;
2463		int nRet = GetTextFace(lpstr, nLen);
2464		strFace.ReleaseBuffer();
2465		return nRet;
2466	}
2467#endif // __ATLSTR_H__
2468
2469	BOOL GetTextMetrics(LPTEXTMETRIC lpMetrics) const
2470	{
2471		ATLASSERT(m_hDC != NULL);
2472		return ::GetTextMetrics(m_hDC, lpMetrics);
2473	}
2474
2475	int SetTextJustification(int nBreakExtra, int nBreakCount)
2476	{
2477		ATLASSERT(m_hDC != NULL);
2478		return ::SetTextJustification(m_hDC, nBreakExtra, nBreakCount);
2479	}
2480
2481	int GetTextCharacterExtra() const
2482	{
2483		ATLASSERT(m_hDC != NULL);
2484		return ::GetTextCharacterExtra(m_hDC);
2485	}
2486
2487	int SetTextCharacterExtra(int nCharExtra)
2488	{
2489		ATLASSERT(m_hDC != NULL);
2490		return ::SetTextCharacterExtra(m_hDC, nCharExtra);
2491	}
2492
2493// Advanced Drawing
2494	BOOL DrawEdge(LPRECT lpRect, UINT nEdge, UINT nFlags)
2495	{
2496		ATLASSERT(m_hDC != NULL);
2497		return ::DrawEdge(m_hDC, lpRect, nEdge, nFlags);
2498	}
2499
2500	BOOL DrawFrameControl(LPRECT lpRect, UINT nType, UINT nState)
2501	{
2502		ATLASSERT(m_hDC != NULL);
2503		return ::DrawFrameControl(m_hDC, lpRect, nType, nState);
2504	}
2505
2506// Scrolling Functions
2507	BOOL ScrollDC(int dx, int dy, LPCRECT lpRectScroll, LPCRECT lpRectClip, HRGN hRgnUpdate, LPRECT lpRectUpdate)
2508	{
2509		ATLASSERT(m_hDC != NULL);
2510		return ::ScrollDC(m_hDC, dx, dy, lpRectScroll, lpRectClip, hRgnUpdate, lpRectUpdate);
2511	}
2512
2513// Font Functions
2514	BOOL GetCharWidth(UINT nFirstChar, UINT nLastChar, LPINT lpBuffer) const
2515	{
2516		ATLASSERT(m_hDC != NULL);
2517		return ::GetCharWidth(m_hDC, nFirstChar, nLastChar, lpBuffer);
2518	}
2519
2520	// GetCharWidth32 is not supported under Win9x
2521	BOOL GetCharWidth32(UINT nFirstChar, UINT nLastChar, LPINT lpBuffer) const
2522	{
2523		ATLASSERT(m_hDC != NULL);
2524		return ::GetCharWidth32(m_hDC, nFirstChar, nLastChar, lpBuffer);
2525	}
2526
2527	DWORD SetMapperFlags(DWORD dwFlag)
2528	{
2529		ATLASSERT(m_hDC != NULL);
2530		return ::SetMapperFlags(m_hDC, dwFlag);
2531	}
2532
2533	BOOL GetAspectRatioFilter(LPSIZE lpSize) const
2534	{
2535		ATLASSERT(m_hDC != NULL);
2536		return ::GetAspectRatioFilterEx(m_hDC, lpSize);
2537	}
2538
2539	BOOL GetCharABCWidths(UINT nFirstChar, UINT nLastChar, LPABC lpabc) const
2540	{
2541		ATLASSERT(m_hDC != NULL);
2542		return ::GetCharABCWidths(m_hDC, nFirstChar, nLastChar, lpabc);
2543	}
2544
2545	DWORD GetFontData(DWORD dwTable, DWORD dwOffset, LPVOID lpData, DWORD cbData) const
2546	{
2547		ATLASSERT(m_hDC != NULL);
2548		return ::GetFontData(m_hDC, dwTable, dwOffset, lpData, cbData);
2549	}
2550
2551	int GetKerningPairs(int nPairs, LPKERNINGPAIR lpkrnpair) const
2552	{
2553		ATLASSERT(m_hDC != NULL);
2554		return ::GetKerningPairs(m_hDC, nPairs, lpkrnpair);
2555	}
2556
2557	UINT GetOutlineTextMetrics(UINT cbData, LPOUTLINETEXTMETRIC lpotm) const
2558	{
2559		ATLASSERT(m_hDC != NULL);
2560		return ::GetOutlineTextMetrics(m_hDC, cbData, lpotm);
2561	}
2562
2563	DWORD GetGlyphOutline(UINT nChar, UINT nFormat, LPGLYPHMETRICS lpgm, DWORD cbBuffer, LPVOID lpBuffer, const MAT2* lpmat2) const
2564	{
2565		ATLASSERT(m_hDC != NULL);
2566		return ::GetGlyphOutline(m_hDC, nChar, nFormat, lpgm, cbBuffer, lpBuffer, lpmat2);
2567	}
2568
2569	BOOL GetCharABCWidths(UINT nFirstChar, UINT nLastChar, LPABCFLOAT lpABCF) const
2570	{
2571		ATLASSERT(m_hDC != NULL);
2572		return ::GetCharABCWidthsFloat(m_hDC, nFirstChar, nLastChar, lpABCF);
2573	}
2574
2575	BOOL GetCharWidth(UINT nFirstChar, UINT nLastChar, float* lpFloatBuffer) const
2576	{
2577		ATLASSERT(m_hDC != NULL);
2578		return ::GetCharWidthFloat(m_hDC, nFirstChar, nLastChar, lpFloatBuffer);
2579	}
2580
2581// Printer/Device Escape Functions
2582	int Escape(int nEscape, int nCount, LPCSTR lpszInData, LPVOID lpOutData)
2583	{
2584		ATLASSERT(m_hDC != NULL);
2585		return ::Escape(m_hDC, nEscape, nCount, lpszInData, lpOutData);
2586	}
2587
2588	int Escape(int nEscape, int nInputSize, LPCSTR lpszInputData,
2589		int nOutputSize, LPSTR lpszOutputData)
2590	{
2591		ATLASSERT(m_hDC != NULL);
2592		return ::ExtEscape(m_hDC, nEscape, nInputSize, lpszInputData, nOutputSize, lpszOutputData);
2593	}
2594
2595	int DrawEscape(int nEscape, int nInputSize, LPCSTR lpszInputData)
2596	{
2597		ATLASSERT(m_hDC != NULL);
2598		return ::DrawEscape(m_hDC, nEscape, nInputSize, lpszInputData);
2599	}
2600
2601	// Escape helpers
2602	int StartDoc(LPCTSTR lpszDocName)  // old Win3.0 version
2603	{
2604		DOCINFO di = {};
2605		di.cbSize = sizeof(DOCINFO);
2606		di.lpszDocName = lpszDocName;
2607		return StartDoc(&di);
2608	}
2609
2610	int StartDoc(LPDOCINFO lpDocInfo)
2611	{
2612		ATLASSERT(m_hDC != NULL);
2613		return ::StartDoc(m_hDC, lpDocInfo);
2614	}
2615
2616	int StartPage()
2617	{
2618		ATLASSERT(m_hDC != NULL);
2619		return ::StartPage(m_hDC);
2620	}
2621
2622	int EndPage()
2623	{
2624		ATLASSERT(m_hDC != NULL);
2625		return ::EndPage(m_hDC);
2626	}
2627
2628	int SetAbortProc(BOOL (CALLBACK* lpfn)(HDC, int))
2629	{
2630		ATLASSERT(m_hDC != NULL);
2631		return ::SetAbortProc(m_hDC, (ABORTPROC)lpfn);
2632	}
2633
2634	int AbortDoc()
2635	{
2636		ATLASSERT(m_hDC != NULL);
2637		return ::AbortDoc(m_hDC);
2638	}
2639
2640	int EndDoc()
2641	{
2642		ATLASSERT(m_hDC != NULL);
2643		return ::EndDoc(m_hDC);
2644	}
2645
2646// MetaFile Functions
2647	BOOL PlayMetaFile(HMETAFILE hMF)
2648	{
2649		ATLASSERT(m_hDC != NULL);
2650		if(::GetDeviceCaps(m_hDC, TECHNOLOGY) == DT_METAFILE)
2651		{
2652			// playing metafile in metafile, just use core windows API
2653			return ::PlayMetaFile(m_hDC, hMF);
2654		}
2655
2656		// for special playback, lParam == pDC
2657		return ::EnumMetaFile(m_hDC, hMF, EnumMetaFileProc, (LPARAM)this);
2658	}
2659
2660	BOOL PlayMetaFile(HENHMETAFILE hEnhMetaFile, LPCRECT lpBounds)
2661	{
2662		ATLASSERT(m_hDC != NULL);
2663		return ::PlayEnhMetaFile(m_hDC, hEnhMetaFile, lpBounds);
2664	}
2665
2666	BOOL AddMetaFileComment(UINT nDataSize, const BYTE* pCommentData) // can be used for enhanced metafiles only
2667	{
2668		ATLASSERT(m_hDC != NULL);
2669		return ::GdiComment(m_hDC, nDataSize, pCommentData);
2670	}
2671
2672	// Special handling for metafile playback
2673	static int CALLBACK EnumMetaFileProc(HDC hDC, HANDLETABLE* pHandleTable, METARECORD* pMetaRec, int nHandles, LPARAM lParam)
2674	{
2675		CDCT<false>* pDC = (CDCT<false>*)lParam;
2676
2677		switch (pMetaRec->rdFunction)
2678		{
2679		case META_SETMAPMODE:
2680			pDC->SetMapMode((int)(short)pMetaRec->rdParm[0]);
2681			break;
2682		case META_SETWINDOWEXT:
2683			pDC->SetWindowExt((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
2684			break;
2685		case META_SETWINDOWORG:
2686			pDC->SetWindowOrg((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
2687			break;
2688		case META_SETVIEWPORTEXT:
2689			pDC->SetViewportExt((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
2690			break;
2691		case META_SETVIEWPORTORG:
2692			pDC->SetViewportOrg((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
2693			break;
2694		case META_SCALEWINDOWEXT:
2695			pDC->ScaleWindowExt((int)(short)pMetaRec->rdParm[3], (int)(short)pMetaRec->rdParm[2], 
2696				(int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
2697			break;
2698		case META_SCALEVIEWPORTEXT:
2699			pDC->ScaleViewportExt((int)(short)pMetaRec->rdParm[3], (int)(short)pMetaRec->rdParm[2],
2700				(int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
2701			break;
2702		case META_OFFSETVIEWPORTORG:
2703			pDC->OffsetViewportOrg((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
2704			break;
2705		case META_SAVEDC:
2706			pDC->SaveDC();
2707			break;
2708		case META_RESTOREDC:
2709			pDC->RestoreDC((int)(short)pMetaRec->rdParm[0]);
2710			break;
2711		case META_SETBKCOLOR:
2712			pDC->SetBkColor(*(UNALIGNED COLORREF*)&pMetaRec->rdParm[0]);
2713			break;
2714		case META_SETTEXTCOLOR:
2715			pDC->SetTextColor(*(UNALIGNED COLORREF*)&pMetaRec->rdParm[0]);
2716			break;
2717
2718		// need to watch out for SelectObject(HFONT), for custom font mapping
2719		case META_SELECTOBJECT:
2720			{
2721				HGDIOBJ hObject = pHandleTable->objectHandle[pMetaRec->rdParm[0]];
2722				UINT nObjType = ::GetObjectType(hObject);
2723				if(nObjType == 0)
2724				{
2725					// object type is unknown, determine if it is a font
2726					HFONT hStockFont = (HFONT)::GetStockObject(SYSTEM_FONT);
2727					HFONT hFontOld = (HFONT)::SelectObject(pDC->m_hDC, hStockFont);
2728					HGDIOBJ hObjOld = ::SelectObject(pDC->m_hDC, hObject);
2729					if(hObjOld == hStockFont)
2730					{
2731						// got the stock object back, so must be selecting a font
2732						pDC->SelectFont((HFONT)hObject);
2733						break;  // don't play the default record
2734					}
2735					else
2736					{
2737						// didn't get the stock object back, so restore everything
2738						::SelectObject(pDC->m_hDC, hFontOld);
2739						::SelectObject(pDC->m_hDC, hObjOld);
2740					}
2741					// and fall through to PlayMetaFileRecord...
2742				}
2743				else if(nObjType == OBJ_FONT)
2744				{
2745					// play back as CDCHandle::SelectFont(HFONT)
2746					pDC->SelectFont((HFONT)hObject);
2747					break;  // don't play the default record
2748				}
2749			}
2750			// fall through...
2751
2752		default:
2753			::PlayMetaFileRecord(hDC, pHandleTable, pMetaRec, nHandles);
2754			break;
2755		}
2756
2757		return 1;
2758	}
2759
2760// Path Functions
2761	BOOL AbortPath()
2762	{
2763		ATLASSERT(m_hDC != NULL);
2764		return ::AbortPath(m_hDC);
2765	}
2766
2767	BOOL BeginPath()
2768	{
2769		ATLASSERT(m_hDC != NULL);
2770		return ::BeginPath(m_hDC);
2771	}
2772
2773	BOOL CloseFigure()
2774	{
2775		ATLASSERT(m_hDC != NULL);
2776		return ::CloseFigure(m_hDC);
2777	}
2778
2779	BOOL EndPath()
2780	{
2781		ATLASSERT(m_hDC != NULL);
2782		return ::EndPath(m_hDC);
2783	}
2784
2785	BOOL FillPath()
2786	{
2787		ATLASSERT(m_hDC != NULL);
2788		return ::FillPath(m_hDC);
2789	}
2790
2791	BOOL FlattenPath()
2792	{
2793		ATLASSERT(m_hDC != NULL);
2794		return ::FlattenPath(m_hDC);
2795	}
2796
2797	BOOL StrokeAndFillPath()
2798	{
2799		ATLASSERT(m_hDC != NULL);
2800		return ::StrokeAndFillPath(m_hDC);
2801	}
2802
2803	BOOL StrokePath()
2804	{
2805		ATLASSERT(m_hDC != NULL);
2806		return ::StrokePath(m_hDC);
2807	}
2808
2809	BOOL WidenPath()
2810	{
2811		ATLASSERT(m_hDC != NULL);
2812		return ::WidenPath(m_hDC);
2813	}
2814
2815	BOOL GetMiterLimit(PFLOAT pfMiterLimit) const
2816	{
2817		ATLASSERT(m_hDC != NULL);
2818		return ::GetMiterLimit(m_hDC, pfMiterLimit);
2819	}
2820
2821	BOOL SetMiterLimit(float fMiterLimit)
2822	{
2823		ATLASSERT(m_hDC != NULL);
2824		return ::SetMiterLimit(m_hDC, fMiterLimit, NULL);
2825	}
2826
2827	int GetPath(LPPOINT lpPoints, LPBYTE lpTypes, int nCount) const
2828	{
2829		ATLASSERT(m_hDC != NULL);
2830		return ::GetPath(m_hDC, lpPoints, lpTypes, nCount);
2831	}
2832
2833	BOOL SelectClipPath(int nMode)
2834	{
2835		ATLASSERT(m_hDC != NULL);
2836		return ::SelectClipPath(m_hDC, nMode);
2837	}
2838
2839// Misc Helper Functions
2840	static CBrushHandle PASCAL GetHalftoneBrush()
2841	{
2842		HBRUSH halftoneBrush = NULL;
2843		WORD grayPattern[8] = {};
2844		for(int i = 0; i < 8; i++)
2845			grayPattern[i] = (WORD)(0x5555 << (i & 1));
2846		HBITMAP grayBitmap = CreateBitmap(8, 8, 1, 1, &grayPattern);
2847		if(grayBitmap != NULL)
2848		{
2849			halftoneBrush = ::CreatePatternBrush(grayBitmap);
2850			DeleteObject(grayBitmap);
2851		}
2852		return CBrushHandle(halftoneBrush);
2853	}
2854
2855	void DrawDragRect(LPCRECT lpRect, SIZE size, LPCRECT lpRectLast, SIZE sizeLast, HBRUSH hBrush = NULL, HBRUSH hBrushLast = NULL)
2856	{
2857		// first, determine the update region and select it
2858		CRgn rgnOutside;
2859		rgnOutside.CreateRectRgnIndirect(lpRect);
2860		RECT rect = *lpRect;
2861		::InflateRect(&rect, -size.cx, -size.cy);
2862		::IntersectRect(&rect, &rect, lpRect);
2863		CRgn rgnInside;
2864		rgnInside.CreateRectRgnIndirect(&rect);
2865		CRgn rgnNew;
2866		rgnNew.CreateRectRgn(0, 0, 0, 0);
2867		rgnNew.CombineRgn(rgnOutside, rgnInside, RGN_XOR);
2868
2869		HBRUSH hBrushOld = NULL;
2870		CBrush brushHalftone;
2871		if(hBrush == NULL)
2872			brushHalftone = hBrush = CDCHandle::GetHalftoneBrush();
2873		if(hBrushLast == NULL)
2874			hBrushLast = hBrush;
2875
2876		CRgn rgnLast;
2877		CRgn rgnUpdate;
2878		if(lpRectLast != NULL)
2879		{
2880			// find difference between new region and old region
2881			rgnLast.CreateRectRgn(0, 0, 0, 0);
2882			rgnOutside.SetRectRgn(lpRectLast->left, lpRectLast->top, lpRectLast->right, lpRectLast->bottom);
2883			rect = *lpRectLast;
2884			::InflateRect(&rect, -sizeLast.cx, -sizeLast.cy);
2885			::IntersectRect(&rect, &rect, lpRectLast);
2886			rgnInside.SetRectRgn(rect.left, rect.top, rect.right, rect.bottom);
2887			rgnLast.CombineRgn(rgnOutside, rgnInside, RGN_XOR);
2888
2889			// only diff them if brushes are the same
2890			if(hBrush == hBrushLast)
2891			{
2892				rgnUpdate.CreateRectRgn(0, 0, 0, 0);
2893				rgnUpdate.CombineRgn(rgnLast, rgnNew, RGN_XOR);
2894			}
2895		}
2896		if((hBrush != hBrushLast) && (lpRectLast != NULL))
2897		{
2898			// brushes are different -- erase old region first
2899			SelectClipRgn(rgnLast);
2900			GetClipBox(&rect);
2901			hBrushOld = SelectBrush(hBrushLast);
2902			PatBlt(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PATINVERT);
2903			SelectBrush(hBrushOld);
2904			hBrushOld = NULL;
2905		}
2906
2907		// draw into the update/new region
2908		SelectClipRgn(rgnUpdate.IsNull() ? rgnNew : rgnUpdate);
2909		GetClipBox(&rect);
2910		hBrushOld = SelectBrush(hBrush);
2911		PatBlt(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PATINVERT);
2912
2913		// cleanup DC
2914		if(hBrushOld != NULL)
2915			SelectBrush(hBrushOld);
2916		SelectClipRgn(NULL);
2917	}
2918
2919	void FillSolidRect(LPCRECT lpRect, COLORREF clr)
2920	{
2921		ATLASSERT(m_hDC != NULL);
2922
2923		COLORREF clrOld = ::SetBkColor(m_hDC, clr);
2924		ATLASSERT(clrOld != CLR_INVALID);
2925		if(clrOld != CLR_INVALID)
2926		{
2927			::ExtTextOut(m_hDC, 0, 0, ETO_OPAQUE, lpRect, NULL, 0, NULL);
2928			::SetBkColor(m_hDC, clrOld);
2929		}
2930	}
2931
2932	void FillSolidRect(int x, int y, int cx, int cy, COLORREF clr)
2933	{
2934		ATLASSERT(m_hDC != NULL);
2935
2936		RECT rect = { x, y, x + cx, y + cy };
2937		FillSolidRect(&rect, clr);
2938	}
2939
2940	void Draw3dRect(LPCRECT lpRect, COLORREF clrTopLeft, COLORREF clrBottomRight)
2941	{
2942		Draw3dRect(lpRect->left, lpRect->top, lpRect->right - lpRect->left,
2943			lpRect->bottom - lpRect->top, clrTopLeft, clrBottomRight);
2944	}
2945
2946	void Draw3dRect(int x, int y, int cx, int cy, COLORREF clrTopLeft, COLORREF clrBottomRight)
2947	{
2948		FillSolidRect(x, y, cx - 1, 1, clrTopLeft);
2949		FillSolidRect(x, y, 1, cy - 1, clrTopLeft);
2950		FillSolidRect(x + cx, y, -1, cy, clrBottomRight);
2951		FillSolidRect(x, y + cy, cx, -1, clrBottomRight);
2952	}
2953
2954// DIB support
2955	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)
2956	{
2957		ATLASSERT(m_hDC != NULL);
2958		return ::SetDIBitsToDevice(m_hDC, x, y, dwWidth, dwHeight, xSrc, ySrc, uStartScan, cScanLines, lpvBits, lpbmi, uColorUse);
2959	}
2960
2961	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)
2962	{
2963		ATLASSERT(m_hDC != NULL);
2964		return ::StretchDIBits(m_hDC, x, y, nWidth, nHeight, xSrc, ySrc, nSrcWidth, nSrcHeight, lpvBits, lpbmi, uColorUse, dwRop);
2965	}
2966
2967	UINT GetDIBColorTable(UINT uStartIndex, UINT cEntries, RGBQUAD* pColors) const
2968	{
2969		ATLASSERT(m_hDC != NULL);
2970		return ::GetDIBColorTable(m_hDC, uStartIndex, cEntries, pColors);
2971	}
2972
2973	UINT SetDIBColorTable(UINT uStartIndex, UINT cEntries, CONST RGBQUAD* pColors)
2974	{
2975		ATLASSERT(m_hDC != NULL);
2976		return ::SetDIBColorTable(m_hDC, uStartIndex, cEntries, pColors);
2977	}
2978
2979// OpenGL support
2980#if !defined(_ATL_NO_OPENGL)
2981	int ChoosePixelFormat(CONST PIXELFORMATDESCRIPTOR* ppfd)
2982	{
2983		ATLASSERT(m_hDC != NULL);
2984		return ::ChoosePixelFormat(m_hDC, ppfd);
2985	}
2986
2987	int DescribePixelFormat(int iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd)
2988	{
2989		ATLASSERT(m_hDC != NULL);
2990		return ::DescribePixelFormat(m_hDC, iPixelFormat, nBytes, ppfd);
2991	}
2992
2993	int GetPixelFormat() const
2994	{
2995		ATLASSERT(m_hDC != NULL);
2996		return ::GetPixelFormat(m_hDC);
2997	}
2998
2999	BOOL SetPixelFormat(int iPixelFormat, CONST PIXELFORMATDESCRIPTOR* ppfd)
3000	{
3001		ATLASSERT(m_hDC != NULL);
3002		return ::SetPixelFormat(m_hDC, iPixelFormat, ppfd);
3003	}
3004
3005	BOOL SwapBuffers()
3006	{
3007		ATLASSERT(m_hDC != NULL);
3008		return ::SwapBuffers(m_hDC);
3009	}
3010
3011	HGLRC wglCreateContext()
3012	{
3013		ATLASSERT(m_hDC != NULL);
3014		return ::wglCreateContext(m_hDC);
3015	}
3016
3017	HGLRC wglCreateLayerContext(int iLayerPlane)
3018	{
3019		ATLASSERT(m_hDC != NULL);
3020		return ::wglCreateLayerContext(m_hDC, iLayerPlane);
3021	}
3022
3023	BOOL wglMakeCurrent(HGLRC hglrc)
3024	{
3025		ATLASSERT(m_hDC != NULL);
3026		return ::wglMakeCurrent(m_hDC, hglrc);
3027	}
3028
3029	BOOL wglUseFontBitmaps(DWORD dwFirst, DWORD dwCount, DWORD listBase)
3030	{
3031		ATLASSERT(m_hDC != NULL);
3032		return ::wglUseFontBitmaps(m_hDC, dwFirst, dwCount, listBase);
3033	}
3034
3035	BOOL wglUseFontOutlines(DWORD dwFirst, DWORD dwCount, DWORD listBase, FLOAT deviation, FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf)
3036	{
3037		ATLASSERT(m_hDC != NULL);
3038		return ::wglUseFontOutlines(m_hDC, dwFirst, dwCount, listBase, deviation, extrusion, format, lpgmf);
3039	}
3040
3041	BOOL wglDescribeLayerPlane(int iPixelFormat, int iLayerPlane, UINT nBytes, LPLAYERPLANEDESCRIPTOR plpd)
3042	{
3043		ATLASSERT(m_hDC != NULL);
3044		return ::wglDescribeLayerPlane(m_hDC, iPixelFormat, iLayerPlane, nBytes, plpd);
3045	}
3046
3047	int wglSetLayerPaletteEntries(int iLayerPlane, int iStart, int cEntries, CONST COLORREF* pclr)
3048	{
3049		ATLASSERT(m_hDC != NULL);
3050		return ::wglSetLayerPaletteEntries(m_hDC, iLayerPlane, iStart, cEntries, pclr);
3051	}
3052
3053	int wglGetLayerPaletteEntries(int iLayerPlane, int iStart, int cEntries, COLORREF* pclr)
3054	{
3055		ATLASSERT(m_hDC != NULL);
3056		return ::wglGetLayerPaletteEntries(m_hDC, iLayerPlane, iStart, cEntries, pclr);
3057	}
3058
3059	BOOL wglRealizeLayerPalette(int iLayerPlane, BOOL bRealize)
3060	{
3061		ATLASSERT(m_hDC != NULL);
3062		return ::wglRealizeLayerPalette(m_hDC, iLayerPlane, bRealize);
3063	}
3064
3065	BOOL wglSwapLayerBuffers(UINT uPlanes)
3066	{
3067		ATLASSERT(m_hDC != NULL);
3068		return ::wglSwapLayerBuffers(m_hDC, uPlanes);
3069	}
3070#endif // !defined(_ATL_NO_OPENGL)
3071
3072	COLORREF GetDCPenColor() const
3073	{
3074		ATLASSERT(m_hDC != NULL);
3075		return ::GetDCPenColor(m_hDC);
3076	}
3077
3078	COLORREF SetDCPenColor(COLORREF clr)
3079	{
3080		ATLASSERT(m_hDC != NULL);
3081		return ::SetDCPenColor(m_hDC, clr);
3082	}
3083
3084	COLORREF GetDCBrushColor() const
3085	{
3086		ATLASSERT(m_hDC != NULL);
3087		return ::GetDCBrushColor(m_hDC);
3088	}
3089
3090	COLORREF SetDCBrushColor(COLORREF clr)
3091	{
3092		ATLASSERT(m_hDC != NULL);
3093		return ::SetDCBrushColor(m_hDC, clr);
3094	}
3095
3096	DWORD GetFontUnicodeRanges(LPGLYPHSET lpgs) const
3097	{
3098		ATLASSERT(m_hDC != NULL);
3099		return ::GetFontUnicodeRanges(m_hDC, lpgs);
3100	}
3101
3102	DWORD GetGlyphIndices(LPCTSTR lpstr, int cch, LPWORD pgi, DWORD dwFlags) const
3103	{
3104		ATLASSERT(m_hDC != NULL);
3105		return ::GetGlyphIndices(m_hDC, lpstr, cch, pgi, dwFlags);
3106	}
3107
3108	BOOL GetTextExtentPointI(LPWORD pgiIn, int cgi, LPSIZE lpSize) const
3109	{
3110		ATLASSERT(m_hDC != NULL);
3111		return ::GetTextExtentPointI(m_hDC, pgiIn, cgi, lpSize);
3112	}
3113
3114	BOOL GetTextExtentExPointI(LPWORD pgiIn, int cgi, int nMaxExtent, LPINT lpnFit, LPINT alpDx, LPSIZE lpSize) const
3115	{
3116		ATLASSERT(m_hDC != NULL);
3117		return ::GetTextExtentExPointI(m_hDC, pgiIn, cgi, nMaxExtent, lpnFit, alpDx, lpSize);
3118	}
3119
3120	BOOL GetCharWidthI(UINT giFirst, UINT cgi, LPWORD pgi, LPINT lpBuffer) const
3121	{
3122		ATLASSERT(m_hDC != NULL);
3123		return ::GetCharWidthI(m_hDC, giFirst, cgi, pgi, lpBuffer);
3124	}
3125
3126	BOOL GetCharABCWidthsI(UINT giFirst, UINT cgi, LPWORD pgi, LPABC lpabc) const
3127	{
3128		ATLASSERT(m_hDC != NULL);
3129		return ::GetCharABCWidthsI(m_hDC, giFirst, cgi, pgi, lpabc);
3130	}
3131
3132	BOOL ColorCorrectPalette(HPALETTE hPalette, DWORD dwFirstEntry, DWORD dwNumOfEntries)
3133	{
3134		ATLASSERT(m_hDC != NULL);
3135		return ::ColorCorrectPalette(m_hDC, hPalette, dwFirstEntry, dwNumOfEntries);
3136	}
3137};
3138
3139
3140///////////////////////////////////////////////////////////////////////////////
3141// CDC Helpers
3142
3143class CPaintDC : public CDC
3144{
3145public:
3146// Data members
3147	HWND m_hWnd;
3148	PAINTSTRUCT m_ps;
3149
3150// Constructor/destructor
3151	CPaintDC(HWND hWnd)
3152	{
3153		ATLASSERT(::IsWindow(hWnd));
3154		m_hWnd = hWnd;
3155		m_hDC = ::BeginPaint(hWnd, &m_ps);
3156	}
3157
3158	~CPaintDC()
3159	{
3160		ATLASSERT(m_hDC != NULL);
3161		ATLASSERT(::IsWindow(m_hWnd));
3162		::EndPaint(m_hWnd, &m_ps);
3163		Detach();
3164	}
3165};
3166
3167class CClientDC : public CDC
3168{
3169public:
3170// Data members
3171	HWND m_hWnd;
3172
3173// Constructor/destructor
3174	CClientDC(HWND hWnd)
3175	{
3176		ATLASSERT((hWnd == NULL) || ::IsWindow(hWnd));
3177		m_hWnd = hWnd;
3178		m_hDC = ::GetDC(hWnd);
3179	}
3180
3181	~CClientDC()
3182	{
3183		ATLASSERT(m_hDC != NULL);
3184		::ReleaseDC(m_hWnd, Detach());
3185	}
3186};
3187
3188class CWindowDC : public CDC
3189{
3190public:
3191// Data members
3192	HWND m_hWnd;
3193
3194// Constructor/destructor
3195	CWindowDC(HWND hWnd)
3196	{
3197		ATLASSERT((hWnd == NULL) || ::IsWindow(hWnd));
3198		m_hWnd = hWnd;
3199		m_hDC = ::GetWindowDC(hWnd);
3200	}
3201
3202	~CWindowDC()
3203	{
3204		ATLASSERT(m_hDC != NULL);
3205		::ReleaseDC(m_hWnd, Detach());
3206	}
3207};
3208
3209class CMemoryDC : public CDC
3210{
3211public:
3212// Data members
3213	HDC m_hDCOriginal;
3214	RECT m_rcPaint;
3215	CBitmap m_bmp;
3216	HBITMAP m_hBmpOld;
3217
3218// Constructor/destructor
3219	CMemoryDC(HDC hDC, const RECT& rcPaint) : m_hDCOriginal(hDC), m_hBmpOld(NULL)
3220	{
3221		m_rcPaint = rcPaint;
3222		CreateCompatibleDC(m_hDCOriginal);
3223		ATLASSERT(m_hDC != NULL);
3224		m_bmp.CreateCompatibleBitmap(m_hDCOriginal, m_rcPaint.right - m_rcPaint.left, m_rcPaint.bottom - m_rcPaint.top);
3225		ATLASSERT(m_bmp.m_hBitmap != NULL);
3226		m_hBmpOld = SelectBitmap(m_bmp);
3227		SetViewportOrg(-m_rcPaint.left, -m_rcPaint.top);
3228	}
3229
3230	~CMemoryDC()
3231	{
3232		::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);
3233		SelectBitmap(m_hBmpOld);
3234	}
3235};
3236
3237
3238///////////////////////////////////////////////////////////////////////////////
3239// Enhanced metafile support
3240
3241class CEnhMetaFileInfo
3242{
3243public:
3244// Data members
3245	HENHMETAFILE m_hEMF;
3246	BYTE* m_pBits;
3247	TCHAR* m_pDesc;
3248	ENHMETAHEADER m_header;
3249	PIXELFORMATDESCRIPTOR m_pfd;
3250
3251// Constructor/destructor
3252	CEnhMetaFileInfo(HENHMETAFILE hEMF) : m_hEMF(hEMF), m_pBits(NULL), m_pDesc(NULL)
3253	{
3254		memset(&m_header, 0, sizeof(m_header));
3255		memset(&m_pfd, 0, sizeof(m_pfd));
3256	}
3257
3258	~CEnhMetaFileInfo()
3259	{
3260		delete [] m_pBits;
3261		delete [] m_pDesc;
3262	}
3263
3264// Operations
3265	BYTE* GetEnhMetaFileBits()
3266	{
3267		ATLASSERT(m_hEMF != NULL);
3268		UINT nBytes = ::GetEnhMetaFileBits(m_hEMF, 0, NULL);
3269		delete [] m_pBits;
3270		m_pBits = NULL;
3271		ATLTRY(m_pBits = new BYTE[nBytes]);
3272		if (m_pBits != NULL)
3273			::GetEnhMetaFileBits(m_hEMF, nBytes, m_pBits);
3274		return m_pBits;
3275	}
3276
3277	LPTSTR GetEnhMetaFileDescription()
3278	{
3279		ATLASSERT(m_hEMF != NULL);
3280		UINT nLen = ::GetEnhMetaFileDescription(m_hEMF, 0, NULL);
3281		delete [] m_pDesc;
3282		m_pDesc = NULL;
3283		ATLTRY(m_pDesc = new TCHAR[nLen]);
3284		if (m_pDesc != NULL)
3285			nLen = ::GetEnhMetaFileDescription(m_hEMF, nLen, m_pDesc);
3286		return m_pDesc;
3287	}
3288
3289	ENHMETAHEADER* GetEnhMetaFileHeader()
3290	{
3291		ATLASSERT(m_hEMF != NULL);
3292		memset(&m_header, 0, sizeof(m_header));
3293		m_header.iType = EMR_HEADER;
3294		m_header.nSize = sizeof(ENHMETAHEADER);
3295		UINT n = ::GetEnhMetaFileHeader(m_hEMF, sizeof(ENHMETAHEADER), &m_header);
3296		return (n != 0) ? &m_header : NULL;
3297	}
3298
3299	PIXELFORMATDESCRIPTOR* GetEnhMetaFilePixelFormat()
3300	{
3301		ATLASSERT(m_hEMF != NULL);
3302		memset(&m_pfd, 0, sizeof(m_pfd));
3303		UINT n = ::GetEnhMetaFilePixelFormat(m_hEMF, sizeof(m_pfd), &m_pfd);
3304		return (n != 0) ? &m_pfd : NULL;
3305	}
3306};
3307
3308
3309template <bool t_bManaged>
3310class CEnhMetaFileT
3311{
3312public:
3313// Data members
3314	HENHMETAFILE m_hEMF;
3315
3316// Constructor/destructor
3317	CEnhMetaFileT(HENHMETAFILE hEMF = NULL) : m_hEMF(hEMF)
3318	{
3319	}
3320
3321	~CEnhMetaFileT()
3322	{
3323		if(t_bManaged && (m_hEMF != NULL))
3324			DeleteObject();
3325	}
3326
3327// Operations
3328	CEnhMetaFileT<t_bManaged>& operator =(HENHMETAFILE hEMF)
3329	{
3330		Attach(hEMF);
3331		return *this;
3332	}
3333
3334	void Attach(HENHMETAFILE hEMF)
3335	{
3336		if(t_bManaged && (m_hEMF != NULL) && (m_hEMF != hEMF))
3337			DeleteObject();
3338		m_hEMF = hEMF;
3339	}
3340
3341	HENHMETAFILE Detach()
3342	{
3343		HENHMETAFILE hEMF = m_hEMF;
3344		m_hEMF = NULL;
3345		return hEMF;
3346	}
3347
3348	operator HENHMETAFILE() const { return m_hEMF; }
3349
3350	bool IsNull() const { return (m_hEMF == NULL); }
3351
3352	BOOL DeleteObject()
3353	{
3354		ATLASSERT(m_hEMF != NULL);
3355		BOOL bRet = ::DeleteEnhMetaFile(m_hEMF);
3356		m_hEMF = NULL;
3357		return bRet;
3358	}
3359
3360	UINT GetEnhMetaFileBits(UINT cbBuffer, LPBYTE lpbBuffer) const
3361	{
3362		ATLASSERT(m_hEMF != NULL);
3363		return ::GetEnhMetaFileBits(m_hEMF, cbBuffer, lpbBuffer);
3364	}
3365
3366	UINT GetEnhMetaFileDescription(UINT cchBuffer, LPTSTR lpszDescription) const
3367	{
3368		ATLASSERT(m_hEMF != NULL);
3369		return ::GetEnhMetaFileDescription(m_hEMF, cchBuffer, lpszDescription);
3370	}
3371
3372	UINT GetEnhMetaFileHeader(LPENHMETAHEADER lpemh) const
3373	{
3374		ATLASSERT(m_hEMF != NULL);
3375		lpemh->iType = EMR_HEADER;
3376		lpemh->nSize = sizeof(ENHMETAHEADER);
3377		return ::GetEnhMetaFileHeader(m_hEMF, sizeof(ENHMETAHEADER), lpemh);
3378	}
3379
3380	UINT GetEnhMetaFilePaletteEntries(UINT cEntries, LPPALETTEENTRY lppe) const
3381	{
3382		ATLASSERT(m_hEMF != NULL);
3383		return ::GetEnhMetaFilePaletteEntries(m_hEMF, cEntries, lppe);
3384	}
3385
3386	UINT GetEnhMetaFilePixelFormat(DWORD cbBuffer, PIXELFORMATDESCRIPTOR* ppfd) const
3387	{
3388		ATLASSERT(m_hEMF != NULL);
3389		return ::GetEnhMetaFilePixelFormat(m_hEMF, cbBuffer, ppfd);
3390	}
3391};
3392
3393typedef CEnhMetaFileT<false>   CEnhMetaFileHandle;
3394typedef CEnhMetaFileT<true>    CEnhMetaFile;
3395
3396
3397class CEnhMetaFileDC : public CDC
3398{
3399public:
3400// Constructor/destructor
3401	CEnhMetaFileDC()
3402	{
3403	}
3404
3405	CEnhMetaFileDC(HDC hdc, LPCRECT lpRect)
3406	{
3407		Create(hdc, NULL, lpRect, NULL);
3408		ATLASSERT(m_hDC != NULL);
3409	}
3410
3411	CEnhMetaFileDC(HDC hdcRef, LPCTSTR lpFilename, LPCRECT lpRect, LPCTSTR lpDescription)
3412	{
3413		Create(hdcRef, lpFilename, lpRect, lpDescription);
3414		ATLASSERT(m_hDC != NULL);
3415	}
3416
3417	~CEnhMetaFileDC()
3418	{
3419		HENHMETAFILE hEMF = Close();
3420		if (hEMF != NULL)
3421			::DeleteEnhMetaFile(hEMF);
3422	}
3423
3424// Operations
3425	void Create(HDC hdcRef, LPCTSTR lpFilename, LPCRECT lpRect, LPCTSTR lpDescription)
3426	{
3427		ATLASSERT(m_hDC == NULL);
3428		m_hDC = ::CreateEnhMetaFile(hdcRef, lpFilename, lpRect, lpDescription);
3429	}
3430
3431	HENHMETAFILE Close()
3432	{
3433		HENHMETAFILE hEMF = NULL;
3434		if (m_hDC != NULL)
3435		{
3436			hEMF = ::CloseEnhMetaFile(m_hDC);
3437			m_hDC = NULL;
3438		}
3439		return hEMF;
3440	}
3441};
3442
3443} // namespace WTL
3444
3445#endif // __ATLGDI_H__