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