home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / wingdi.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  34KB  |  1,379 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFX_CORE2_SEG
  14. #pragma code_seg(AFX_CORE2_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. /////////////////////////////////////////////////////////////////////////////
  23. // Diagnostic Output
  24. #ifdef _DEBUG
  25. CDumpContext& AFXAPI operator<<(CDumpContext& dc, SIZE size)
  26. {
  27.     return dc << "(" << size.cx << " x " << size.cy << ")";
  28. }
  29.  
  30. CDumpContext& AFXAPI operator<<(CDumpContext& dc, POINT point)
  31. {
  32.     return dc << "(" << point.x << ", " << point.y << ")";
  33. }
  34.  
  35. CDumpContext& AFXAPI operator<<(CDumpContext& dc, const RECT& rect)
  36. {
  37.     return dc << "(L " << rect.left << ", T " << rect.top << ", R " <<
  38.         rect.right << ", B " << rect.bottom << ")";
  39. }
  40. #endif //_DEBUG
  41.  
  42. /////////////////////////////////////////////////////////////////////////////
  43. // CDC
  44.  
  45. CDC::CDC()
  46. {
  47.     m_hDC = NULL;
  48.     m_hAttribDC = NULL;
  49.     m_bPrinting = FALSE;
  50. }
  51.  
  52. #ifdef _DEBUG
  53. void CDC::AssertValid() const
  54. {
  55.     CObject::AssertValid();
  56. }
  57.  
  58. void CDC::Dump(CDumpContext& dc) const
  59. {
  60.     CObject::Dump(dc);
  61.  
  62.     dc << "m_hDC = " << (UINT)m_hDC;
  63.     dc << "\nm_hAttribDC = " << (UINT)m_hAttribDC;
  64.     dc << "\nm_bPrinting = " << m_bPrinting;
  65.  
  66.     dc << "\n";
  67. }
  68. #endif //_DEBUG
  69.  
  70. #include "fixalloc.h"
  71.  
  72. class CTempDC : public CDC
  73. {
  74.     DECLARE_DYNCREATE(CTempDC)
  75.     DECLARE_FIXED_ALLOC(CTempDC);
  76. };
  77.  
  78. CHandleMap* PASCAL afxMapHDC(BOOL bCreate)
  79. {
  80.     AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
  81.     if (pState->m_pmapHDC == NULL && bCreate)
  82.     {
  83.         BOOL bEnable = AfxEnableMemoryTracking(FALSE);
  84. #ifndef _AFX_PORTABLE
  85.         _PNH pnhOldHandler = AfxSetNewHandler(&AfxCriticalNewHandler);
  86. #endif
  87.         pState->m_pmapHDC = new CHandleMap(RUNTIME_CLASS(CTempDC),
  88.             offsetof(CDC, m_hDC), 2);
  89.  
  90. #ifndef _AFX_PORTABLE
  91.         AfxSetNewHandler(pnhOldHandler);
  92. #endif
  93.         AfxEnableMemoryTracking(bEnable);
  94.     }
  95.     return pState->m_pmapHDC;
  96. }
  97.  
  98. CDC* PASCAL CDC::FromHandle(HDC hDC)
  99. {
  100.     CHandleMap* pMap = afxMapHDC(TRUE); //create map if not exist
  101.     ASSERT(pMap != NULL);
  102.     CDC* pDC = (CDC*)pMap->FromHandle(hDC);
  103.     ASSERT(pDC == NULL || pDC->m_hDC == hDC);
  104.     return pDC;
  105. }
  106.  
  107. BOOL CDC::Attach(HDC hDC)
  108. {
  109.     ASSERT(m_hDC == NULL);      // only attach once, detach on destroy
  110.     ASSERT(m_hAttribDC == NULL);    // only attach to an empty DC
  111.  
  112.     if (hDC == NULL)
  113.         return FALSE;
  114.     CHandleMap* pMap = afxMapHDC(TRUE); // create map if not exist
  115.     ASSERT(pMap != NULL);
  116.     pMap->SetPermanent(m_hDC = hDC, this);
  117.  
  118.     SetAttribDC(m_hDC);     // Default to same as output
  119.     return TRUE;
  120. }
  121.  
  122. HDC CDC::Detach()
  123. {
  124.     HDC hDC = m_hDC;
  125.     if (hDC != NULL)
  126.     {
  127.         CHandleMap* pMap = afxMapHDC(); // don't create if not exist
  128.         if (pMap != NULL)
  129.             pMap->RemoveHandle(m_hDC);
  130.     }
  131.  
  132.     ReleaseAttribDC();
  133.     m_hDC = NULL;
  134.     return hDC;
  135. }
  136.  
  137. BOOL CDC::DeleteDC()
  138. {
  139.     if (m_hDC == NULL)
  140.         return FALSE;
  141.  
  142.     return ::DeleteDC(Detach());
  143. }
  144.  
  145. CDC::~CDC()
  146. {
  147.     if (m_hDC != NULL)
  148.         ::DeleteDC(Detach());
  149. }
  150.  
  151.  
  152. void CDC::SetAttribDC(HDC hDC)  // Set the Attribute DC
  153. {
  154.     m_hAttribDC = hDC;
  155. }
  156.  
  157. void CDC::SetOutputDC(HDC hDC)  // Set the Output DC
  158. {
  159. #ifdef _DEBUG
  160.     CHandleMap* pMap = afxMapHDC();
  161.     if (pMap != NULL && pMap->LookupPermanent(m_hDC) == this)
  162.     {
  163.         TRACE0("Cannot Set Output hDC on Attached CDC.\n");
  164.         ASSERT(FALSE);
  165.     }
  166. #endif
  167.     m_hDC = hDC;
  168. }
  169.  
  170. void CDC::ReleaseAttribDC()     // Release the Attribute DC
  171. {
  172.     m_hAttribDC = NULL;
  173. }
  174.  
  175. void CDC::ReleaseOutputDC()     // Release the Output DC
  176. {
  177. #ifdef _DEBUG
  178.     CHandleMap* pMap = afxMapHDC();
  179.     if (pMap != NULL && pMap->LookupPermanent(m_hDC) == this)
  180.     {
  181.         TRACE0("Cannot Release Output hDC on Attached CDC.\n");
  182.         ASSERT(FALSE);
  183.     }
  184. #endif
  185.     m_hDC = NULL;
  186. }
  187.  
  188. /////////////////////////////////////////////////////////////////////////////
  189. // Out-of-line routines
  190.  
  191. int CDC::StartDoc(LPCTSTR lpszDocName)
  192. {
  193.     DOCINFO di;
  194.     memset(&di, 0, sizeof(DOCINFO));
  195.     di.cbSize = sizeof(DOCINFO);
  196.     di.lpszDocName = lpszDocName;
  197.     return StartDoc(&di);
  198. }
  199.  
  200. int CDC::SaveDC()
  201. {
  202.     ASSERT(m_hDC != NULL);
  203.     int nRetVal = 0;
  204.     if (m_hAttribDC != NULL)
  205.         nRetVal = ::SaveDC(m_hAttribDC);
  206.     if (m_hDC != m_hAttribDC && ::SaveDC(m_hDC) != 0)
  207.         nRetVal = -1;   // -1 is the only valid restore value for complex DCs
  208.     return nRetVal;
  209. }
  210.  
  211. BOOL CDC::RestoreDC(int nSavedDC)
  212. {
  213.     // if two distinct DCs, nSavedDC can only be -1
  214.     ASSERT(m_hDC != NULL);
  215.     ASSERT(m_hDC == m_hAttribDC || nSavedDC == -1);
  216.  
  217.     BOOL bRetVal = TRUE;
  218.     if (m_hDC != m_hAttribDC)
  219.         bRetVal = ::RestoreDC(m_hDC, nSavedDC);
  220.     if (m_hAttribDC != NULL)
  221.         bRetVal = (bRetVal && ::RestoreDC(m_hAttribDC, nSavedDC));
  222.     return bRetVal;
  223. }
  224.  
  225. CGdiObject* PASCAL CDC::SelectGdiObject(HDC hDC, HGDIOBJ h)
  226. {
  227.     return CGdiObject::FromHandle(::SelectObject(hDC, h));
  228. }
  229.  
  230. CGdiObject* CDC::SelectStockObject(int nIndex)
  231. {
  232.     ASSERT(m_hDC != NULL);
  233.  
  234.     HGDIOBJ hObject = ::GetStockObject(nIndex);
  235.     HGDIOBJ hOldObj = NULL;
  236.  
  237.     ASSERT(hObject != NULL);
  238.     if (m_hDC != m_hAttribDC)
  239.         hOldObj = ::SelectObject(m_hDC, hObject);
  240.     if (m_hAttribDC != NULL)
  241.         hOldObj = ::SelectObject(m_hAttribDC, hObject);
  242.     return CGdiObject::FromHandle(hOldObj);
  243. }
  244.  
  245. CPen* CDC::SelectObject(CPen* pPen)
  246. {
  247.     ASSERT(m_hDC != NULL);
  248.     HGDIOBJ hOldObj = NULL;
  249.  
  250.     if (m_hDC != m_hAttribDC)
  251.         hOldObj = ::SelectObject(m_hDC, pPen->GetSafeHandle());
  252.     if (m_hAttribDC != NULL)
  253.         hOldObj = ::SelectObject(m_hAttribDC, pPen->GetSafeHandle());
  254.     return (CPen*)CGdiObject::FromHandle(hOldObj);
  255. }
  256.  
  257. CBrush* CDC::SelectObject(CBrush* pBrush)
  258. {
  259.     ASSERT(m_hDC != NULL);
  260.     HGDIOBJ hOldObj = NULL;
  261.  
  262.     if (m_hDC != m_hAttribDC)
  263.         hOldObj = ::SelectObject(m_hDC, pBrush->GetSafeHandle());
  264.     if (m_hAttribDC != NULL)
  265.         hOldObj = ::SelectObject(m_hAttribDC, pBrush->GetSafeHandle());
  266.     return (CBrush*)CGdiObject::FromHandle(hOldObj);
  267. }
  268.  
  269. CFont* CDC::SelectObject(CFont* pFont)
  270. {
  271.     ASSERT(m_hDC != NULL);
  272.     HGDIOBJ hOldObj = NULL;
  273.  
  274.     if (m_hDC != m_hAttribDC)
  275.         hOldObj = ::SelectObject(m_hDC, pFont->GetSafeHandle());
  276.     if (m_hAttribDC != NULL)
  277.         hOldObj = ::SelectObject(m_hAttribDC, pFont->GetSafeHandle());
  278.     return (CFont*)CGdiObject::FromHandle(hOldObj);
  279. }
  280.  
  281. int CDC::SelectObject(CRgn* pRgn)
  282. {
  283.     ASSERT(m_hDC != NULL);
  284.     int nRetVal = GDI_ERROR;
  285.  
  286.     if (m_hDC != m_hAttribDC)
  287.         nRetVal = (int)::SelectObject(m_hDC, pRgn->GetSafeHandle());
  288.     if (m_hAttribDC != NULL)
  289.         nRetVal = (int)::SelectObject(m_hAttribDC, pRgn->GetSafeHandle());
  290.     return nRetVal;
  291. }
  292.  
  293. CPalette* CDC::SelectPalette(CPalette* pPalette, BOOL bForceBackground)
  294. {
  295.     ASSERT(m_hDC != NULL);
  296.  
  297.     return (CPalette*) CGdiObject::FromHandle(::SelectPalette(m_hDC,
  298.         (HPALETTE)pPalette->GetSafeHandle(), bForceBackground));
  299. }
  300.  
  301. COLORREF CDC::SetBkColor(COLORREF crColor)
  302. {
  303.     ASSERT(m_hDC != NULL);
  304.     COLORREF crRetVal = CLR_INVALID;
  305.  
  306.     if (m_hDC != m_hAttribDC)
  307.         crRetVal = ::SetBkColor(m_hDC, crColor);
  308.     if (m_hAttribDC != NULL)
  309.         crRetVal = ::SetBkColor(m_hAttribDC, crColor);
  310.     return crRetVal;
  311. }
  312.  
  313. int CDC::SetBkMode(int nBkMode)
  314. {
  315.     ASSERT(m_hDC != NULL);
  316.     int nRetVal = 0;
  317.  
  318.     if (m_hDC != m_hAttribDC)
  319.         nRetVal = ::SetBkMode(m_hDC, nBkMode);
  320.     if (m_hAttribDC != NULL)
  321.         nRetVal = ::SetBkMode(m_hAttribDC, nBkMode);
  322.     return nRetVal;
  323. }
  324.  
  325. int CDC::SetPolyFillMode(int nPolyFillMode)
  326. {
  327.     ASSERT(m_hDC != NULL);
  328.     int nRetVal = 0;
  329.  
  330.     if (m_hDC != m_hAttribDC)
  331.         nRetVal = ::SetPolyFillMode(m_hDC, nPolyFillMode);
  332.     if (m_hAttribDC != NULL)
  333.         nRetVal = ::SetPolyFillMode(m_hAttribDC, nPolyFillMode);
  334.     return nRetVal;
  335. }
  336.  
  337. int CDC::SetROP2(int nDrawMode)
  338. {
  339.     ASSERT(m_hDC != NULL);
  340.     int nRetVal = 0;
  341.  
  342.     if (m_hDC != m_hAttribDC)
  343.         nRetVal = ::SetROP2(m_hDC, nDrawMode);
  344.     if (m_hAttribDC != NULL)
  345.         nRetVal = ::SetROP2(m_hAttribDC, nDrawMode);
  346.     return nRetVal;
  347. }
  348.  
  349. int CDC::SetStretchBltMode(int nStretchMode)
  350. {
  351.     ASSERT(m_hDC != NULL);
  352.     int nRetVal = 0;
  353.  
  354.     if (m_hDC != m_hAttribDC)
  355.         nRetVal = ::SetStretchBltMode(m_hDC, nStretchMode);
  356.     if (m_hAttribDC != NULL)
  357.         nRetVal = ::SetStretchBltMode(m_hAttribDC, nStretchMode);
  358.     return nRetVal;
  359. }
  360.  
  361. COLORREF CDC::SetTextColor(COLORREF crColor)
  362. {
  363.     ASSERT(m_hDC != NULL);
  364.     COLORREF crRetVal = CLR_INVALID;
  365.  
  366.     if (m_hDC != m_hAttribDC)
  367.         crRetVal = ::SetTextColor(m_hDC, crColor);
  368.     if (m_hAttribDC != NULL)
  369.         crRetVal = ::SetTextColor(m_hAttribDC, crColor);
  370.     return crRetVal;
  371. }
  372.  
  373. int CDC::SetMapMode(int nMapMode)
  374. {
  375.     ASSERT(m_hDC != NULL);
  376.     int nRetVal = 0;
  377.  
  378.     if (m_hDC != m_hAttribDC)
  379.         nRetVal = ::SetMapMode(m_hDC, nMapMode);
  380.     if (m_hAttribDC != NULL)
  381.         nRetVal = ::SetMapMode(m_hAttribDC, nMapMode);
  382.     return nRetVal;
  383. }
  384.  
  385. CPoint CDC::SetViewportOrg(int x, int y)
  386. {
  387.     ASSERT(m_hDC != NULL);
  388.     CPoint point;
  389.  
  390.     if (m_hDC != m_hAttribDC)
  391.         VERIFY(::SetViewportOrgEx(m_hDC, x, y, &point));
  392.     if (m_hAttribDC != NULL)
  393.         VERIFY(::SetViewportOrgEx(m_hAttribDC, x, y, &point));
  394.     return point;
  395. }
  396.  
  397. CPoint CDC::OffsetViewportOrg(int nWidth, int nHeight)
  398. {
  399.     ASSERT(m_hDC != NULL);
  400.     CPoint point;
  401.  
  402.     if (m_hDC != m_hAttribDC)
  403.         VERIFY(::OffsetViewportOrgEx(m_hDC, nWidth, nHeight, &point));
  404.     if (m_hAttribDC != NULL)
  405.         VERIFY(::OffsetViewportOrgEx(m_hAttribDC, nWidth, nHeight, &point));
  406.     return point;
  407. }
  408.  
  409. CSize CDC::SetViewportExt(int x, int y)
  410. {
  411.     ASSERT(m_hDC != NULL);
  412.     CSize size;
  413.  
  414.     if (m_hDC != m_hAttribDC)
  415.         VERIFY(::SetViewportExtEx(m_hDC, x, y, &size));
  416.     if (m_hAttribDC != NULL)
  417.         VERIFY(::SetViewportExtEx(m_hAttribDC, x, y, &size));
  418.     return size;
  419. }
  420.  
  421. CSize CDC::ScaleViewportExt(int xNum, int xDenom, int yNum, int yDenom)
  422. {
  423.     ASSERT(m_hDC != NULL);
  424.     CSize size;
  425.  
  426.     if (m_hDC != m_hAttribDC)
  427.         VERIFY(::ScaleViewportExtEx(m_hDC, xNum, xDenom, yNum, yDenom, &size));
  428.     if (m_hAttribDC != NULL)
  429.         VERIFY(::ScaleViewportExtEx(m_hAttribDC, xNum, xDenom, yNum, yDenom, &size));
  430.     return size;
  431. }
  432.  
  433. CPoint CDC::SetWindowOrg(int x, int y)
  434. {
  435.     ASSERT(m_hDC != NULL);
  436.     CPoint point;
  437.  
  438.     if (m_hDC != m_hAttribDC)
  439.         VERIFY(::SetWindowOrgEx(m_hDC, x, y, &point));
  440.     if (m_hAttribDC != NULL)
  441.         VERIFY(::SetWindowOrgEx(m_hAttribDC, x, y, &point));
  442.     return point;
  443. }
  444.  
  445. CPoint CDC::OffsetWindowOrg(int nWidth, int nHeight)
  446. {
  447.     ASSERT(m_hDC != NULL);
  448.     CPoint point;
  449.  
  450.     if (m_hDC != m_hAttribDC)
  451.         VERIFY(::OffsetWindowOrgEx(m_hDC, nWidth, nHeight, &point));
  452.     if (m_hAttribDC != NULL)
  453.         VERIFY(::OffsetWindowOrgEx(m_hAttribDC, nWidth, nHeight, &point));
  454.     return point;
  455. }
  456.  
  457. CSize CDC::SetWindowExt(int x, int y)
  458. {
  459.     ASSERT(m_hDC != NULL);
  460.     CSize size;
  461.  
  462.     if (m_hDC != m_hAttribDC)
  463.         VERIFY(::SetWindowExtEx(m_hDC, x, y, &size));
  464.     if (m_hAttribDC != NULL)
  465.         VERIFY(::SetWindowExtEx(m_hAttribDC, x, y, &size));
  466.     return size;
  467. }
  468.  
  469. CSize CDC::ScaleWindowExt(int xNum, int xDenom, int yNum, int yDenom)
  470. {
  471.     ASSERT(m_hDC != NULL);
  472.     CSize size;
  473.  
  474.     if (m_hDC != m_hAttribDC)
  475.         VERIFY(::ScaleWindowExtEx(m_hDC, xNum, xDenom, yNum, yDenom, &size));
  476.     if (m_hAttribDC != NULL)
  477.         VERIFY(::ScaleWindowExtEx(m_hAttribDC, xNum, xDenom, yNum, yDenom, &size));
  478.     return size;
  479. }
  480.  
  481. int CDC::GetClipBox(LPRECT lpRect) const
  482. {
  483.     ASSERT(m_hDC != NULL);
  484.     return ::GetClipBox(m_hDC, lpRect);
  485. }
  486.  
  487. int CDC::SelectClipRgn(CRgn* pRgn)
  488. {
  489.     ASSERT(m_hDC != NULL);
  490.     int nRetVal = ERROR;
  491.  
  492.     if (m_hDC != m_hAttribDC)
  493.         nRetVal = ::SelectClipRgn(m_hDC, (HRGN)pRgn->GetSafeHandle());
  494.     if (m_hAttribDC != NULL)
  495.         nRetVal = ::SelectClipRgn(m_hAttribDC, (HRGN)pRgn->GetSafeHandle());
  496.     return nRetVal;
  497. }
  498.  
  499. int CDC::ExcludeClipRect(int x1, int y1, int x2, int y2)
  500. {
  501.     ASSERT(m_hDC != NULL);
  502.     int nRetVal = ERROR;
  503.  
  504.     if (m_hDC != m_hAttribDC)
  505.         nRetVal = ::ExcludeClipRect(m_hDC, x1, y1, x2, y2);
  506.     if (m_hAttribDC != NULL)
  507.         nRetVal = ::ExcludeClipRect(m_hAttribDC, x1, y1, x2, y2);
  508.     return nRetVal;
  509. }
  510.  
  511. int CDC::ExcludeClipRect(LPCRECT lpRect)
  512. {
  513.     ASSERT(m_hDC != NULL);
  514.     int nRetVal = ERROR;
  515.  
  516.     if (m_hDC != m_hAttribDC)
  517.         nRetVal = ::ExcludeClipRect(m_hDC, lpRect->left, lpRect->top,
  518.             lpRect->right, lpRect->bottom);
  519.     if (m_hAttribDC != NULL)
  520.         nRetVal = ::ExcludeClipRect(m_hAttribDC, lpRect->left, lpRect->top,
  521.             lpRect->right, lpRect->bottom);
  522.     return nRetVal;
  523. }
  524.  
  525. int CDC::IntersectClipRect(int x1, int y1, int x2, int y2)
  526. {
  527.     ASSERT(m_hDC != NULL);
  528.     int nRetVal = ERROR;
  529.  
  530.     if (m_hDC != m_hAttribDC)
  531.         nRetVal = ::IntersectClipRect(m_hDC, x1, y1, x2, y2);
  532.     if (m_hAttribDC != NULL)
  533.         nRetVal = ::IntersectClipRect(m_hAttribDC, x1, y1, x2, y2);
  534.     return nRetVal;
  535. }
  536.  
  537. int CDC::IntersectClipRect(LPCRECT lpRect)
  538. {
  539.     ASSERT(m_hDC != NULL);
  540.     int nRetVal = ERROR;
  541.  
  542.     if (m_hDC != m_hAttribDC)
  543.         nRetVal = ::IntersectClipRect(m_hDC, lpRect->left, lpRect->top,
  544.             lpRect->right, lpRect->bottom);
  545.     if (m_hAttribDC != NULL)
  546.         nRetVal = ::IntersectClipRect(m_hAttribDC, lpRect->left, lpRect->top,
  547.             lpRect->right, lpRect->bottom);
  548.     return nRetVal;
  549. }
  550.  
  551. int CDC::OffsetClipRgn(int x, int y)
  552. {
  553.     ASSERT(m_hDC != NULL);
  554.     int nRetVal = ERROR;
  555.  
  556.     if (m_hDC != m_hAttribDC)
  557.         nRetVal = ::OffsetClipRgn(m_hDC, x, y);
  558.     if (m_hAttribDC != NULL)
  559.         nRetVal = ::OffsetClipRgn(m_hAttribDC, x, y);
  560.     return nRetVal;
  561. }
  562.  
  563. int CDC::OffsetClipRgn(SIZE size)
  564. {
  565.     ASSERT(m_hDC != NULL);
  566.     int nRetVal = ERROR;
  567.  
  568.     if (m_hDC != m_hAttribDC)
  569.         nRetVal = ::OffsetClipRgn(m_hDC, size.cx, size.cy);
  570.     if (m_hAttribDC != NULL)
  571.         nRetVal = ::OffsetClipRgn(m_hAttribDC, size.cx, size.cy);
  572.     return nRetVal;
  573. }
  574.  
  575. CPoint CDC::MoveTo(int x, int y)
  576. {
  577.     ASSERT(m_hDC != NULL);
  578.     CPoint point;
  579.  
  580.     if (m_hDC != m_hAttribDC)
  581.         VERIFY(::MoveToEx(m_hDC, x, y, &point));
  582.     if (m_hAttribDC != NULL)
  583.         VERIFY(::MoveToEx(m_hAttribDC, x, y, &point));
  584.     return point;
  585. }
  586.  
  587. BOOL CDC::LineTo(int x, int y)
  588. {
  589.     ASSERT(m_hDC != NULL);
  590.     if (m_hAttribDC != NULL && m_hDC != m_hAttribDC)
  591.         ::MoveToEx(m_hAttribDC, x, y, NULL);
  592.     return ::LineTo(m_hDC, x, y);
  593. }
  594.  
  595. UINT CDC::SetTextAlign(UINT nFlags)
  596. {
  597.     ASSERT(m_hDC != NULL);
  598.     UINT nRetVal = GDI_ERROR;
  599.  
  600.     if (m_hDC != m_hAttribDC)
  601.         ::SetTextAlign(m_hDC, nFlags);
  602.     if (m_hAttribDC != NULL)
  603.         nRetVal = ::SetTextAlign(m_hAttribDC, nFlags);
  604.     return nRetVal;
  605. }
  606.  
  607. int CDC::SetTextJustification(int nBreakExtra, int nBreakCount)
  608. {
  609.     ASSERT(m_hDC != NULL);
  610.     int nRetVal = 0;
  611.  
  612.     if (m_hDC != m_hAttribDC)
  613.         nRetVal = ::SetTextJustification(m_hDC, nBreakExtra, nBreakCount);
  614.     if (m_hAttribDC != NULL)
  615.         nRetVal = ::SetTextJustification(m_hAttribDC, nBreakExtra, nBreakCount);
  616.     return nRetVal;
  617. }
  618.  
  619. int CDC::SetTextCharacterExtra(int nCharExtra)
  620. {
  621.     ASSERT(m_hDC != NULL);
  622.     int nRetVal = 0x8000000;
  623.     if (m_hDC != m_hAttribDC)
  624.         nRetVal = ::SetTextCharacterExtra(m_hDC, nCharExtra);
  625.     if (m_hAttribDC != NULL)
  626.         nRetVal = ::SetTextCharacterExtra(m_hAttribDC, nCharExtra);
  627.     return nRetVal;
  628. }
  629.  
  630. DWORD CDC::SetMapperFlags(DWORD dwFlag)
  631. {
  632.     ASSERT(m_hDC != NULL);
  633.     DWORD dwRetVal = GDI_ERROR;
  634.     if (m_hDC != m_hAttribDC)
  635.         dwRetVal = ::SetMapperFlags(m_hDC, dwFlag);
  636.     if (m_hAttribDC != NULL)
  637.         dwRetVal = ::SetMapperFlags(m_hAttribDC, dwFlag);
  638.     return dwRetVal;
  639. }
  640.  
  641. typedef DWORD (CALLBACK* AFX_GDIGETLAYOUTPROC)(HDC);
  642. typedef DWORD (CALLBACK* AFX_GDISETLAYOUTPROC)(HDC, DWORD);
  643.  
  644. DWORD CDC::GetLayout() const
  645. {
  646.     ASSERT(m_hDC != NULL);
  647.  
  648.     HINSTANCE hInst = ::GetModuleHandleA("GDI32.DLL");
  649.     ASSERT(hInst != NULL);
  650.  
  651.     DWORD dwGetLayout = LAYOUT_LTR;
  652.  
  653.     AFX_GDIGETLAYOUTPROC pfn;
  654.     pfn = (AFX_GDIGETLAYOUTPROC) GetProcAddress(hInst, "GetLayout");
  655.  
  656.     // if they API is available, just call it. If it is not
  657.     // available, indicate an error.
  658.  
  659.     if (pfn != NULL)
  660.         dwGetLayout = (*pfn)(m_hDC);
  661.     else
  662.     {
  663.         dwGetLayout = GDI_ERROR;
  664.         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  665.     }
  666.  
  667.     return dwGetLayout;
  668. }
  669.  
  670. DWORD CDC::SetLayout(DWORD dwSetLayout)
  671. {
  672.     ASSERT(m_hDC != NULL);
  673.  
  674.     HINSTANCE hInst = ::GetModuleHandleA("GDI32.DLL");
  675.     ASSERT(hInst != NULL);
  676.  
  677.     DWORD dwGetLayout = LAYOUT_LTR;
  678.  
  679.     AFX_GDISETLAYOUTPROC pfn;
  680.     pfn = (AFX_GDISETLAYOUTPROC) GetProcAddress(hInst, "SetLayout");
  681.  
  682.     // If the API is availalbe, just call it. If it's not available,
  683.     // setting anything other than LAYOUT_LTR is an error.
  684.  
  685.     if (pfn != NULL)
  686.         dwGetLayout = (*pfn)(m_hDC, dwSetLayout);
  687.     else if (dwSetLayout != LAYOUT_LTR)
  688.     {
  689.         dwGetLayout = GDI_ERROR;
  690.         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  691.     }
  692.  
  693.     return dwGetLayout;
  694. }
  695.  
  696. void CWnd::ScreenToClient(LPRECT lpRect) const
  697. {
  698.     ASSERT(::IsWindow(m_hWnd));
  699.     ::ScreenToClient(m_hWnd, (LPPOINT)lpRect);
  700.     ::ScreenToClient(m_hWnd, ((LPPOINT)lpRect)+1);
  701.     if (GetExStyle() & WS_EX_LAYOUTRTL)
  702.         CRect::SwapLeftRight(lpRect);
  703. }
  704.  
  705. void CWnd::ClientToScreen(LPRECT lpRect) const
  706. {
  707.     ASSERT(::IsWindow(m_hWnd));
  708.     ::ClientToScreen(m_hWnd, (LPPOINT)lpRect);
  709.     ::ClientToScreen(m_hWnd, ((LPPOINT)lpRect)+1);
  710.     if (GetExStyle() & WS_EX_LAYOUTRTL)
  711.         CRect::SwapLeftRight(lpRect);
  712. }
  713.  
  714. /////////////////////////////////////////////////////////////////////////////
  715. // Advanced Win32 GDI functions
  716.  
  717. BOOL CDC::ArcTo(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
  718. {
  719.     ASSERT(m_hDC != NULL);
  720.     BOOL bResult = ::ArcTo(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4);
  721.     if (m_hDC != m_hAttribDC)
  722.     {
  723.         CPoint pt;
  724.         VERIFY(::GetCurrentPositionEx(m_hDC, &pt));
  725.         VERIFY(::MoveToEx(m_hAttribDC, pt.x, pt.y, NULL));
  726.     }
  727.     return bResult;
  728. }
  729.  
  730. int CDC::SetArcDirection(int nArcDirection)
  731. {
  732.     ASSERT(m_hDC != NULL);
  733.     int nResult = 0;
  734.     if (m_hDC != m_hAttribDC)
  735.         nResult = ::SetArcDirection(m_hDC, nArcDirection);
  736.     if (m_hAttribDC != NULL)
  737.         nResult = ::SetArcDirection(m_hAttribDC, nArcDirection);
  738.     return nResult;
  739. }
  740.  
  741. BOOL CDC::PolyDraw(const POINT* lpPoints, const BYTE* lpTypes, int nCount)
  742. {
  743.     ASSERT(m_hDC != NULL);
  744.     BOOL bResult = ::PolyDraw(m_hDC, lpPoints, lpTypes, nCount);
  745.     if (m_hDC != m_hAttribDC)
  746.     {
  747.         CPoint pt;
  748.         VERIFY(::GetCurrentPositionEx(m_hDC, &pt));
  749.         VERIFY(::MoveToEx(m_hAttribDC, pt.x, pt.y, NULL));
  750.     }
  751.     return bResult;
  752. }
  753.  
  754. BOOL CDC::PolylineTo(const POINT* lpPoints, int nCount)
  755. {
  756.     ASSERT(m_hDC != NULL);
  757.     BOOL bResult = ::PolylineTo(m_hDC, lpPoints, nCount);
  758.     if (m_hDC != m_hAttribDC)
  759.     {
  760.         CPoint pt;
  761.         VERIFY(::GetCurrentPositionEx(m_hDC, &pt));
  762.         VERIFY(::MoveToEx(m_hAttribDC, pt.x, pt.y, NULL));
  763.     }
  764.     return bResult;
  765. }
  766.  
  767. BOOL CDC::SetColorAdjustment(const COLORADJUSTMENT* lpColorAdjust)
  768. {
  769.     ASSERT(m_hDC != NULL);
  770.     BOOL bResult = FALSE;
  771.     if (m_hDC != m_hAttribDC)
  772.         bResult = ::SetColorAdjustment(m_hDC, lpColorAdjust);
  773.     if (m_hAttribDC != NULL)
  774.         bResult = ::SetColorAdjustment(m_hAttribDC, lpColorAdjust);
  775.     return bResult;
  776. }
  777.  
  778. BOOL CDC::PolyBezierTo(const POINT* lpPoints, int nCount)
  779. {
  780.     ASSERT(m_hDC != NULL);
  781.     BOOL bResult = ::PolyBezierTo(m_hDC, lpPoints, nCount);
  782.     if (m_hDC != m_hAttribDC)
  783.     {
  784.         CPoint pt;
  785.         VERIFY(::GetCurrentPositionEx(m_hDC, &pt));
  786.         VERIFY(::MoveToEx(m_hAttribDC, pt.x, pt.y, NULL));
  787.     }
  788.     return bResult;
  789. }
  790.  
  791. BOOL CDC::SelectClipPath(int nMode)
  792. {
  793.     ASSERT(m_hDC != NULL);
  794.  
  795.     // output DC always holds the current path
  796.     if (!::SelectClipPath(m_hDC, nMode))
  797.         return FALSE;
  798.  
  799.     // transfer clipping region into the attribute DC
  800.     BOOL bResult = TRUE;
  801.     if (m_hDC != m_hAttribDC)
  802.     {
  803.         HRGN hRgn = ::CreateRectRgn(0, 0, 0, 0);
  804.         if (::GetClipRgn(m_hDC, hRgn) < 0 || !::SelectClipRgn(m_hAttribDC, hRgn))
  805.         {
  806.             TRACE0("Error: unable to transfer clip region in CDC::SelectClipPath!\n");
  807.             bResult = FALSE;
  808.         }
  809.         DeleteObject(hRgn);
  810.     }
  811.     return bResult;
  812. }
  813.  
  814. int CDC::SelectClipRgn(CRgn* pRgn, int nMode)
  815. {
  816.     ASSERT(m_hDC != NULL);
  817.     int nRetVal = ERROR;
  818.     if (m_hDC != m_hAttribDC)
  819.         nRetVal = ::ExtSelectClipRgn(m_hDC, (HRGN)pRgn->GetSafeHandle(), nMode);
  820.     if (m_hAttribDC != NULL)
  821.         nRetVal = ::ExtSelectClipRgn(m_hAttribDC, (HRGN)pRgn->GetSafeHandle(), nMode);
  822.     return nRetVal;
  823. }
  824.  
  825. /////////////////////////////////////////////////////////////////////////////
  826. // Special handling for metafile playback
  827.  
  828. int CALLBACK AfxEnumMetaFileProc(HDC hDC,
  829.     HANDLETABLE* pHandleTable, METARECORD* pMetaRec, int nHandles, LPARAM lParam)
  830. {
  831.     CDC* pDC = (CDC*)lParam;
  832.     ASSERT_VALID(pDC);
  833.  
  834.     switch (pMetaRec->rdFunction)
  835.     {
  836.     // these records have effects different for each CDC derived class
  837.     case META_SETMAPMODE:
  838.         pDC->SetMapMode((int)(short)pMetaRec->rdParm[0]);
  839.         break;
  840.     case META_SETWINDOWEXT:
  841.         pDC->SetWindowExt(
  842.             (int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
  843.         break;
  844.     case META_SETWINDOWORG:
  845.         pDC->SetWindowOrg(
  846.             (int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
  847.         break;
  848.     case META_SETVIEWPORTEXT:
  849.         pDC->SetViewportExt(
  850.             (int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
  851.         break;
  852.     case META_SETVIEWPORTORG:
  853.         pDC->SetViewportOrg(
  854.             (int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
  855.         break;
  856.     case META_SCALEWINDOWEXT:
  857.         pDC->ScaleWindowExt(
  858.             (int)(short)pMetaRec->rdParm[3], (int)(short)pMetaRec->rdParm[2],
  859.             (int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
  860.         break;
  861.     case META_SCALEVIEWPORTEXT:
  862.         pDC->ScaleViewportExt(
  863.             (int)(short)pMetaRec->rdParm[3], (int)(short)pMetaRec->rdParm[2],
  864.             (int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
  865.         break;
  866.     case META_OFFSETVIEWPORTORG:
  867.         pDC->OffsetViewportOrg(
  868.             (int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
  869.         break;
  870.     case META_SAVEDC:
  871.         pDC->SaveDC();
  872.         break;
  873.     case META_RESTOREDC:
  874.         pDC->RestoreDC((int)(short)pMetaRec->rdParm[0]);
  875.         break;
  876.     case META_SETBKCOLOR:
  877.         pDC->SetBkColor(*(UNALIGNED COLORREF*)&pMetaRec->rdParm[0]);
  878.         break;
  879.     case META_SETTEXTCOLOR:
  880.         pDC->SetTextColor(*(UNALIGNED COLORREF*)&pMetaRec->rdParm[0]);
  881.         break;
  882.  
  883.     // need to watch out for SelectObject(HFONT), for custom font mapping
  884.     case META_SELECTOBJECT:
  885.         {
  886.             HGDIOBJ hObject = pHandleTable->objectHandle[pMetaRec->rdParm[0]];
  887.             UINT nObjType = GetObjectType(hObject);
  888.             if (nObjType == 0)
  889.             {
  890.                 // object type is unknown, determine if it is a font
  891.                 HFONT hStockFont = (HFONT)::GetStockObject(SYSTEM_FONT);
  892.                 HFONT hFontOld = (HFONT)::SelectObject(pDC->m_hDC, hStockFont);
  893.                 HGDIOBJ hObjOld = ::SelectObject(pDC->m_hDC, hObject);
  894.                 if (hObjOld == hStockFont)
  895.                 {
  896.                     // got the stock object back, so must be selecting a font
  897.                     pDC->SelectObject(CFont::FromHandle((HFONT)hObject));
  898.                     break;  // don't play the default record
  899.                 }
  900.                 else
  901.                 {
  902.                     // didn't get the stock object back, so restore everything
  903.                     ::SelectObject(pDC->m_hDC, hFontOld);
  904.                     ::SelectObject(pDC->m_hDC, hObjOld);
  905.                 }
  906.                 // and fall through to PlayMetaFileRecord...
  907.             }
  908.             else if (nObjType == OBJ_FONT)
  909.             {
  910.                 // play back as CDC::SelectObject(CFont*)
  911.                 pDC->SelectObject(CFont::FromHandle((HFONT)hObject));
  912.                 break;  // don't play the default record
  913.             }
  914.         }
  915.         // fall through...
  916.  
  917.     default:
  918.         ::PlayMetaFileRecord(hDC, pHandleTable, pMetaRec, nHandles);
  919.         break;
  920.     }
  921.  
  922.     return 1;
  923. }
  924.  
  925. BOOL CDC::PlayMetaFile(HMETAFILE hMF)
  926. {
  927.     if (::GetDeviceCaps(m_hDC, TECHNOLOGY) == DT_METAFILE)
  928.     {
  929.         // playing metafile in metafile, just use core windows API
  930.         return ::PlayMetaFile(m_hDC, hMF);
  931.     }
  932.  
  933.     // for special playback, lParam == pDC
  934.     return ::EnumMetaFile(m_hDC, hMF, AfxEnumMetaFileProc, (LPARAM)this);
  935. }
  936.  
  937. /////////////////////////////////////////////////////////////////////////////
  938. // Coordinate transforms
  939.  
  940. void CDC::LPtoDP(LPSIZE lpSize) const
  941. {
  942.     ASSERT(AfxIsValidAddress(lpSize, sizeof(SIZE)));
  943.  
  944.     CSize sizeWinExt = GetWindowExt();
  945.     CSize sizeVpExt = GetViewportExt();
  946.     lpSize->cx = MulDiv(lpSize->cx, abs(sizeVpExt.cx), abs(sizeWinExt.cx));
  947.     lpSize->cy = MulDiv(lpSize->cy, abs(sizeVpExt.cy), abs(sizeWinExt.cy));
  948. }
  949.  
  950. void CDC::DPtoLP(LPSIZE lpSize) const
  951. {
  952.     ASSERT(AfxIsValidAddress(lpSize, sizeof(SIZE)));
  953.  
  954.     CSize sizeWinExt = GetWindowExt();
  955.     CSize sizeVpExt = GetViewportExt();
  956.     lpSize->cx = MulDiv(lpSize->cx, abs(sizeWinExt.cx), abs(sizeVpExt.cx));
  957.     lpSize->cy = MulDiv(lpSize->cy, abs(sizeWinExt.cy), abs(sizeVpExt.cy));
  958. }
  959.  
  960. /////////////////////////////////////////////////////////////////////////////
  961. // Helper DCs
  962.  
  963. #ifdef _DEBUG
  964. void CClientDC::AssertValid() const
  965. {
  966.     CDC::AssertValid();
  967.     ASSERT(m_hWnd == NULL || ::IsWindow(m_hWnd));
  968. }
  969.  
  970. void CClientDC::Dump(CDumpContext& dc) const
  971. {
  972.     CDC::Dump(dc);
  973.  
  974.     dc << "m_hWnd = " << (UINT)m_hWnd;
  975.     dc << "\n";
  976. }
  977. #endif
  978.  
  979. CClientDC::CClientDC(CWnd* pWnd)
  980. {
  981.     ASSERT(pWnd == NULL || ::IsWindow(pWnd->m_hWnd));
  982.  
  983.     if (!Attach(::GetDC(m_hWnd = pWnd->GetSafeHwnd())))
  984.         AfxThrowResourceException();
  985. }
  986.  
  987. CClientDC::~CClientDC()
  988. {
  989.     ASSERT(m_hDC != NULL);
  990.     ::ReleaseDC(m_hWnd, Detach());
  991. }
  992.  
  993. #ifdef _DEBUG
  994. void CWindowDC::AssertValid() const
  995. {
  996.     CDC::AssertValid();
  997.     ASSERT(m_hWnd == NULL || ::IsWindow(m_hWnd));
  998. }
  999.  
  1000. void CWindowDC::Dump(CDumpContext& dc) const
  1001. {
  1002.     CDC::Dump(dc);
  1003.  
  1004.     dc << "m_hWnd = " << (UINT)m_hWnd;
  1005.     dc << "\n";
  1006. }
  1007. #endif
  1008.  
  1009. CWindowDC::CWindowDC(CWnd* pWnd)
  1010. {
  1011.     ASSERT(pWnd == NULL || ::IsWindow(pWnd->m_hWnd));
  1012.  
  1013.     if (!Attach(::GetWindowDC(m_hWnd = pWnd->GetSafeHwnd())))
  1014.         AfxThrowResourceException();
  1015. }
  1016.  
  1017. CWindowDC::~CWindowDC()
  1018. {
  1019.     ASSERT(m_hDC != NULL);
  1020.     ::ReleaseDC(m_hWnd, Detach());
  1021. }
  1022.  
  1023. #ifdef _DEBUG
  1024. void CPaintDC::AssertValid() const
  1025. {
  1026.     CDC::AssertValid();
  1027.     ASSERT(::IsWindow(m_hWnd));
  1028. }
  1029.  
  1030. void CPaintDC::Dump(CDumpContext& dc) const
  1031. {
  1032.     CDC::Dump(dc);
  1033.  
  1034.     dc << "m_hWnd = " << (UINT)m_hWnd;
  1035.     dc << "\nm_ps.hdc = " << (UINT)m_ps.hdc;
  1036.     dc << "\nm_ps.fErase = " << m_ps.fErase;
  1037.     dc << "\nm_ps.rcPaint = " << (CRect)m_ps.rcPaint;
  1038.  
  1039.     dc << "\n";
  1040. }
  1041. #endif
  1042.  
  1043. CPaintDC::CPaintDC(CWnd* pWnd)
  1044. {
  1045.     ASSERT_VALID(pWnd);
  1046.     ASSERT(::IsWindow(pWnd->m_hWnd));
  1047.  
  1048.     if (!Attach(::BeginPaint(m_hWnd = pWnd->m_hWnd, &m_ps)))
  1049.         AfxThrowResourceException();
  1050. }
  1051.  
  1052. CPaintDC::~CPaintDC()
  1053. {
  1054.     ASSERT(m_hDC != NULL);
  1055.     ASSERT(::IsWindow(m_hWnd));
  1056.  
  1057.     ::EndPaint(m_hWnd, &m_ps);
  1058.     Detach();
  1059. }
  1060.  
  1061. /////////////////////////////////////////////////////////////////////////////
  1062. // CGdiObject
  1063.  
  1064. #ifdef _DEBUG
  1065. void CGdiObject::Dump(CDumpContext& dc) const
  1066. {
  1067.     CObject::Dump(dc);
  1068.  
  1069.     dc << "m_hObject = " << (UINT)m_hObject;
  1070.     dc << "\n";
  1071. }
  1072.  
  1073. void CGdiObject::AssertValid() const
  1074. {
  1075.     CObject::AssertValid();
  1076.     ASSERT(m_hObject == NULL ||
  1077.         (afxData.bWin95 || ::GetObjectType(m_hObject) != 0));
  1078. }
  1079. #endif
  1080.  
  1081. #include "fixalloc.h"
  1082.  
  1083. class CTempGdiObject : public CGdiObject
  1084. {
  1085.     DECLARE_DYNCREATE(CTempGdiObject)
  1086.     DECLARE_FIXED_ALLOC(CTempGdiObject);
  1087. };
  1088.  
  1089. CHandleMap* PASCAL afxMapHGDIOBJ(BOOL bCreate)
  1090. {
  1091.     AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
  1092.     if (pState->m_pmapHGDIOBJ == NULL && bCreate)
  1093.     {
  1094.         BOOL bEnable = AfxEnableMemoryTracking(FALSE);
  1095. #ifndef _AFX_PORTABLE
  1096.         _PNH pnhOldHandler = AfxSetNewHandler(&AfxCriticalNewHandler);
  1097. #endif
  1098.         pState->m_pmapHGDIOBJ = new CHandleMap(RUNTIME_CLASS(CTempGdiObject),
  1099.             offsetof(CGdiObject, m_hObject));
  1100.  
  1101. #ifndef _AFX_PORTABLE
  1102.         AfxSetNewHandler(pnhOldHandler);
  1103. #endif
  1104.         AfxEnableMemoryTracking(bEnable);
  1105.     }
  1106.     return pState->m_pmapHGDIOBJ;
  1107. }
  1108.  
  1109. CGdiObject* PASCAL CGdiObject::FromHandle(HGDIOBJ h)
  1110. {
  1111.     CHandleMap* pMap = afxMapHGDIOBJ(TRUE); //create map if not exist
  1112.     ASSERT(pMap != NULL);
  1113.     CGdiObject* pObject = (CGdiObject*)pMap->FromHandle(h);
  1114.     ASSERT(pObject == NULL || pObject->m_hObject == h);
  1115.     return pObject;
  1116. }
  1117.  
  1118. BOOL CGdiObject::Attach(HGDIOBJ hObject)
  1119. {
  1120.     ASSERT(m_hObject == NULL);      // only attach once, detach on destroy
  1121.     if (hObject == NULL)
  1122.         return FALSE;
  1123.     CHandleMap* pMap = afxMapHGDIOBJ(TRUE); // create map if not exist
  1124.     ASSERT(pMap != NULL);
  1125.     pMap->SetPermanent(m_hObject = hObject, this);
  1126.     return TRUE;
  1127. }
  1128.  
  1129. HGDIOBJ CGdiObject::Detach()
  1130. {
  1131.     HGDIOBJ hObject = m_hObject;
  1132.     if (hObject != NULL)
  1133.     {
  1134.         CHandleMap* pMap = afxMapHGDIOBJ(); // don't create if not exist
  1135.         if (pMap != NULL)
  1136.             pMap->RemoveHandle(m_hObject);
  1137.     }
  1138.  
  1139.     m_hObject = NULL;
  1140.     return hObject;
  1141. }
  1142.  
  1143. BOOL CGdiObject::DeleteObject()
  1144. {
  1145.     if (m_hObject == NULL)
  1146.         return FALSE;
  1147.     return ::DeleteObject(Detach());
  1148. }
  1149.  
  1150. /////////////////////////////////////////////////////////////////////////////
  1151. // Standard GDI objects
  1152.  
  1153. /////////////////////////////////////////////////////////////////////////////
  1154. // CPen
  1155.  
  1156. CPen::CPen(int nPenStyle, int nWidth, COLORREF crColor)
  1157. {
  1158.     if (!Attach(::CreatePen(nPenStyle, nWidth, crColor)))
  1159.         AfxThrowResourceException();
  1160. }
  1161.  
  1162. CPen::CPen(int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush,
  1163.     int nStyleCount, const DWORD* lpStyle)
  1164. {
  1165.     if (!Attach(::ExtCreatePen(nPenStyle, nWidth, pLogBrush, nStyleCount,
  1166.             lpStyle)))
  1167.         AfxThrowResourceException();
  1168. }
  1169.  
  1170. /////////////////////////////////////////////////////////////////////////////
  1171.  
  1172. #ifdef _DEBUG
  1173. void CPen::Dump(CDumpContext& dc) const
  1174. {
  1175.     CGdiObject::Dump(dc);
  1176.  
  1177.     if (m_hObject == NULL)
  1178.         return;
  1179.  
  1180.     if (!afxData.bWin95 && ::GetObjectType(m_hObject) != OBJ_PEN)
  1181.     {
  1182.         // not a valid object
  1183.         dc << "has ILLEGAL HPEN!";
  1184.         return;
  1185.     }
  1186.  
  1187.     LOGPEN lp;
  1188.     VERIFY(GetObject(sizeof(lp), &lp));
  1189.     dc << "lgpn.lopnStyle = " << lp.lopnStyle;
  1190.     dc << "\nlgpn.lopnWidth.x (width) = " << lp.lopnWidth.x;
  1191.     dc << "\nlgpn.lopnColor = " << (void*)lp.lopnColor;
  1192.  
  1193.     dc << "\n";
  1194. }
  1195. #endif
  1196.  
  1197. /////////////////////////////////////////////////////////////////////////////
  1198. // CBrush
  1199.  
  1200. CBrush::CBrush(COLORREF crColor)
  1201. {
  1202.     if (!Attach(::CreateSolidBrush(crColor)))
  1203.         AfxThrowResourceException();
  1204. }
  1205.  
  1206. CBrush::CBrush(int nIndex, COLORREF crColor)
  1207. {
  1208.     if (!Attach(::CreateHatchBrush(nIndex, crColor)))
  1209.         AfxThrowResourceException();
  1210. }
  1211.  
  1212. CBrush::CBrush(CBitmap* pBitmap)
  1213. {
  1214.     ASSERT_VALID(pBitmap);
  1215.  
  1216.     if (!Attach(::CreatePatternBrush((HBITMAP)pBitmap->m_hObject)))
  1217.         AfxThrowResourceException();
  1218. }
  1219.  
  1220. BOOL CBrush::CreateDIBPatternBrush(HGLOBAL hPackedDIB, UINT nUsage)
  1221. {
  1222.     ASSERT(hPackedDIB != NULL);
  1223.     const void* lpPackedDIB = ::GlobalLock(hPackedDIB);
  1224.     ASSERT(lpPackedDIB != NULL);
  1225.     BOOL bResult = Attach(::CreateDIBPatternBrushPt(lpPackedDIB, nUsage));
  1226.     ::GlobalUnlock(hPackedDIB);
  1227.     return bResult;
  1228. }
  1229.  
  1230. #ifdef _DEBUG
  1231. void CBrush::Dump(CDumpContext& dc) const
  1232. {
  1233.     CGdiObject::Dump(dc);
  1234.  
  1235.     if (m_hObject == NULL)
  1236.         return;
  1237.  
  1238.     if (!afxData.bWin95 && ::GetObjectType(m_hObject) != OBJ_BRUSH)
  1239.     {
  1240.         // not a valid window
  1241.         dc << "has ILLEGAL HBRUSH!";
  1242.         return;
  1243.     }
  1244.  
  1245.     LOGBRUSH lb;
  1246.     VERIFY(GetObject(sizeof(lb), &lb));
  1247.     dc << "lb.lbStyle = " << lb.lbStyle;
  1248.     dc << "\nlb.lbHatch = " << lb.lbHatch;
  1249.     dc << "\nlb.lbColor = " << (void*)lb.lbColor;
  1250.  
  1251.     dc << "\n";
  1252. }
  1253. #endif
  1254.  
  1255. /////////////////////////////////////////////////////////////////////////////
  1256.  
  1257. #ifdef _DEBUG
  1258. void CFont::Dump(CDumpContext& dc) const
  1259. {
  1260.     CGdiObject::Dump(dc);
  1261.  
  1262.     if (m_hObject == NULL)
  1263.         return;
  1264.  
  1265.     if (!afxData.bWin95 && ::GetObjectType(m_hObject) != OBJ_FONT)
  1266.     {
  1267.         // not a valid GDI object
  1268.         dc << "has ILLEGAL HFONT!";
  1269.         return;
  1270.     }
  1271.  
  1272.     LOGFONT lf;
  1273.     VERIFY(GetObject(sizeof(lf), &lf));
  1274.     dc << "lf.lfHeight = " << lf.lfHeight;
  1275.     dc << "\nlf.lfWidth = " << lf.lfWidth;
  1276.     dc << "\nlf.lfEscapement = " << lf.lfEscapement;
  1277.     dc << "\nlf.lfOrientation = " << lf.lfOrientation;
  1278.     dc << "\nlf.lfWeight = " << lf.lfWeight;
  1279.     dc << "\nlf.lfItalic = " << (int)lf.lfItalic;
  1280.     dc << "\nlf.lfUnderline = " << (int)lf.lfUnderline;
  1281.     dc << "\nlf.lfStrikeOut = " << (int)lf.lfStrikeOut;
  1282.     dc << "\nlf.lfCharSet = " << (int)lf.lfCharSet;
  1283.     dc << "\nlf.lfOutPrecision = " << (int)lf.lfOutPrecision;
  1284.     dc << "\nlf.lfClipPrecision = " << (int)lf.lfClipPrecision;
  1285.     dc << "\nlf.lfQuality = " << (int)lf.lfQuality;
  1286.     dc << "\nlf.lfPitchAndFamily = " << (int)lf.lfPitchAndFamily;
  1287.     dc << "\nlf.lfFaceName = " << (LPCTSTR)lf.lfFaceName;
  1288.  
  1289.     dc << "\n";
  1290. }
  1291. #endif
  1292.  
  1293. /////////////////////////////////////////////////////////////////////////////
  1294.  
  1295. #ifdef _DEBUG
  1296. void CBitmap::Dump(CDumpContext& dc) const
  1297. {
  1298.     CGdiObject::Dump(dc);
  1299.  
  1300.     if (m_hObject == NULL)
  1301.         return;
  1302.  
  1303.     if (!afxData.bWin95 && ::GetObjectType(m_hObject) != OBJ_BITMAP)
  1304.     {
  1305.         // not a valid object
  1306.         dc << "has ILLEGAL HBITMAP!";
  1307.         return;
  1308.     }
  1309.  
  1310.     BITMAP bm;
  1311.     VERIFY(GetObject(sizeof(bm), &bm));
  1312.     dc << "bm.bmType = " << bm.bmType;
  1313.     dc << "\nbm.bmHeight = " << bm.bmHeight;
  1314.     dc << "\nbm.bmWidth = " << bm.bmWidth;
  1315.     dc << "\nbm.bmWidthBytes = " << bm.bmWidthBytes;
  1316.     dc << "\nbm.bmPlanes = " << bm.bmPlanes;
  1317.     dc << "\nbm.bmBitsPixel = " << bm.bmBitsPixel;
  1318.  
  1319.     dc << "\n";
  1320. }
  1321. #endif
  1322.  
  1323. #ifdef AFX_INIT_SEG
  1324. #pragma code_seg(AFX_INIT_SEG)
  1325. #endif
  1326.  
  1327. IMPLEMENT_DYNAMIC(CResourceException, CException)
  1328. CResourceException _simpleResourceException(FALSE, AFX_IDS_RESOURCE_EXCEPTION);
  1329.  
  1330. IMPLEMENT_DYNAMIC(CUserException, CException)
  1331. CUserException _simpleUserException(FALSE, AFX_IDS_USER_EXCEPTION);
  1332.  
  1333. IMPLEMENT_DYNCREATE(CDC, CObject)
  1334. IMPLEMENT_DYNAMIC(CClientDC, CDC)
  1335. IMPLEMENT_DYNAMIC(CWindowDC, CDC)
  1336. IMPLEMENT_DYNAMIC(CPaintDC, CDC)
  1337. IMPLEMENT_DYNCREATE(CGdiObject, CObject)
  1338.  
  1339. IMPLEMENT_DYNAMIC(CPen, CGdiObject)
  1340. IMPLEMENT_DYNAMIC(CBrush, CGdiObject)
  1341. IMPLEMENT_DYNAMIC(CFont, CGdiObject)
  1342. IMPLEMENT_DYNAMIC(CBitmap, CGdiObject)
  1343. IMPLEMENT_DYNAMIC(CPalette, CGdiObject)
  1344. IMPLEMENT_DYNAMIC(CRgn, CGdiObject)
  1345.  
  1346. IMPLEMENT_DYNCREATE(CTempDC, CDC);
  1347.  
  1348. IMPLEMENT_DYNCREATE(CTempGdiObject, CGdiObject);
  1349.  
  1350. /////////////////////////////////////////////////////////////////////////////
  1351. // Standard exception processing
  1352.  
  1353. #ifdef AFX_CORE2_SEG
  1354. #pragma code_seg(AFX_CORE2_SEG)
  1355. #endif
  1356.  
  1357. // resource failure
  1358. void AFXAPI AfxThrowResourceException()
  1359. {
  1360.     THROW((CResourceException*)&_simpleResourceException);
  1361. }
  1362.  
  1363. // user alert
  1364. void AFXAPI AfxThrowUserException()
  1365. {
  1366.     THROW((CUserException*)&_simpleUserException);
  1367. }
  1368.  
  1369. #ifdef AFX_INIT_SEG
  1370. #pragma code_seg(AFX_INIT_SEG)
  1371. #endif
  1372.  
  1373. #pragma warning(disable: 4074)
  1374. #pragma init_seg(compiler)
  1375. IMPLEMENT_FIXED_ALLOC(CTempDC, 64);
  1376. IMPLEMENT_FIXED_ALLOC(CTempGdiObject, 64);
  1377.  
  1378. /////////////////////////////////////////////////////////////////////////////
  1379.