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 
57 namespace WTL
58 {
59 
60 ///////////////////////////////////////////////////////////////////////////////
61 // Bitmap resource helpers to extract bitmap information for a bitmap resource
62 
AtlGetBitmapResourceInfo(HMODULE hModule,ATL::_U_STRINGorID image)63 inline 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 
AtlGetBitmapResourceBitsPerPixel(HMODULE hModule,ATL::_U_STRINGorID image)74 inline 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 
AtlGetBitmapResourceBitsPerPixel(ATL::_U_STRINGorID image)81 inline 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 
AtlIsAlphaBitmapResource(ATL::_U_STRINGorID image)93 inline bool AtlIsAlphaBitmapResource(ATL::_U_STRINGorID image)
94 {
95 	return (AtlGetBitmapResourceBitsPerPixel(image) == 32);
96 }
97 
98 
99 ///////////////////////////////////////////////////////////////////////////////
100 // CPen
101 
102 template <bool t_bManaged>
103 class CPenT
104 {
105 public:
106 // Data members
107 	HPEN m_hPen;
108 
109 // Constructor/destructor/operators
m_hPen(hPen)110 	CPenT(HPEN hPen = NULL) : m_hPen(hPen)
111 	{ }
112 
~CPenT()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 
Attach(HPEN hPen)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 
Detach()132 	HPEN Detach()
133 	{
134 		HPEN hPen = m_hPen;
135 		m_hPen = NULL;
136 		return hPen;
137 	}
138 
HPEN()139 	operator HPEN() const { return m_hPen; }
140 
IsNull()141 	bool IsNull() const { return (m_hPen == NULL); }
142 
143 // Create methods
CreatePen(int nPenStyle,int nWidth,COLORREF crColor)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 
CreatePenIndirect(LPLOGPEN lpLogPen)158 	HPEN CreatePenIndirect(LPLOGPEN lpLogPen)
159 	{
160 		ATLASSERT(m_hPen == NULL);
161 		m_hPen = ::CreatePenIndirect(lpLogPen);
162 		return m_hPen;
163 	}
164 
DeleteObject()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
GetLogPen(LOGPEN * pLogPen)175 	int GetLogPen(LOGPEN* pLogPen) const
176 	{
177 		ATLASSERT(m_hPen != NULL);
178 		return ::GetObject(m_hPen, sizeof(LOGPEN), pLogPen);
179 	}
180 
GetLogPen(LOGPEN & LogPen)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 
201 typedef CPenT<false>   CPenHandle;
202 typedef CPenT<true>    CPen;
203 
204 
205 ///////////////////////////////////////////////////////////////////////////////
206 // CBrush
207 
208 template <bool t_bManaged>
209 class CBrushT
210 {
211 public:
212 // Data members
213 	HBRUSH m_hBrush;
214 
215 // Constructor/destructor/operators
m_hBrush(hBrush)216 	CBrushT(HBRUSH hBrush = NULL) : m_hBrush(hBrush)
217 	{ }
218 
~CBrushT()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 
Attach(HBRUSH hBrush)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 
Detach()238 	HBRUSH Detach()
239 	{
240 		HBRUSH hBrush = m_hBrush;
241 		m_hBrush = NULL;
242 		return hBrush;
243 	}
244 
HBRUSH()245 	operator HBRUSH() const { return m_hBrush; }
246 
IsNull()247 	bool IsNull() const { return (m_hBrush == NULL); }
248 
249 // Create methods
CreateSolidBrush(COLORREF crColor)250 	HBRUSH CreateSolidBrush(COLORREF crColor)
251 	{
252 		ATLASSERT(m_hBrush == NULL);
253 		m_hBrush = ::CreateSolidBrush(crColor);
254 		return m_hBrush;
255 	}
256 
CreateHatchBrush(int nIndex,COLORREF crColor)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 
CreateBrushIndirect(const LOGBRUSH * lpLogBrush)264 	HBRUSH CreateBrushIndirect(const LOGBRUSH* lpLogBrush)
265 	{
266 		ATLASSERT(m_hBrush == NULL);
267 		m_hBrush = ::CreateBrushIndirect(lpLogBrush);
268 		return m_hBrush;
269 	}
270 
CreatePatternBrush(HBITMAP hBitmap)271 	HBRUSH CreatePatternBrush(HBITMAP hBitmap)
272 	{
273 		ATLASSERT(m_hBrush == NULL);
274 		m_hBrush = ::CreatePatternBrush(hBitmap);
275 		return m_hBrush;
276 	}
277 
CreateDIBPatternBrush(HGLOBAL hPackedDIB,UINT nUsage)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 
CreateDIBPatternBrush(const void * lpPackedDIB,UINT nUsage)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 
CreateSysColorBrush(int nIndex)295 	HBRUSH CreateSysColorBrush(int nIndex)
296 	{
297 		ATLASSERT(m_hBrush == NULL);
298 		m_hBrush = ::GetSysColorBrush(nIndex);
299 		return m_hBrush;
300 	}
301 
DeleteObject()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
GetLogBrush(LOGBRUSH * pLogBrush)312 	int GetLogBrush(LOGBRUSH* pLogBrush) const
313 	{
314 		ATLASSERT(m_hBrush != NULL);
315 		return ::GetObject(m_hBrush, sizeof(LOGBRUSH), pLogBrush);
316 	}
317 
GetLogBrush(LOGBRUSH & LogBrush)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 
325 typedef CBrushT<false>   CBrushHandle;
326 typedef CBrushT<true>    CBrush;
327 
328 
329 ///////////////////////////////////////////////////////////////////////////////
330 // CFont
331 
332 class CLogFont : public LOGFONT
333 {
334 public:
CLogFont()335 	CLogFont()
336 	{
337 		memset(this, 0, sizeof(LOGFONT));
338 	}
339 
CLogFont(const LOGFONT & lf)340 	CLogFont(const LOGFONT& lf)
341 	{
342 		Copy(&lf);
343 	}
344 
CLogFont(HFONT hFont)345 	CLogFont(HFONT hFont)
346 	{
347 		ATLASSERT(::GetObjectType(hFont) == OBJ_FONT);
348 		::GetObject(hFont, sizeof(LOGFONT), (LOGFONT*)this);
349 	}
350 
CreateFontIndirect()351 	HFONT CreateFontIndirect()
352 	{
353 		return ::CreateFontIndirect(this);
354 	}
355 
SetBold()356 	void SetBold()
357 	{
358 		lfWeight = FW_BOLD;
359 	}
360 
IsBold()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 
MakeLarger(int iScale)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 
SetCaptionFont()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 
SetMenuFont()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 
SetStatusFont()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 
SetMessageBoxFont()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 
Copy(const LOGFONT * pLogFont)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 
500 template <bool t_bManaged>
501 class CFontT
502 {
503 public:
504 // Data members
505 	HFONT m_hFont;
506 
507 // Constructor/destructor/operators
m_hFont(hFont)508 	CFontT(HFONT hFont = NULL) : m_hFont(hFont)
509 	{ }
510 
~CFontT()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 
Attach(HFONT hFont)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 
Detach()530 	HFONT Detach()
531 	{
532 		HFONT hFont = m_hFont;
533 		m_hFont = NULL;
534 		return hFont;
535 	}
536 
HFONT()537 	operator HFONT() const { return m_hFont; }
538 
IsNull()539 	bool IsNull() const { return (m_hFont == NULL); }
540 
541 // Create methods
CreateFontIndirect(const LOGFONT * lpLogFont)542 	HFONT CreateFontIndirect(const LOGFONT* lpLogFont)
543 	{
544 		ATLASSERT(m_hFont == NULL);
545 		m_hFont = ::CreateFontIndirect(lpLogFont);
546 		return m_hFont;
547 	}
548 
CreateFontIndirectEx(CONST ENUMLOGFONTEXDV * penumlfex)549 	HFONT CreateFontIndirectEx(CONST ENUMLOGFONTEXDV* penumlfex)
550 	{
551 		ATLASSERT(m_hFont == NULL);
552 		m_hFont = ::CreateFontIndirectEx(penumlfex);
553 		return m_hFont;
554 	}
555 
CreateFont(int nHeight,int nWidth,int nEscapement,int nOrientation,int nWeight,BYTE bItalic,BYTE bUnderline,BYTE cStrikeOut,BYTE nCharSet,BYTE nOutPrecision,BYTE nClipPrecision,BYTE nQuality,BYTE nPitchAndFamily,LPCTSTR lpszFacename)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 
DeleteObject()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
GetLogFont(LOGFONT * pLogFont)614 	int GetLogFont(LOGFONT* pLogFont) const
615 	{
616 		ATLASSERT(m_hFont != NULL);
617 		return ::GetObject(m_hFont, sizeof(LOGFONT), pLogFont);
618 	}
619 
GetLogFont(LOGFONT & LogFont)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 
627 typedef CFontT<false>   CFontHandle;
628 typedef CFontT<true>    CFont;
629 
630 
631 ///////////////////////////////////////////////////////////////////////////////
632 // CBitmap
633 
634 template <bool t_bManaged>
635 class CBitmapT
636 {
637 public:
638 // Data members
639 	HBITMAP m_hBitmap;
640 
641 // Constructor/destructor/operators
m_hBitmap(hBitmap)642 	CBitmapT(HBITMAP hBitmap = NULL) : m_hBitmap(hBitmap)
643 	{ }
644 
~CBitmapT()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 
Attach(HBITMAP hBitmap)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 
Detach()664 	HBITMAP Detach()
665 	{
666 		HBITMAP hBitmap = m_hBitmap;
667 		m_hBitmap = NULL;
668 		return hBitmap;
669 	}
670 
HBITMAP()671 	operator HBITMAP() const { return m_hBitmap; }
672 
IsNull()673 	bool IsNull() const { return (m_hBitmap == NULL); }
674 
675 // Create and load methods
LoadBitmap(ATL::_U_STRINGorID bitmap)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 
LoadOEMBitmap(UINT nIDBitmap)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 
CreateBitmap(int nWidth,int nHeight,UINT nPlanes,UINT nBitsPerPixel,const void * lpBits)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 
CreateBitmapIndirect(LPBITMAP lpBitmap)704 	HBITMAP CreateBitmapIndirect(LPBITMAP lpBitmap)
705 	{
706 		ATLASSERT(m_hBitmap == NULL);
707 		m_hBitmap = ::CreateBitmapIndirect(lpBitmap);
708 		return m_hBitmap;
709 	}
710 
CreateCompatibleBitmap(HDC hDC,int nWidth,int nHeight)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 
CreateDiscardableBitmap(HDC hDC,int nWidth,int nHeight)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 
DeleteObject()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
GetBitmap(BITMAP * pBitMap)735 	int GetBitmap(BITMAP* pBitMap) const
736 	{
737 		ATLASSERT(m_hBitmap != NULL);
738 		return ::GetObject(m_hBitmap, sizeof(BITMAP), pBitMap);
739 	}
740 
GetBitmap(BITMAP & bm)741 	bool GetBitmap(BITMAP& bm) const
742 	{
743 		ATLASSERT(m_hBitmap != NULL);
744 		return (::GetObject(m_hBitmap, sizeof(BITMAP), &bm) == sizeof(BITMAP));
745 	}
746 
GetSize(SIZE & size)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 
GetBitmapBits(DWORD dwCount,LPVOID lpBits)758 	DWORD GetBitmapBits(DWORD dwCount, LPVOID lpBits) const
759 	{
760 		ATLASSERT(m_hBitmap != NULL);
761 		return ::GetBitmapBits(m_hBitmap, dwCount, lpBits);
762 	}
763 
SetBitmapBits(DWORD dwCount,const void * lpBits)764 	DWORD SetBitmapBits(DWORD dwCount, const void* lpBits)
765 	{
766 		ATLASSERT(m_hBitmap != NULL);
767 		return ::SetBitmapBits(m_hBitmap, dwCount, lpBits);
768 	}
769 
GetBitmapDimension(LPSIZE lpSize)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
CreateDIBitmap(HDC hDC,CONST BITMAPINFOHEADER * lpbmih,DWORD dwInit,CONST VOID * lpbInit,CONST BITMAPINFO * lpbmi,UINT uColorUse)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 
CreateDIBSection(HDC hDC,CONST BITMAPINFO * lpbmi,UINT uColorUse,VOID ** ppvBits,HANDLE hSection,DWORD dwOffset)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 
GetDIBits(HDC hDC,UINT uStartScan,UINT cScanLines,LPVOID lpvBits,LPBITMAPINFO lpbmi,UINT uColorUse)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 
SetDIBits(HDC hDC,UINT uStartScan,UINT cScanLines,CONST VOID * lpvBits,CONST BITMAPINFO * lpbmi,UINT uColorUse)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 
810 typedef CBitmapT<false>   CBitmapHandle;
811 typedef CBitmapT<true>    CBitmap;
812 
813 
814 ///////////////////////////////////////////////////////////////////////////////
815 // CPalette
816 
817 template <bool t_bManaged>
818 class CPaletteT
819 {
820 public:
821 // Data members
822 	HPALETTE m_hPalette;
823 
824 // Constructor/destructor/operators
m_hPalette(hPalette)825 	CPaletteT(HPALETTE hPalette = NULL) : m_hPalette(hPalette)
826 	{ }
827 
~CPaletteT()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 
Attach(HPALETTE hPalette)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 
Detach()847 	HPALETTE Detach()
848 	{
849 		HPALETTE hPalette = m_hPalette;
850 		m_hPalette = NULL;
851 		return hPalette;
852 	}
853 
HPALETTE()854 	operator HPALETTE() const { return m_hPalette; }
855 
IsNull()856 	bool IsNull() const { return (m_hPalette == NULL); }
857 
858 // Create methods
CreatePalette(LPLOGPALETTE lpLogPalette)859 	HPALETTE CreatePalette(LPLOGPALETTE lpLogPalette)
860 	{
861 		ATLASSERT(m_hPalette == NULL);
862 		m_hPalette = ::CreatePalette(lpLogPalette);
863 		return m_hPalette;
864 	}
865 
CreateHalftonePalette(HDC hDC)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 
DeleteObject()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
GetEntryCount()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 
GetPaletteEntries(UINT nStartIndex,UINT nNumEntries,LPPALETTEENTRY lpPaletteColors)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 
SetPaletteEntries(UINT nStartIndex,UINT nNumEntries,LPPALETTEENTRY lpPaletteColors)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
AnimatePalette(UINT nStartIndex,UINT nNumEntries,LPPALETTEENTRY lpPaletteColors)905 	void AnimatePalette(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors)
906 	{
907 		ATLASSERT(m_hPalette != NULL);
908 		::AnimatePalette(m_hPalette, nStartIndex, nNumEntries, lpPaletteColors);
909 	}
910 
ResizePalette(UINT nNumEntries)911 	BOOL ResizePalette(UINT nNumEntries)
912 	{
913 		ATLASSERT(m_hPalette != NULL);
914 		return ::ResizePalette(m_hPalette, nNumEntries);
915 	}
916 
GetNearestPaletteIndex(COLORREF crColor)917 	UINT GetNearestPaletteIndex(COLORREF crColor) const
918 	{
919 		ATLASSERT(m_hPalette != NULL);
920 		return ::GetNearestPaletteIndex(m_hPalette, crColor);
921 	}
922 };
923 
924 typedef CPaletteT<false>   CPaletteHandle;
925 typedef CPaletteT<true>    CPalette;
926 
927 
928 ///////////////////////////////////////////////////////////////////////////////
929 // CRgn
930 
931 template <bool t_bManaged>
932 class CRgnT
933 {
934 public:
935 // Data members
936 	HRGN m_hRgn;
937 
938 // Constructor/destructor/operators
m_hRgn(hRgn)939 	CRgnT(HRGN hRgn = NULL) : m_hRgn(hRgn)
940 	{ }
941 
~CRgnT()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 
Attach(HRGN hRgn)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 
Detach()961 	HRGN Detach()
962 	{
963 		HRGN hRgn = m_hRgn;
964 		m_hRgn = NULL;
965 		return hRgn;
966 	}
967 
HRGN()968 	operator HRGN() const { return m_hRgn; }
969 
IsNull()970 	bool IsNull() const { return (m_hRgn == NULL); }
971 
972 // Create methods
CreateRectRgn(int x1,int y1,int x2,int y2)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 
CreateRectRgnIndirect(LPCRECT lpRect)980 	HRGN CreateRectRgnIndirect(LPCRECT lpRect)
981 	{
982 		ATLASSERT(m_hRgn == NULL);
983 		m_hRgn = ::CreateRectRgnIndirect(lpRect);
984 		return m_hRgn;
985 	}
986 
CreateEllipticRgn(int x1,int y1,int x2,int y2)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 
CreateEllipticRgnIndirect(LPCRECT lpRect)994 	HRGN CreateEllipticRgnIndirect(LPCRECT lpRect)
995 	{
996 		ATLASSERT(m_hRgn == NULL);
997 		m_hRgn = ::CreateEllipticRgnIndirect(lpRect);
998 		return m_hRgn;
999 	}
1000 
CreatePolygonRgn(const POINT * lpPoints,int nCount,int nMode)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 
CreatePolyPolygonRgn(const POINT * lpPoints,const INT * lpPolyCounts,int nCount,int nPolyFillMode)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 
CreateRoundRectRgn(int x1,int y1,int x2,int y2,int x3,int y3)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 
CreateFromPath(HDC hDC)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 
CreateFromData(const XFORM * lpXForm,int nCount,const RGNDATA * pRgnData)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 
DeleteObject()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
SetRectRgn(int x1,int y1,int x2,int y2)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 
SetRectRgn(LPCRECT lpRect)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 
CombineRgn(HRGN hRgnSrc1,HRGN hRgnSrc2,int nCombineMode)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 
CombineRgn(HRGN hRgnSrc,int nCombineMode)1065 	int CombineRgn(HRGN hRgnSrc, int nCombineMode)
1066 	{
1067 		ATLASSERT(m_hRgn != NULL);
1068 		return ::CombineRgn(m_hRgn, m_hRgn, hRgnSrc, nCombineMode);
1069 	}
1070 
CopyRgn(HRGN hRgnSrc)1071 	int CopyRgn(HRGN hRgnSrc)
1072 	{
1073 		ATLASSERT(m_hRgn != NULL);
1074 		return ::CombineRgn(m_hRgn, hRgnSrc, NULL, RGN_COPY);
1075 	}
1076 
EqualRgn(HRGN hRgn)1077 	BOOL EqualRgn(HRGN hRgn) const
1078 	{
1079 		ATLASSERT(m_hRgn != NULL);
1080 		return ::EqualRgn(m_hRgn, hRgn);
1081 	}
1082 
OffsetRgn(int x,int y)1083 	int OffsetRgn(int x, int y)
1084 	{
1085 		ATLASSERT(m_hRgn != NULL);
1086 		return ::OffsetRgn(m_hRgn, x, y);
1087 	}
1088 
OffsetRgn(POINT point)1089 	int OffsetRgn(POINT point)
1090 	{
1091 		ATLASSERT(m_hRgn != NULL);
1092 		return ::OffsetRgn(m_hRgn, point.x, point.y);
1093 	}
1094 
GetRgnBox(LPRECT lpRect)1095 	int GetRgnBox(LPRECT lpRect) const
1096 	{
1097 		ATLASSERT(m_hRgn != NULL);
1098 		return ::GetRgnBox(m_hRgn, lpRect);
1099 	}
1100 
PtInRegion(int x,int y)1101 	BOOL PtInRegion(int x, int y) const
1102 	{
1103 		ATLASSERT(m_hRgn != NULL);
1104 		return ::PtInRegion(m_hRgn, x, y);
1105 	}
1106 
PtInRegion(POINT point)1107 	BOOL PtInRegion(POINT point) const
1108 	{
1109 		ATLASSERT(m_hRgn != NULL);
1110 		return ::PtInRegion(m_hRgn, point.x, point.y);
1111 	}
1112 
RectInRegion(LPCRECT lpRect)1113 	BOOL RectInRegion(LPCRECT lpRect) const
1114 	{
1115 		ATLASSERT(m_hRgn != NULL);
1116 		return ::RectInRegion(m_hRgn, lpRect);
1117 	}
1118 
GetRegionData(LPRGNDATA lpRgnData,int nDataSize)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 
1126 typedef CRgnT<false>   CRgnHandle;
1127 typedef CRgnT<true>    CRgn;
1128 
1129 
1130 ///////////////////////////////////////////////////////////////////////////////
1131 // CDC - The device context class
1132 
1133 template <bool t_bManaged>
1134 class CDCT;
1135 typedef CDCT<false>   CDCHandle;
1136 typedef CDCT<true>    CDC;
1137 
1138 template <bool t_bManaged>
1139 class CDCT
1140 {
1141 public:
1142 // Data members
1143 	HDC m_hDC;
1144 
1145 // Constructor/destructor/operators
m_hDC(hDC)1146 	CDCT(HDC hDC = NULL) : m_hDC(hDC)
1147 	{
1148 	}
1149 
~CDCT()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 
Attach(HDC hDC)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 
Detach()1169 	HDC Detach()
1170 	{
1171 		HDC hDC = m_hDC;
1172 		m_hDC = NULL;
1173 		return hDC;
1174 	}
1175 
HDC()1176 	operator HDC() const { return m_hDC; }
1177 
IsNull()1178 	bool IsNull() const { return (m_hDC == NULL); }
1179 
1180 // Operations
WindowFromDC()1181 	HWND WindowFromDC() const
1182 	{
1183 		ATLASSERT(m_hDC != NULL);
1184 		return ::WindowFromDC(m_hDC);
1185 	}
1186 
GetCurrentPen()1187 	CPenHandle GetCurrentPen() const
1188 	{
1189 		ATLASSERT(m_hDC != NULL);
1190 		return CPenHandle((HPEN)::GetCurrentObject(m_hDC, OBJ_PEN));
1191 	}
1192 
GetCurrentBrush()1193 	CBrushHandle GetCurrentBrush() const
1194 	{
1195 		ATLASSERT(m_hDC != NULL);
1196 		return CBrushHandle((HBRUSH)::GetCurrentObject(m_hDC, OBJ_BRUSH));
1197 	}
1198 
GetCurrentPalette()1199 	CPaletteHandle GetCurrentPalette() const
1200 	{
1201 		ATLASSERT(m_hDC != NULL);
1202 		return CPaletteHandle((HPALETTE)::GetCurrentObject(m_hDC, OBJ_PAL));
1203 	}
1204 
GetCurrentFont()1205 	CFontHandle GetCurrentFont() const
1206 	{
1207 		ATLASSERT(m_hDC != NULL);
1208 		return CFontHandle((HFONT)::GetCurrentObject(m_hDC, OBJ_FONT));
1209 	}
1210 
GetCurrentBitmap()1211 	CBitmapHandle GetCurrentBitmap() const
1212 	{
1213 		ATLASSERT(m_hDC != NULL);
1214 		return CBitmapHandle((HBITMAP)::GetCurrentObject(m_hDC, OBJ_BITMAP));
1215 	}
1216 
CreateDC(LPCTSTR lpszDriverName,LPCTSTR lpszDeviceName,LPCTSTR lpszOutput,const DEVMODE * lpInitData)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 
DeleteDC()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
SaveDC()1242 	int SaveDC()
1243 	{
1244 		ATLASSERT(m_hDC != NULL);
1245 		return ::SaveDC(m_hDC);
1246 	}
1247 
RestoreDC(int nSavedDC)1248 	BOOL RestoreDC(int nSavedDC)
1249 	{
1250 		ATLASSERT(m_hDC != NULL);
1251 		return ::RestoreDC(m_hDC, nSavedDC);
1252 	}
1253 
GetDeviceCaps(int nIndex)1254 	int GetDeviceCaps(int nIndex) const
1255 	{
1256 		ATLASSERT(m_hDC != NULL);
1257 		return ::GetDeviceCaps(m_hDC, nIndex);
1258 	}
1259 
SetBoundsRect(LPCRECT lpRectBounds,UINT flags)1260 	UINT SetBoundsRect(LPCRECT lpRectBounds, UINT flags)
1261 	{
1262 		ATLASSERT(m_hDC != NULL);
1263 		return ::SetBoundsRect(m_hDC, lpRectBounds, flags);
1264 	}
1265 
GetBoundsRect(LPRECT lpRectBounds,UINT flags)1266 	UINT GetBoundsRect(LPRECT lpRectBounds, UINT flags) const
1267 	{
1268 		ATLASSERT(m_hDC != NULL);
1269 		return ::GetBoundsRect(m_hDC, lpRectBounds, flags);
1270 	}
1271 
ResetDC(const DEVMODE * lpDevMode)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
GetBrushOrg(LPPOINT lpPoint)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 
EnumObjects(int nObjectType,int (CALLBACK * lpfn)(LPVOID,LPARAM),LPARAM lpData)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
SelectPen(HPEN hPen)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 
SelectBrush(HBRUSH hBrush)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 
SelectFont(HFONT hFont)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 
SelectBitmap(HBITMAP hBitmap)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 
SelectRgn(HRGN hRgn)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
SelectStockPen(int nPen)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 
SelectStockBrush(int nBrush)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 
SelectStockFont(int nFont)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 
SelectStockPalette(int nPalette,BOOL bForceBackground)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
GetNearestColor(COLORREF crColor)1370 	COLORREF GetNearestColor(COLORREF crColor) const
1371 	{
1372 		ATLASSERT(m_hDC != NULL);
1373 		return ::GetNearestColor(m_hDC, crColor);
1374 	}
1375 
SelectPalette(HPALETTE hPalette,BOOL bForceBackground)1376 	HPALETTE SelectPalette(HPALETTE hPalette, BOOL bForceBackground)
1377 	{
1378 		ATLASSERT(m_hDC != NULL);
1379 
1380 		return ::SelectPalette(m_hDC, hPalette, bForceBackground);
1381 	}
1382 
RealizePalette()1383 	UINT RealizePalette()
1384 	{
1385 		ATLASSERT(m_hDC != NULL);
1386 		return ::RealizePalette(m_hDC);
1387 	}
1388 
UpdateColors()1389 	void UpdateColors()
1390 	{
1391 		ATLASSERT(m_hDC != NULL);
1392 		::UpdateColors(m_hDC);
1393 	}
1394 
1395 // Drawing-Attribute Functions
GetBkColor()1396 	COLORREF GetBkColor() const
1397 	{
1398 		ATLASSERT(m_hDC != NULL);
1399 		return ::GetBkColor(m_hDC);
1400 	}
1401 
GetBkMode()1402 	int GetBkMode() const
1403 	{
1404 		ATLASSERT(m_hDC != NULL);
1405 		return ::GetBkMode(m_hDC);
1406 	}
1407 
GetPolyFillMode()1408 	int GetPolyFillMode() const
1409 	{
1410 		ATLASSERT(m_hDC != NULL);
1411 		return ::GetPolyFillMode(m_hDC);
1412 	}
1413 
GetROP2()1414 	int GetROP2() const
1415 	{
1416 		ATLASSERT(m_hDC != NULL);
1417 		return ::GetROP2(m_hDC);
1418 	}
1419 
GetStretchBltMode()1420 	int GetStretchBltMode() const
1421 	{
1422 		ATLASSERT(m_hDC != NULL);
1423 		return ::GetStretchBltMode(m_hDC);
1424 	}
1425 
GetTextColor()1426 	COLORREF GetTextColor() const
1427 	{
1428 		ATLASSERT(m_hDC != NULL);
1429 		return ::GetTextColor(m_hDC);
1430 	}
1431 
SetBkColor(COLORREF crColor)1432 	COLORREF SetBkColor(COLORREF crColor)
1433 	{
1434 		ATLASSERT(m_hDC != NULL);
1435 		return ::SetBkColor(m_hDC, crColor);
1436 	}
1437 
SetBkMode(int nBkMode)1438 	int SetBkMode(int nBkMode)
1439 	{
1440 		ATLASSERT(m_hDC != NULL);
1441 		return ::SetBkMode(m_hDC, nBkMode);
1442 	}
1443 
SetPolyFillMode(int nPolyFillMode)1444 	int SetPolyFillMode(int nPolyFillMode)
1445 	{
1446 		ATLASSERT(m_hDC != NULL);
1447 		return ::SetPolyFillMode(m_hDC, nPolyFillMode);
1448 	}
1449 
SetROP2(int nDrawMode)1450 	int SetROP2(int nDrawMode)
1451 	{
1452 		ATLASSERT(m_hDC != NULL);
1453 		return ::SetROP2(m_hDC, nDrawMode);
1454 	}
1455 
SetStretchBltMode(int nStretchMode)1456 	int SetStretchBltMode(int nStretchMode)
1457 	{
1458 		ATLASSERT(m_hDC != NULL);
1459 		return ::SetStretchBltMode(m_hDC, nStretchMode);
1460 	}
1461 
SetTextColor(COLORREF crColor)1462 	COLORREF SetTextColor(COLORREF crColor)
1463 	{
1464 		ATLASSERT(m_hDC != NULL);
1465 		return ::SetTextColor(m_hDC, crColor);
1466 	}
1467 
GetColorAdjustment(LPCOLORADJUSTMENT lpColorAdjust)1468 	BOOL GetColorAdjustment(LPCOLORADJUSTMENT lpColorAdjust) const
1469 	{
1470 		ATLASSERT(m_hDC != NULL);
1471 		return ::GetColorAdjustment(m_hDC, lpColorAdjust);
1472 	}
1473 
SetColorAdjustment(const COLORADJUSTMENT * lpColorAdjust)1474 	BOOL SetColorAdjustment(const COLORADJUSTMENT* lpColorAdjust)
1475 	{
1476 		ATLASSERT(m_hDC != NULL);
1477 		return ::SetColorAdjustment(m_hDC, lpColorAdjust);
1478 	}
1479 
1480 // Mapping Functions
GetMapMode()1481 	int GetMapMode() const
1482 	{
1483 		ATLASSERT(m_hDC != NULL);
1484 		return ::GetMapMode(m_hDC);
1485 	}
1486 
GetViewportOrg(LPPOINT lpPoint)1487 	BOOL GetViewportOrg(LPPOINT lpPoint) const
1488 	{
1489 		ATLASSERT(m_hDC != NULL);
1490 		return ::GetViewportOrgEx(m_hDC, lpPoint);
1491 	}
1492 
SetMapMode(int nMapMode)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
GetViewportExt(LPSIZE lpSize)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
GetWindowOrg(LPPOINT lpPoint)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
GetWindowExt(LPSIZE lpSize)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 
DPtoLP(LPRECT lpRect)1600 	BOOL DPtoLP(LPRECT lpRect) const
1601 	{
1602 		ATLASSERT(m_hDC != NULL);
1603 		return ::DPtoLP(m_hDC, (LPPOINT)lpRect, 2);
1604 	}
1605 
DPtoLP(LPSIZE lpSize)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 
LPtoDP(LPRECT lpRect)1625 	BOOL LPtoDP(LPRECT lpRect) const
1626 	{
1627 		ATLASSERT(m_hDC != NULL);
1628 		return ::LPtoDP(m_hDC, (LPPOINT)lpRect, 2);
1629 	}
1630 
LPtoDP(LPSIZE lpSize)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 
DPtoHIMETRIC(LPSIZE lpSize)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 
HIMETRICtoDP(LPSIZE lpSize)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 
LPtoHIMETRIC(LPSIZE lpSize)1691 	void LPtoHIMETRIC(LPSIZE lpSize)
1692 	{
1693 		LPtoDP(lpSize);
1694 		DPtoHIMETRIC(lpSize);
1695 	}
1696 
HIMETRICtoLP(LPSIZE lpSize)1697 	void HIMETRICtoLP(LPSIZE lpSize)
1698 	{
1699 		HIMETRICtoDP(lpSize);
1700 		DPtoLP(lpSize);
1701 	}
1702 
1703 // Region Functions
FillRgn(HRGN hRgn,HBRUSH hBrush)1704 	BOOL FillRgn(HRGN hRgn, HBRUSH hBrush)
1705 	{
1706 		ATLASSERT(m_hDC != NULL);
1707 		return ::FillRgn(m_hDC, hRgn, hBrush);
1708 	}
1709 
FrameRgn(HRGN hRgn,HBRUSH hBrush,int nWidth,int nHeight)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 
InvertRgn(HRGN hRgn)1716 	BOOL InvertRgn(HRGN hRgn)
1717 	{
1718 		ATLASSERT(m_hDC != NULL);
1719 		return ::InvertRgn(m_hDC, hRgn);
1720 	}
1721 
PaintRgn(HRGN hRgn)1722 	BOOL PaintRgn(HRGN hRgn)
1723 	{
1724 		ATLASSERT(m_hDC != NULL);
1725 		return ::PaintRgn(m_hDC, hRgn);
1726 	}
1727 
1728 // Clipping Functions
GetClipBox(LPRECT lpRect)1729 	int GetClipBox(LPRECT lpRect) const
1730 	{
1731 		ATLASSERT(m_hDC != NULL);
1732 		return ::GetClipBox(m_hDC, lpRect);
1733 	}
1734 
GetClipRgn(CRgn & region)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 
PtVisible(int x,int y)1748 	BOOL PtVisible(int x, int y) const
1749 	{
1750 		ATLASSERT(m_hDC != NULL);
1751 		return ::PtVisible(m_hDC, x, y);
1752 	}
1753 
PtVisible(POINT point)1754 	BOOL PtVisible(POINT point) const
1755 	{
1756 		ATLASSERT(m_hDC != NULL);
1757 		return ::PtVisible(m_hDC, point.x, point.y);
1758 	}
1759 
RectVisible(LPCRECT lpRect)1760 	BOOL RectVisible(LPCRECT lpRect) const
1761 	{
1762 		ATLASSERT(m_hDC != NULL);
1763 		return ::RectVisible(m_hDC, lpRect);
1764 	}
1765 
SelectClipRgn(HRGN hRgn)1766 	int SelectClipRgn(HRGN hRgn)
1767 	{
1768 		ATLASSERT(m_hDC != NULL);
1769 		return ::SelectClipRgn(m_hDC, (HRGN)hRgn);
1770 	}
1771 
ExcludeClipRect(int x1,int y1,int x2,int y2)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 
ExcludeClipRect(LPCRECT lpRect)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 
ExcludeUpdateRgn(HWND hWnd)1784 	int ExcludeUpdateRgn(HWND hWnd)
1785 	{
1786 		ATLASSERT(m_hDC != NULL);
1787 		return ::ExcludeUpdateRgn(m_hDC, hWnd);
1788 	}
1789 
IntersectClipRect(int x1,int y1,int x2,int y2)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 
IntersectClipRect(LPCRECT lpRect)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 
OffsetClipRgn(int x,int y)1802 	int OffsetClipRgn(int x, int y)
1803 	{
1804 		ATLASSERT(m_hDC != NULL);
1805 		return ::OffsetClipRgn(m_hDC, x, y);
1806 	}
1807 
OffsetClipRgn(SIZE size)1808 	int OffsetClipRgn(SIZE size)
1809 	{
1810 		ATLASSERT(m_hDC != NULL);
1811 		return ::OffsetClipRgn(m_hDC, size.cx, size.cy);
1812 	}
1813 
SelectClipRgn(HRGN hRgn,int nMode)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
GetCurrentPosition(LPPOINT lpPoint)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 
LineTo(int x,int y)1839 	BOOL LineTo(int x, int y)
1840 	{
1841 		ATLASSERT(m_hDC != NULL);
1842 		return ::LineTo(m_hDC, x, y);
1843 	}
1844 
LineTo(POINT point)1845 	BOOL LineTo(POINT point)
1846 	{
1847 		ATLASSERT(m_hDC != NULL);
1848 		return LineTo(point.x, point.y);
1849 	}
1850 
Arc(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4)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 
Arc(LPCRECT lpRect,POINT ptStart,POINT ptEnd)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 
Polyline(const POINT * lpPoints,int nCount)1865 	BOOL Polyline(const POINT* lpPoints, int nCount)
1866 	{
1867 		ATLASSERT(m_hDC != NULL);
1868 		return ::Polyline(m_hDC, lpPoints, nCount);
1869 	}
1870 
AngleArc(int x,int y,int nRadius,float fStartAngle,float fSweepAngle)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 
ArcTo(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4)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 
ArcTo(LPCRECT lpRect,POINT ptStart,POINT ptEnd)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 
GetArcDirection()1890 	int GetArcDirection() const
1891 	{
1892 		ATLASSERT(m_hDC != NULL);
1893 		return ::GetArcDirection(m_hDC);
1894 	}
1895 
SetArcDirection(int nArcDirection)1896 	int SetArcDirection(int nArcDirection)
1897 	{
1898 		ATLASSERT(m_hDC != NULL);
1899 		return ::SetArcDirection(m_hDC, nArcDirection);
1900 	}
1901 
PolyDraw(const POINT * lpPoints,const BYTE * lpTypes,int nCount)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 
PolylineTo(const POINT * lpPoints,int nCount)1908 	BOOL PolylineTo(const POINT* lpPoints, int nCount)
1909 	{
1910 		ATLASSERT(m_hDC != NULL);
1911 		return ::PolylineTo(m_hDC, lpPoints, nCount);
1912 	}
1913 
PolyPolyline(const POINT * lpPoints,const DWORD * lpPolyPoints,int nCount)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 
PolyBezier(const POINT * lpPoints,int nCount)1921 	BOOL PolyBezier(const POINT* lpPoints, int nCount)
1922 	{
1923 		ATLASSERT(m_hDC != NULL);
1924 		return ::PolyBezier(m_hDC, lpPoints, nCount);
1925 	}
1926 
PolyBezierTo(const POINT * lpPoints,int nCount)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
FillRect(LPCRECT lpRect,HBRUSH hBrush)1934 	BOOL FillRect(LPCRECT lpRect, HBRUSH hBrush)
1935 	{
1936 		ATLASSERT(m_hDC != NULL);
1937 		return ::FillRect(m_hDC, lpRect, hBrush);
1938 	}
1939 
FillRect(LPCRECT lpRect,int nColorIndex)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 
FrameRect(LPCRECT lpRect,HBRUSH hBrush)1946 	BOOL FrameRect(LPCRECT lpRect, HBRUSH hBrush)
1947 	{
1948 		ATLASSERT(m_hDC != NULL);
1949 		return ::FrameRect(m_hDC, lpRect, hBrush);
1950 	}
1951 
InvertRect(LPCRECT lpRect)1952 	BOOL InvertRect(LPCRECT lpRect)
1953 	{
1954 		ATLASSERT(m_hDC != NULL);
1955 		return ::InvertRect(m_hDC, lpRect);
1956 	}
1957 
DrawIcon(int x,int y,HICON hIcon)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 
DrawIcon(POINT point,HICON hIcon)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
Chord(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4)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 
Chord(LPCRECT lpRect,POINT ptStart,POINT ptEnd)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 
DrawFocusRect(LPCRECT lpRect)2019 	void DrawFocusRect(LPCRECT lpRect)
2020 	{
2021 		ATLASSERT(m_hDC != NULL);
2022 		::DrawFocusRect(m_hDC, lpRect);
2023 	}
2024 
Ellipse(int x1,int y1,int x2,int y2)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 
Ellipse(LPCRECT lpRect)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 
Pie(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4)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 
Pie(LPCRECT lpRect,POINT ptStart,POINT ptEnd)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 
Polygon(const POINT * lpPoints,int nCount)2049 	BOOL Polygon(const POINT* lpPoints, int nCount)
2050 	{
2051 		ATLASSERT(m_hDC != NULL);
2052 		return ::Polygon(m_hDC, lpPoints, nCount);
2053 	}
2054 
PolyPolygon(const POINT * lpPoints,const INT * lpPolyCounts,int nCount)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 
Rectangle(int x1,int y1,int x2,int y2)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 
Rectangle(LPCRECT lpRect)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 
RoundRect(int x1,int y1,int x2,int y2,int x3,int y3)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 
RoundRect(LPCRECT lpRect,POINT point)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
PatBlt(int x,int y,int nWidth,int nHeight,DWORD dwRop)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 
BitBlt(int x,int y,int nWidth,int nHeight,HDC hSrcDC,int xSrc,int ySrc,DWORD dwRop)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 
StretchBlt(int x,int y,int nWidth,int nHeight,HDC hSrcDC,int xSrc,int ySrc,int nSrcWidth,int nSrcHeight,DWORD dwRop)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 
GetPixel(int x,int y)2105 	COLORREF GetPixel(int x, int y) const
2106 	{
2107 		ATLASSERT(m_hDC != NULL);
2108 		return ::GetPixel(m_hDC, x, y);
2109 	}
2110 
GetPixel(POINT point)2111 	COLORREF GetPixel(POINT point) const
2112 	{
2113 		ATLASSERT(m_hDC != NULL);
2114 		return ::GetPixel(m_hDC, point.x, point.y);
2115 	}
2116 
SetPixel(int x,int y,COLORREF crColor)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 
SetPixel(POINT point,COLORREF crColor)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 
FloodFill(int x,int y,COLORREF crColor)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 
ExtFloodFill(int x,int y,COLORREF crColor,UINT nFillType)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 
MaskBlt(int x,int y,int nWidth,int nHeight,HDC hSrcDC,int xSrc,int ySrc,HBITMAP hMaskBitmap,int xMask,int yMask,DWORD dwRop)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 
PlgBlt(LPPOINT lpPoint,HDC hSrcDC,int xSrc,int ySrc,int nWidth,int nHeight,HBITMAP hMaskBitmap,int xMask,int yMask)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 
SetPixelV(int x,int y,COLORREF crColor)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 
SetPixelV(POINT point,COLORREF crColor)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 
TransparentBlt(int x,int y,int nWidth,int nHeight,HDC hSrcDC,int xSrc,int ySrc,int nSrcWidth,int nSrcHeight,UINT crTransparent)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 
GradientFill(const PTRIVERTEX pVertices,DWORD nVertices,void * pMeshElements,DWORD nMeshElements,DWORD dwMode)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 
GradientFillRect(RECT & rect,COLORREF clr1,COLORREF clr2,bool bHorizontal)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 
AlphaBlend(int x,int y,int nWidth,int nHeight,HDC hSrcDC,int xSrc,int ySrc,int nSrcWidth,int nSrcHeight,BLENDFUNCTION bf)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 
DrawText(LPCTSTR lpstrText,int cchText,LPRECT lpRect,UINT uFormat)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 
DrawText(LPTSTR lpstrText,int cchText,LPRECT lpRect,UINT uFormat)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
DrawShadowText(LPCWSTR lpstrText,int cchText,LPRECT lpRect,DWORD dwFlags,COLORREF clrText,COLORREF clrShadow,int xOffset,int yOffset)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 
GetTextExtent(LPCTSTR lpszString,int nCount,LPSIZE lpSize)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 
GrayString(HBRUSH hBrush,BOOL (CALLBACK * lpfnOutput)(HDC,LPARAM,int),LPARAM lpData,int nCount,int x,int y,int nWidth,int nHeight)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 
GetTextAlign()2403 	UINT GetTextAlign() const
2404 	{
2405 		ATLASSERT(m_hDC != NULL);
2406 		return ::GetTextAlign(m_hDC);
2407 	}
2408 
SetTextAlign(UINT nFlags)2409 	UINT SetTextAlign(UINT nFlags)
2410 	{
2411 		ATLASSERT(m_hDC != NULL);
2412 		return ::SetTextAlign(m_hDC, nFlags);
2413 	}
2414 
GetTextFace(LPTSTR lpszFacename,int nCount)2415 	int GetTextFace(LPTSTR lpszFacename, int nCount) const
2416 	{
2417 		ATLASSERT(m_hDC != NULL);
2418 		return ::GetTextFace(m_hDC, nCount, lpszFacename);
2419 	}
2420 
GetTextFaceLen()2421 	int GetTextFaceLen() const
2422 	{
2423 		ATLASSERT(m_hDC != NULL);
2424 		return ::GetTextFace(m_hDC, 0, NULL);
2425 	}
2426 
2427 #ifdef _OLEAUTO_H_
GetTextFace(BSTR & bstrFace)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__
GetTextFace(ATL::CString & strFace)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 
GetTextMetrics(LPTEXTMETRIC lpMetrics)2469 	BOOL GetTextMetrics(LPTEXTMETRIC lpMetrics) const
2470 	{
2471 		ATLASSERT(m_hDC != NULL);
2472 		return ::GetTextMetrics(m_hDC, lpMetrics);
2473 	}
2474 
SetTextJustification(int nBreakExtra,int nBreakCount)2475 	int SetTextJustification(int nBreakExtra, int nBreakCount)
2476 	{
2477 		ATLASSERT(m_hDC != NULL);
2478 		return ::SetTextJustification(m_hDC, nBreakExtra, nBreakCount);
2479 	}
2480 
GetTextCharacterExtra()2481 	int GetTextCharacterExtra() const
2482 	{
2483 		ATLASSERT(m_hDC != NULL);
2484 		return ::GetTextCharacterExtra(m_hDC);
2485 	}
2486 
SetTextCharacterExtra(int nCharExtra)2487 	int SetTextCharacterExtra(int nCharExtra)
2488 	{
2489 		ATLASSERT(m_hDC != NULL);
2490 		return ::SetTextCharacterExtra(m_hDC, nCharExtra);
2491 	}
2492 
2493 // Advanced Drawing
DrawEdge(LPRECT lpRect,UINT nEdge,UINT nFlags)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 
DrawFrameControl(LPRECT lpRect,UINT nType,UINT nState)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
ScrollDC(int dx,int dy,LPCRECT lpRectScroll,LPCRECT lpRectClip,HRGN hRgnUpdate,LPRECT lpRectUpdate)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
GetCharWidth(UINT nFirstChar,UINT nLastChar,LPINT lpBuffer)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
GetCharWidth32(UINT nFirstChar,UINT nLastChar,LPINT lpBuffer)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 
SetMapperFlags(DWORD dwFlag)2527 	DWORD SetMapperFlags(DWORD dwFlag)
2528 	{
2529 		ATLASSERT(m_hDC != NULL);
2530 		return ::SetMapperFlags(m_hDC, dwFlag);
2531 	}
2532 
GetAspectRatioFilter(LPSIZE lpSize)2533 	BOOL GetAspectRatioFilter(LPSIZE lpSize) const
2534 	{
2535 		ATLASSERT(m_hDC != NULL);
2536 		return ::GetAspectRatioFilterEx(m_hDC, lpSize);
2537 	}
2538 
GetCharABCWidths(UINT nFirstChar,UINT nLastChar,LPABC lpabc)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 
GetFontData(DWORD dwTable,DWORD dwOffset,LPVOID lpData,DWORD cbData)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 
GetKerningPairs(int nPairs,LPKERNINGPAIR lpkrnpair)2551 	int GetKerningPairs(int nPairs, LPKERNINGPAIR lpkrnpair) const
2552 	{
2553 		ATLASSERT(m_hDC != NULL);
2554 		return ::GetKerningPairs(m_hDC, nPairs, lpkrnpair);
2555 	}
2556 
GetOutlineTextMetrics(UINT cbData,LPOUTLINETEXTMETRIC lpotm)2557 	UINT GetOutlineTextMetrics(UINT cbData, LPOUTLINETEXTMETRIC lpotm) const
2558 	{
2559 		ATLASSERT(m_hDC != NULL);
2560 		return ::GetOutlineTextMetrics(m_hDC, cbData, lpotm);
2561 	}
2562 
GetGlyphOutline(UINT nChar,UINT nFormat,LPGLYPHMETRICS lpgm,DWORD cbBuffer,LPVOID lpBuffer,const MAT2 * lpmat2)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 
GetCharABCWidths(UINT nFirstChar,UINT nLastChar,LPABCFLOAT lpABCF)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 
GetCharWidth(UINT nFirstChar,UINT nLastChar,float * lpFloatBuffer)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
Escape(int nEscape,int nCount,LPCSTR lpszInData,LPVOID lpOutData)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 
Escape(int nEscape,int nInputSize,LPCSTR lpszInputData,int nOutputSize,LPSTR lpszOutputData)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 
DrawEscape(int nEscape,int nInputSize,LPCSTR lpszInputData)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
StartDoc(LPCTSTR lpszDocName)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 
StartDoc(LPDOCINFO lpDocInfo)2610 	int StartDoc(LPDOCINFO lpDocInfo)
2611 	{
2612 		ATLASSERT(m_hDC != NULL);
2613 		return ::StartDoc(m_hDC, lpDocInfo);
2614 	}
2615 
StartPage()2616 	int StartPage()
2617 	{
2618 		ATLASSERT(m_hDC != NULL);
2619 		return ::StartPage(m_hDC);
2620 	}
2621 
EndPage()2622 	int EndPage()
2623 	{
2624 		ATLASSERT(m_hDC != NULL);
2625 		return ::EndPage(m_hDC);
2626 	}
2627 
SetAbortProc(BOOL (CALLBACK * lpfn)(HDC,int))2628 	int SetAbortProc(BOOL (CALLBACK* lpfn)(HDC, int))
2629 	{
2630 		ATLASSERT(m_hDC != NULL);
2631 		return ::SetAbortProc(m_hDC, (ABORTPROC)lpfn);
2632 	}
2633 
AbortDoc()2634 	int AbortDoc()
2635 	{
2636 		ATLASSERT(m_hDC != NULL);
2637 		return ::AbortDoc(m_hDC);
2638 	}
2639 
EndDoc()2640 	int EndDoc()
2641 	{
2642 		ATLASSERT(m_hDC != NULL);
2643 		return ::EndDoc(m_hDC);
2644 	}
2645 
2646 // MetaFile Functions
PlayMetaFile(HMETAFILE hMF)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 
PlayMetaFile(HENHMETAFILE hEnhMetaFile,LPCRECT lpBounds)2660 	BOOL PlayMetaFile(HENHMETAFILE hEnhMetaFile, LPCRECT lpBounds)
2661 	{
2662 		ATLASSERT(m_hDC != NULL);
2663 		return ::PlayEnhMetaFile(m_hDC, hEnhMetaFile, lpBounds);
2664 	}
2665 
AddMetaFileComment(UINT nDataSize,const BYTE * pCommentData)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
EnumMetaFileProc(HDC hDC,HANDLETABLE * pHandleTable,METARECORD * pMetaRec,int nHandles,LPARAM lParam)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
AbortPath()2761 	BOOL AbortPath()
2762 	{
2763 		ATLASSERT(m_hDC != NULL);
2764 		return ::AbortPath(m_hDC);
2765 	}
2766 
BeginPath()2767 	BOOL BeginPath()
2768 	{
2769 		ATLASSERT(m_hDC != NULL);
2770 		return ::BeginPath(m_hDC);
2771 	}
2772 
CloseFigure()2773 	BOOL CloseFigure()
2774 	{
2775 		ATLASSERT(m_hDC != NULL);
2776 		return ::CloseFigure(m_hDC);
2777 	}
2778 
EndPath()2779 	BOOL EndPath()
2780 	{
2781 		ATLASSERT(m_hDC != NULL);
2782 		return ::EndPath(m_hDC);
2783 	}
2784 
FillPath()2785 	BOOL FillPath()
2786 	{
2787 		ATLASSERT(m_hDC != NULL);
2788 		return ::FillPath(m_hDC);
2789 	}
2790 
FlattenPath()2791 	BOOL FlattenPath()
2792 	{
2793 		ATLASSERT(m_hDC != NULL);
2794 		return ::FlattenPath(m_hDC);
2795 	}
2796 
StrokeAndFillPath()2797 	BOOL StrokeAndFillPath()
2798 	{
2799 		ATLASSERT(m_hDC != NULL);
2800 		return ::StrokeAndFillPath(m_hDC);
2801 	}
2802 
StrokePath()2803 	BOOL StrokePath()
2804 	{
2805 		ATLASSERT(m_hDC != NULL);
2806 		return ::StrokePath(m_hDC);
2807 	}
2808 
WidenPath()2809 	BOOL WidenPath()
2810 	{
2811 		ATLASSERT(m_hDC != NULL);
2812 		return ::WidenPath(m_hDC);
2813 	}
2814 
GetMiterLimit(PFLOAT pfMiterLimit)2815 	BOOL GetMiterLimit(PFLOAT pfMiterLimit) const
2816 	{
2817 		ATLASSERT(m_hDC != NULL);
2818 		return ::GetMiterLimit(m_hDC, pfMiterLimit);
2819 	}
2820 
SetMiterLimit(float fMiterLimit)2821 	BOOL SetMiterLimit(float fMiterLimit)
2822 	{
2823 		ATLASSERT(m_hDC != NULL);
2824 		return ::SetMiterLimit(m_hDC, fMiterLimit, NULL);
2825 	}
2826 
GetPath(LPPOINT lpPoints,LPBYTE lpTypes,int nCount)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 
SelectClipPath(int nMode)2833 	BOOL SelectClipPath(int nMode)
2834 	{
2835 		ATLASSERT(m_hDC != NULL);
2836 		return ::SelectClipPath(m_hDC, nMode);
2837 	}
2838 
2839 // Misc Helper Functions
GetHalftoneBrush()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 
FillSolidRect(LPCRECT lpRect,COLORREF clr)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 
FillSolidRect(int x,int y,int cx,int cy,COLORREF clr)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 
Draw3dRect(LPCRECT lpRect,COLORREF clrTopLeft,COLORREF clrBottomRight)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 
Draw3dRect(int x,int y,int cx,int cy,COLORREF clrTopLeft,COLORREF clrBottomRight)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
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)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 
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)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 
GetDIBColorTable(UINT uStartIndex,UINT cEntries,RGBQUAD * pColors)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 
SetDIBColorTable(UINT uStartIndex,UINT cEntries,CONST RGBQUAD * pColors)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)
ChoosePixelFormat(CONST PIXELFORMATDESCRIPTOR * ppfd)2981 	int ChoosePixelFormat(CONST PIXELFORMATDESCRIPTOR* ppfd)
2982 	{
2983 		ATLASSERT(m_hDC != NULL);
2984 		return ::ChoosePixelFormat(m_hDC, ppfd);
2985 	}
2986 
DescribePixelFormat(int iPixelFormat,UINT nBytes,LPPIXELFORMATDESCRIPTOR ppfd)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 
GetPixelFormat()2993 	int GetPixelFormat() const
2994 	{
2995 		ATLASSERT(m_hDC != NULL);
2996 		return ::GetPixelFormat(m_hDC);
2997 	}
2998 
SetPixelFormat(int iPixelFormat,CONST PIXELFORMATDESCRIPTOR * ppfd)2999 	BOOL SetPixelFormat(int iPixelFormat, CONST PIXELFORMATDESCRIPTOR* ppfd)
3000 	{
3001 		ATLASSERT(m_hDC != NULL);
3002 		return ::SetPixelFormat(m_hDC, iPixelFormat, ppfd);
3003 	}
3004 
SwapBuffers()3005 	BOOL SwapBuffers()
3006 	{
3007 		ATLASSERT(m_hDC != NULL);
3008 		return ::SwapBuffers(m_hDC);
3009 	}
3010 
wglCreateContext()3011 	HGLRC wglCreateContext()
3012 	{
3013 		ATLASSERT(m_hDC != NULL);
3014 		return ::wglCreateContext(m_hDC);
3015 	}
3016 
wglCreateLayerContext(int iLayerPlane)3017 	HGLRC wglCreateLayerContext(int iLayerPlane)
3018 	{
3019 		ATLASSERT(m_hDC != NULL);
3020 		return ::wglCreateLayerContext(m_hDC, iLayerPlane);
3021 	}
3022 
wglMakeCurrent(HGLRC hglrc)3023 	BOOL wglMakeCurrent(HGLRC hglrc)
3024 	{
3025 		ATLASSERT(m_hDC != NULL);
3026 		return ::wglMakeCurrent(m_hDC, hglrc);
3027 	}
3028 
wglUseFontBitmaps(DWORD dwFirst,DWORD dwCount,DWORD listBase)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 
wglUseFontOutlines(DWORD dwFirst,DWORD dwCount,DWORD listBase,FLOAT deviation,FLOAT extrusion,int format,LPGLYPHMETRICSFLOAT lpgmf)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 
wglDescribeLayerPlane(int iPixelFormat,int iLayerPlane,UINT nBytes,LPLAYERPLANEDESCRIPTOR plpd)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 
wglSetLayerPaletteEntries(int iLayerPlane,int iStart,int cEntries,CONST COLORREF * pclr)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 
wglGetLayerPaletteEntries(int iLayerPlane,int iStart,int cEntries,COLORREF * pclr)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 
wglRealizeLayerPalette(int iLayerPlane,BOOL bRealize)3059 	BOOL wglRealizeLayerPalette(int iLayerPlane, BOOL bRealize)
3060 	{
3061 		ATLASSERT(m_hDC != NULL);
3062 		return ::wglRealizeLayerPalette(m_hDC, iLayerPlane, bRealize);
3063 	}
3064 
wglSwapLayerBuffers(UINT uPlanes)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 
GetDCPenColor()3072 	COLORREF GetDCPenColor() const
3073 	{
3074 		ATLASSERT(m_hDC != NULL);
3075 		return ::GetDCPenColor(m_hDC);
3076 	}
3077 
SetDCPenColor(COLORREF clr)3078 	COLORREF SetDCPenColor(COLORREF clr)
3079 	{
3080 		ATLASSERT(m_hDC != NULL);
3081 		return ::SetDCPenColor(m_hDC, clr);
3082 	}
3083 
GetDCBrushColor()3084 	COLORREF GetDCBrushColor() const
3085 	{
3086 		ATLASSERT(m_hDC != NULL);
3087 		return ::GetDCBrushColor(m_hDC);
3088 	}
3089 
SetDCBrushColor(COLORREF clr)3090 	COLORREF SetDCBrushColor(COLORREF clr)
3091 	{
3092 		ATLASSERT(m_hDC != NULL);
3093 		return ::SetDCBrushColor(m_hDC, clr);
3094 	}
3095 
GetFontUnicodeRanges(LPGLYPHSET lpgs)3096 	DWORD GetFontUnicodeRanges(LPGLYPHSET lpgs) const
3097 	{
3098 		ATLASSERT(m_hDC != NULL);
3099 		return ::GetFontUnicodeRanges(m_hDC, lpgs);
3100 	}
3101 
GetGlyphIndices(LPCTSTR lpstr,int cch,LPWORD pgi,DWORD dwFlags)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 
GetTextExtentPointI(LPWORD pgiIn,int cgi,LPSIZE lpSize)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 
GetTextExtentExPointI(LPWORD pgiIn,int cgi,int nMaxExtent,LPINT lpnFit,LPINT alpDx,LPSIZE lpSize)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 
GetCharWidthI(UINT giFirst,UINT cgi,LPWORD pgi,LPINT lpBuffer)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 
GetCharABCWidthsI(UINT giFirst,UINT cgi,LPWORD pgi,LPABC lpabc)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 
ColorCorrectPalette(HPALETTE hPalette,DWORD dwFirstEntry,DWORD dwNumOfEntries)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 
3143 class CPaintDC : public CDC
3144 {
3145 public:
3146 // Data members
3147 	HWND m_hWnd;
3148 	PAINTSTRUCT m_ps;
3149 
3150 // Constructor/destructor
CPaintDC(HWND hWnd)3151 	CPaintDC(HWND hWnd)
3152 	{
3153 		ATLASSERT(::IsWindow(hWnd));
3154 		m_hWnd = hWnd;
3155 		m_hDC = ::BeginPaint(hWnd, &m_ps);
3156 	}
3157 
~CPaintDC()3158 	~CPaintDC()
3159 	{
3160 		ATLASSERT(m_hDC != NULL);
3161 		ATLASSERT(::IsWindow(m_hWnd));
3162 		::EndPaint(m_hWnd, &m_ps);
3163 		Detach();
3164 	}
3165 };
3166 
3167 class CClientDC : public CDC
3168 {
3169 public:
3170 // Data members
3171 	HWND m_hWnd;
3172 
3173 // Constructor/destructor
CClientDC(HWND hWnd)3174 	CClientDC(HWND hWnd)
3175 	{
3176 		ATLASSERT((hWnd == NULL) || ::IsWindow(hWnd));
3177 		m_hWnd = hWnd;
3178 		m_hDC = ::GetDC(hWnd);
3179 	}
3180 
~CClientDC()3181 	~CClientDC()
3182 	{
3183 		ATLASSERT(m_hDC != NULL);
3184 		::ReleaseDC(m_hWnd, Detach());
3185 	}
3186 };
3187 
3188 class CWindowDC : public CDC
3189 {
3190 public:
3191 // Data members
3192 	HWND m_hWnd;
3193 
3194 // Constructor/destructor
CWindowDC(HWND hWnd)3195 	CWindowDC(HWND hWnd)
3196 	{
3197 		ATLASSERT((hWnd == NULL) || ::IsWindow(hWnd));
3198 		m_hWnd = hWnd;
3199 		m_hDC = ::GetWindowDC(hWnd);
3200 	}
3201 
~CWindowDC()3202 	~CWindowDC()
3203 	{
3204 		ATLASSERT(m_hDC != NULL);
3205 		::ReleaseDC(m_hWnd, Detach());
3206 	}
3207 };
3208 
3209 class CMemoryDC : public CDC
3210 {
3211 public:
3212 // Data members
3213 	HDC m_hDCOriginal;
3214 	RECT m_rcPaint;
3215 	CBitmap m_bmp;
3216 	HBITMAP m_hBmpOld;
3217 
3218 // Constructor/destructor
CMemoryDC(HDC hDC,const RECT & rcPaint)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 
~CMemoryDC()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 
3241 class CEnhMetaFileInfo
3242 {
3243 public:
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
CEnhMetaFileInfo(HENHMETAFILE hEMF)3252 	CEnhMetaFileInfo(HENHMETAFILE hEMF) : m_hEMF(hEMF), m_pBits(NULL), m_pDesc(NULL)
3253 	{ }
3254 
~CEnhMetaFileInfo()3255 	~CEnhMetaFileInfo()
3256 	{
3257 		delete [] m_pBits;
3258 		delete [] m_pDesc;
3259 	}
3260 
3261 // Operations
GetEnhMetaFileBits()3262 	BYTE* GetEnhMetaFileBits()
3263 	{
3264 		ATLASSERT(m_hEMF != NULL);
3265 		UINT nBytes = ::GetEnhMetaFileBits(m_hEMF, 0, NULL);
3266 		delete [] m_pBits;
3267 		m_pBits = NULL;
3268 		ATLTRY(m_pBits = new BYTE[nBytes]);
3269 		if (m_pBits != NULL)
3270 			::GetEnhMetaFileBits(m_hEMF, nBytes, m_pBits);
3271 		return m_pBits;
3272 	}
3273 
GetEnhMetaFileDescription()3274 	LPTSTR GetEnhMetaFileDescription()
3275 	{
3276 		ATLASSERT(m_hEMF != NULL);
3277 		UINT nLen = ::GetEnhMetaFileDescription(m_hEMF, 0, NULL);
3278 		delete [] m_pDesc;
3279 		m_pDesc = NULL;
3280 		ATLTRY(m_pDesc = new TCHAR[nLen]);
3281 		if (m_pDesc != NULL)
3282 			nLen = ::GetEnhMetaFileDescription(m_hEMF, nLen, m_pDesc);
3283 		return m_pDesc;
3284 	}
3285 
GetEnhMetaFileHeader()3286 	ENHMETAHEADER* GetEnhMetaFileHeader()
3287 	{
3288 		ATLASSERT(m_hEMF != NULL);
3289 		memset(&m_header, 0, sizeof(m_header));
3290 		m_header.iType = EMR_HEADER;
3291 		m_header.nSize = sizeof(ENHMETAHEADER);
3292 		UINT n = ::GetEnhMetaFileHeader(m_hEMF, sizeof(ENHMETAHEADER), &m_header);
3293 		return (n != 0) ? &m_header : NULL;
3294 	}
3295 
GetEnhMetaFilePixelFormat()3296 	PIXELFORMATDESCRIPTOR* GetEnhMetaFilePixelFormat()
3297 	{
3298 		ATLASSERT(m_hEMF != NULL);
3299 		memset(&m_pfd, 0, sizeof(m_pfd));
3300 		UINT n = ::GetEnhMetaFilePixelFormat(m_hEMF, sizeof(m_pfd), &m_pfd);
3301 		return (n != 0) ? &m_pfd : NULL;
3302 	}
3303 };
3304 
3305 
3306 template <bool t_bManaged>
3307 class CEnhMetaFileT
3308 {
3309 public:
3310 // Data members
3311 	HENHMETAFILE m_hEMF;
3312 
3313 // Constructor/destructor
m_hEMF(hEMF)3314 	CEnhMetaFileT(HENHMETAFILE hEMF = NULL) : m_hEMF(hEMF)
3315 	{
3316 	}
3317 
~CEnhMetaFileT()3318 	~CEnhMetaFileT()
3319 	{
3320 		if(t_bManaged && (m_hEMF != NULL))
3321 			DeleteObject();
3322 	}
3323 
3324 // Operations
3325 	CEnhMetaFileT<t_bManaged>& operator =(HENHMETAFILE hEMF)
3326 	{
3327 		Attach(hEMF);
3328 		return *this;
3329 	}
3330 
Attach(HENHMETAFILE hEMF)3331 	void Attach(HENHMETAFILE hEMF)
3332 	{
3333 		if(t_bManaged && (m_hEMF != NULL) && (m_hEMF != hEMF))
3334 			DeleteObject();
3335 		m_hEMF = hEMF;
3336 	}
3337 
Detach()3338 	HENHMETAFILE Detach()
3339 	{
3340 		HENHMETAFILE hEMF = m_hEMF;
3341 		m_hEMF = NULL;
3342 		return hEMF;
3343 	}
3344 
HENHMETAFILE()3345 	operator HENHMETAFILE() const { return m_hEMF; }
3346 
IsNull()3347 	bool IsNull() const { return (m_hEMF == NULL); }
3348 
DeleteObject()3349 	BOOL DeleteObject()
3350 	{
3351 		ATLASSERT(m_hEMF != NULL);
3352 		BOOL bRet = ::DeleteEnhMetaFile(m_hEMF);
3353 		m_hEMF = NULL;
3354 		return bRet;
3355 	}
3356 
GetEnhMetaFileBits(UINT cbBuffer,LPBYTE lpbBuffer)3357 	UINT GetEnhMetaFileBits(UINT cbBuffer, LPBYTE lpbBuffer) const
3358 	{
3359 		ATLASSERT(m_hEMF != NULL);
3360 		return ::GetEnhMetaFileBits(m_hEMF, cbBuffer, lpbBuffer);
3361 	}
3362 
GetEnhMetaFileDescription(UINT cchBuffer,LPTSTR lpszDescription)3363 	UINT GetEnhMetaFileDescription(UINT cchBuffer, LPTSTR lpszDescription) const
3364 	{
3365 		ATLASSERT(m_hEMF != NULL);
3366 		return ::GetEnhMetaFileDescription(m_hEMF, cchBuffer, lpszDescription);
3367 	}
3368 
GetEnhMetaFileHeader(LPENHMETAHEADER lpemh)3369 	UINT GetEnhMetaFileHeader(LPENHMETAHEADER lpemh) const
3370 	{
3371 		ATLASSERT(m_hEMF != NULL);
3372 		lpemh->iType = EMR_HEADER;
3373 		lpemh->nSize = sizeof(ENHMETAHEADER);
3374 		return ::GetEnhMetaFileHeader(m_hEMF, sizeof(ENHMETAHEADER), lpemh);
3375 	}
3376 
GetEnhMetaFilePaletteEntries(UINT cEntries,LPPALETTEENTRY lppe)3377 	UINT GetEnhMetaFilePaletteEntries(UINT cEntries, LPPALETTEENTRY lppe) const
3378 	{
3379 		ATLASSERT(m_hEMF != NULL);
3380 		return ::GetEnhMetaFilePaletteEntries(m_hEMF, cEntries, lppe);
3381 	}
3382 
GetEnhMetaFilePixelFormat(DWORD cbBuffer,PIXELFORMATDESCRIPTOR * ppfd)3383 	UINT GetEnhMetaFilePixelFormat(DWORD cbBuffer, PIXELFORMATDESCRIPTOR* ppfd) const
3384 	{
3385 		ATLASSERT(m_hEMF != NULL);
3386 		return ::GetEnhMetaFilePixelFormat(m_hEMF, cbBuffer, ppfd);
3387 	}
3388 };
3389 
3390 typedef CEnhMetaFileT<false>   CEnhMetaFileHandle;
3391 typedef CEnhMetaFileT<true>    CEnhMetaFile;
3392 
3393 
3394 class CEnhMetaFileDC : public CDC
3395 {
3396 public:
3397 // Constructor/destructor
CEnhMetaFileDC()3398 	CEnhMetaFileDC()
3399 	{
3400 	}
3401 
CEnhMetaFileDC(HDC hdc,LPCRECT lpRect)3402 	CEnhMetaFileDC(HDC hdc, LPCRECT lpRect)
3403 	{
3404 		Create(hdc, NULL, lpRect, NULL);
3405 		ATLASSERT(m_hDC != NULL);
3406 	}
3407 
CEnhMetaFileDC(HDC hdcRef,LPCTSTR lpFilename,LPCRECT lpRect,LPCTSTR lpDescription)3408 	CEnhMetaFileDC(HDC hdcRef, LPCTSTR lpFilename, LPCRECT lpRect, LPCTSTR lpDescription)
3409 	{
3410 		Create(hdcRef, lpFilename, lpRect, lpDescription);
3411 		ATLASSERT(m_hDC != NULL);
3412 	}
3413 
~CEnhMetaFileDC()3414 	~CEnhMetaFileDC()
3415 	{
3416 		HENHMETAFILE hEMF = Close();
3417 		if (hEMF != NULL)
3418 			::DeleteEnhMetaFile(hEMF);
3419 	}
3420 
3421 // Operations
Create(HDC hdcRef,LPCTSTR lpFilename,LPCRECT lpRect,LPCTSTR lpDescription)3422 	void Create(HDC hdcRef, LPCTSTR lpFilename, LPCRECT lpRect, LPCTSTR lpDescription)
3423 	{
3424 		ATLASSERT(m_hDC == NULL);
3425 		m_hDC = ::CreateEnhMetaFile(hdcRef, lpFilename, lpRect, lpDescription);
3426 	}
3427 
Close()3428 	HENHMETAFILE Close()
3429 	{
3430 		HENHMETAFILE hEMF = NULL;
3431 		if (m_hDC != NULL)
3432 		{
3433 			hEMF = ::CloseEnhMetaFile(m_hDC);
3434 			m_hDC = NULL;
3435 		}
3436 		return hEMF;
3437 	}
3438 };
3439 
3440 } // namespace WTL
3441 
3442 #endif // __ATLGDI_H__
3443