home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / WINGDIX.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-30  |  9.2 KB  |  357 lines

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