home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / wingdix.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  9KB  |  353 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_CORE4_SEG
  14. #pragma code_seg(AFX_CORE4_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. AFX_STATIC_DATA HBRUSH _afxHalftoneBrush = 0;
  23.  
  24. void AFX_CDECL AfxWingdixTerm()
  25. {
  26.     AfxDeleteObject((HGDIOBJ*)&_afxHalftoneBrush);
  27. }
  28. char _afxWingdixTerm = (char)atexit(&AfxWingdixTerm);
  29.  
  30. /////////////////////////////////////////////////////////////////////////////
  31. // More coordinate transforms (in separate file to avoid transitive refs)
  32.  
  33. #define HIMETRIC_INCH   2540    // HIMETRIC units per inch
  34.  
  35. void CDC::DPtoHIMETRIC(LPSIZE lpSize) const
  36. {
  37.     ASSERT(AfxIsValidAddress(lpSize, sizeof(SIZE)));
  38.  
  39.     int nMapMode;
  40.     if (this != NULL && (nMapMode = GetMapMode()) < MM_ISOTROPIC &&
  41.         nMapMode != MM_TEXT)
  42.     {
  43.         // when using a constrained map mode, map against physical inch
  44.         ((CDC*)this)->SetMapMode(MM_HIMETRIC);
  45.         DPtoLP(lpSize);
  46.         ((CDC*)this)->SetMapMode(nMapMode);
  47.     }
  48.     else
  49.     {
  50.         // map against logical inch for non-constrained mapping modes
  51.         int cxPerInch, cyPerInch;
  52.         if (this != NULL)
  53.         {
  54.             ASSERT_VALID(this);
  55.             ASSERT(m_hDC != NULL);  // no HDC attached or created?
  56.             cxPerInch = GetDeviceCaps(LOGPIXELSX);
  57.             cyPerInch = GetDeviceCaps(LOGPIXELSY);
  58.         }
  59.         else
  60.         {
  61.             cxPerInch = afxData.cxPixelsPerInch;
  62.             cyPerInch = afxData.cyPixelsPerInch;
  63.         }
  64.         ASSERT(cxPerInch != 0 && cyPerInch != 0);
  65.         lpSize->cx = MulDiv(lpSize->cx, HIMETRIC_INCH, cxPerInch);
  66.         lpSize->cy = MulDiv(lpSize->cy, HIMETRIC_INCH, cyPerInch);
  67.     }
  68. }
  69.  
  70. void CDC::HIMETRICtoDP(LPSIZE lpSize) const
  71. {
  72.     ASSERT(AfxIsValidAddress(lpSize, sizeof(SIZE)));
  73.  
  74.     int nMapMode;
  75.     if (this != NULL && (nMapMode = GetMapMode()) < MM_ISOTROPIC &&
  76.         nMapMode != MM_TEXT)
  77.     {
  78.         // when using a constrained map mode, map against physical inch
  79.         ((CDC*)this)->SetMapMode(MM_HIMETRIC);
  80.         LPtoDP(lpSize);
  81.         ((CDC*)this)->SetMapMode(nMapMode);
  82.     }
  83.     else
  84.     {
  85.         // map against logical inch for non-constrained mapping modes
  86.         int cxPerInch, cyPerInch;
  87.         if (this != NULL)
  88.         {
  89.             ASSERT_VALID(this);
  90.             ASSERT(m_hDC != NULL);  // no HDC attached or created?
  91.             cxPerInch = GetDeviceCaps(LOGPIXELSX);
  92.             cyPerInch = GetDeviceCaps(LOGPIXELSY);
  93.         }
  94.         else
  95.         {
  96.             cxPerInch = afxData.cxPixelsPerInch;
  97.             cyPerInch = afxData.cyPixelsPerInch;
  98.         }
  99.         ASSERT(cxPerInch != 0 && cyPerInch != 0);
  100.         lpSize->cx = MulDiv(lpSize->cx, cxPerInch, HIMETRIC_INCH);
  101.         lpSize->cy = MulDiv(lpSize->cy, cyPerInch, HIMETRIC_INCH);
  102.     }
  103. }
  104.  
  105. void CDC::LPtoHIMETRIC(LPSIZE lpSize) const
  106. {
  107.     ASSERT(AfxIsValidAddress(lpSize, sizeof(SIZE)));
  108.  
  109.     LPtoDP(lpSize);
  110.     DPtoHIMETRIC(lpSize);
  111. }
  112.  
  113. void CDC::HIMETRICtoLP(LPSIZE lpSize) const
  114. {
  115.     ASSERT(AfxIsValidAddress(lpSize, sizeof(SIZE)));
  116.  
  117.     HIMETRICtoDP(lpSize);
  118.     DPtoLP(lpSize);
  119. }
  120.  
  121. /////////////////////////////////////////////////////////////////////////////
  122. // special CDC drawing primitives/helpers
  123.  
  124. CBrush* PASCAL CDC::GetHalftoneBrush()
  125. {
  126.     AfxLockGlobals(CRIT_HALFTONEBRUSH);
  127.     if (_afxHalftoneBrush == NULL)
  128.     {
  129.         WORD grayPattern[8];
  130.         for (int i = 0; i < 8; i++)
  131.             grayPattern[i] = (WORD)(0x5555 << (i & 1));
  132.         HBITMAP grayBitmap = CreateBitmap(8, 8, 1, 1, &grayPattern);
  133.         if (grayBitmap != NULL)
  134.         {
  135.             _afxHalftoneBrush = ::CreatePatternBrush(grayBitmap);
  136.             DeleteObject(grayBitmap);
  137.         }
  138.     }
  139.     AfxUnlockGlobals(CRIT_HALFTONEBRUSH);
  140.     return CBrush::FromHandle(_afxHalftoneBrush);
  141. }
  142.  
  143. void CDC::DrawDragRect(LPCRECT lpRect, SIZE size,
  144.     LPCRECT lpRectLast, SIZE sizeLast, CBrush* pBrush, CBrush* pBrushLast)
  145. {
  146.     ASSERT(AfxIsValidAddress(lpRect, sizeof(RECT), FALSE));
  147.     ASSERT(lpRectLast == NULL ||
  148.         AfxIsValidAddress(lpRectLast, sizeof(RECT), FALSE));
  149.  
  150.     // first, determine the update region and select it
  151.     CRgn rgnNew;
  152.     CRgn rgnOutside, rgnInside;
  153.     rgnOutside.CreateRectRgnIndirect(lpRect);
  154.     CRect rect = *lpRect;
  155.     rect.InflateRect(-size.cx, -size.cy);
  156.     rect.IntersectRect(rect, lpRect);
  157.     rgnInside.CreateRectRgnIndirect(rect);
  158.     rgnNew.CreateRectRgn(0, 0, 0, 0);
  159.     rgnNew.CombineRgn(&rgnOutside, &rgnInside, RGN_XOR);
  160.  
  161.     CBrush* pBrushOld = NULL;
  162.     if (pBrush == NULL)
  163.         pBrush = CDC::GetHalftoneBrush();
  164.     if (pBrushLast == NULL)
  165.         pBrushLast = pBrush;
  166.  
  167.     CRgn rgnLast, rgnUpdate;
  168.     if (lpRectLast != NULL)
  169.     {
  170.         // find difference between new region and old region
  171.         rgnLast.CreateRectRgn(0, 0, 0, 0);
  172.         rgnOutside.SetRectRgn(lpRectLast);
  173.         rect = *lpRectLast;
  174.         rect.InflateRect(-sizeLast.cx, -sizeLast.cy);
  175.         rect.IntersectRect(rect, lpRectLast);
  176.         rgnInside.SetRectRgn(rect);
  177.         rgnLast.CombineRgn(&rgnOutside, &rgnInside, RGN_XOR);
  178.  
  179.         // only diff them if brushes are the same
  180.         if (pBrush->m_hObject == pBrushLast->m_hObject)
  181.         {
  182.             rgnUpdate.CreateRectRgn(0, 0, 0, 0);
  183.             rgnUpdate.CombineRgn(&rgnLast, &rgnNew, RGN_XOR);
  184.         }
  185.     }
  186.     if (pBrush->m_hObject != pBrushLast->m_hObject && lpRectLast != NULL)
  187.     {
  188.         // brushes are different -- erase old region first
  189.         SelectClipRgn(&rgnLast);
  190.         GetClipBox(&rect);
  191.         pBrushOld = SelectObject(pBrushLast);
  192.         PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATINVERT);
  193.         SelectObject(pBrushOld);
  194.         pBrushOld = NULL;
  195.     }
  196.  
  197.     // draw into the update/new region
  198.     SelectClipRgn(rgnUpdate.m_hObject != NULL ? &rgnUpdate : &rgnNew);
  199.     GetClipBox(&rect);
  200.     pBrushOld = SelectObject(pBrush);
  201.     PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATINVERT);
  202.  
  203.     // cleanup DC
  204.     if (pBrushOld != NULL)
  205.         SelectObject(pBrushOld);
  206.     SelectClipRgn(NULL);
  207. }
  208.  
  209. void CDC::FillSolidRect(LPCRECT lpRect, COLORREF clr)
  210. {
  211.     ASSERT_VALID(this);
  212.     ASSERT(m_hDC != NULL);
  213.  
  214.     ::SetBkColor(m_hDC, clr);
  215.     ::ExtTextOut(m_hDC, 0, 0, ETO_OPAQUE, lpRect, NULL, 0, NULL);
  216. }
  217.  
  218. void CDC::FillSolidRect(int x, int y, int cx, int cy, COLORREF clr)
  219. {
  220.     ASSERT_VALID(this);
  221.     ASSERT(m_hDC != NULL);
  222.  
  223.     ::SetBkColor(m_hDC, clr);
  224.     CRect rect(x, y, x + cx, y + cy);
  225.     ::ExtTextOut(m_hDC, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
  226. }
  227.  
  228. void CDC::Draw3dRect(LPCRECT lpRect,
  229.     COLORREF clrTopLeft, COLORREF clrBottomRight)
  230. {
  231.     Draw3dRect(lpRect->left, lpRect->top, lpRect->right - lpRect->left,
  232.         lpRect->bottom - lpRect->top, clrTopLeft, clrBottomRight);
  233. }
  234.  
  235. void CDC::Draw3dRect(int x, int y, int cx, int cy,
  236.     COLORREF clrTopLeft, COLORREF clrBottomRight)
  237. {
  238.     FillSolidRect(x, y, cx - 1, 1, clrTopLeft);
  239.     FillSolidRect(x, y, 1, cy - 1, clrTopLeft);
  240.     FillSolidRect(x + cx, y, -1, cy, clrBottomRight);
  241.     FillSolidRect(x, y + cy, cx, -1, clrBottomRight);
  242. }
  243.  
  244. /////////////////////////////////////////////////////////////////////////////
  245. // out-of-line CBrush, CFont, etc. helpers
  246.  
  247. // nPointSize is actually scaled 10x
  248. BOOL CFont::CreatePointFont(int nPointSize, LPCTSTR lpszFaceName, CDC* pDC)
  249. {
  250.     ASSERT(AfxIsValidString(lpszFaceName));
  251.  
  252.     LOGFONT logFont;
  253.     memset(&logFont, 0, sizeof(LOGFONT));
  254.     logFont.lfCharSet = DEFAULT_CHARSET;
  255.     logFont.lfHeight = nPointSize;
  256.     lstrcpyn(logFont.lfFaceName, lpszFaceName, _countof(logFont.lfFaceName));
  257.  
  258.     return CreatePointFontIndirect(&logFont, pDC);
  259. }
  260.  
  261. // pLogFont->nHeight is interpreted as PointSize * 10
  262. BOOL CFont::CreatePointFontIndirect(const LOGFONT* lpLogFont, CDC* pDC)
  263. {
  264.     ASSERT(AfxIsValidAddress(lpLogFont, sizeof(LOGFONT), FALSE));
  265.     HDC hDC;
  266.     if (pDC != NULL)
  267.     {
  268.         ASSERT_VALID(pDC);
  269.         ASSERT(pDC->m_hAttribDC != NULL);
  270.         hDC = pDC->m_hAttribDC;
  271.     }
  272.     else
  273.         hDC = ::GetDC(NULL);
  274.  
  275.     // convert nPointSize to logical units based on pDC
  276.     LOGFONT logFont = *lpLogFont;
  277.     POINT pt;
  278.     pt.y = ::GetDeviceCaps(hDC, LOGPIXELSY) * logFont.lfHeight;
  279.     pt.y /= 720;    // 72 points/inch, 10 decipoints/point
  280.     ::DPtoLP(hDC, &pt, 1);
  281.     POINT ptOrg = { 0, 0 };
  282.     ::DPtoLP(hDC, &ptOrg, 1);
  283.     logFont.lfHeight = -abs(pt.y - ptOrg.y);
  284.  
  285.     if (pDC == NULL)
  286.         ReleaseDC(NULL, hDC);
  287.  
  288.     return CreateFontIndirect(&logFont);
  289. }
  290.  
  291. /////////////////////////////////////////////////////////////////////////////
  292. // out-of-line CRect, CSize, etc. helpers
  293.  
  294. void CRect::NormalizeRect()
  295. {
  296.     int nTemp;
  297.     if (left > right)
  298.     {
  299.         nTemp = left;
  300.         left = right;
  301.         right = nTemp;
  302.     }
  303.     if (top > bottom)
  304.     {
  305.         nTemp = top;
  306.         top = bottom;
  307.         bottom = nTemp;
  308.     }
  309. }
  310.  
  311. void CRect::InflateRect(LPCRECT lpRect)
  312. {
  313.     left -= lpRect->left;
  314.     top -= lpRect->top;
  315.     right += lpRect->right;
  316.     bottom += lpRect->bottom;
  317. }
  318.  
  319. void CRect::InflateRect(int l, int t, int r, int b)
  320. {
  321.     left -= l;
  322.     top -= t;
  323.     right += r;
  324.     bottom += b;
  325. }
  326.  
  327. void CRect::DeflateRect(LPCRECT lpRect)
  328. {
  329.     left += lpRect->left;
  330.     top += lpRect->top;
  331.     right -= lpRect->right;
  332.     bottom -= lpRect->bottom;
  333. }
  334.  
  335. void CRect::DeflateRect(int l, int t, int r, int b)
  336. {
  337.     left += l;
  338.     top += t;
  339.     right -= r;
  340.     bottom -= b;
  341. }
  342.  
  343. CRect CRect::MulDiv(int nMultiplier, int nDivisor) const
  344. {
  345.     return CRect(
  346.         ::MulDiv(left, nMultiplier, nDivisor),
  347.         ::MulDiv(top, nMultiplier, nDivisor),
  348.         ::MulDiv(right, nMultiplier, nDivisor),
  349.         ::MulDiv(bottom, nMultiplier, nDivisor));
  350. }
  351.  
  352. /////////////////////////////////////////////////////////////////////////////
  353.