home *** CD-ROM | disk | FTP | other *** search
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
-
- #include "stdafx.h"
-
- #ifdef AFX_CORE4_SEG
- #pragma code_seg(AFX_CORE4_SEG)
- #endif
-
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
-
- AFX_STATIC_DATA HBRUSH _afxHalftoneBrush = 0;
-
- void AFX_CDECL AfxWingdixTerm()
- {
- AfxDeleteObject((HGDIOBJ*)&_afxHalftoneBrush);
- }
- char _afxWingdixTerm = (char)atexit(&AfxWingdixTerm);
-
- /////////////////////////////////////////////////////////////////////////////
- // More coordinate transforms (in separate file to avoid transitive refs)
-
- #define HIMETRIC_INCH 2540 // HIMETRIC units per inch
-
- void CDC::DPtoHIMETRIC(LPSIZE lpSize) const
- {
- ASSERT(AfxIsValidAddress(lpSize, sizeof(SIZE)));
-
- int nMapMode;
- if (this != NULL && (nMapMode = GetMapMode()) < MM_ISOTROPIC &&
- nMapMode != MM_TEXT)
- {
- // when using a constrained map mode, map against physical inch
- ((CDC*)this)->SetMapMode(MM_HIMETRIC);
- DPtoLP(lpSize);
- ((CDC*)this)->SetMapMode(nMapMode);
- }
- else
- {
- // map against logical inch for non-constrained mapping modes
- int cxPerInch, cyPerInch;
- if (this != NULL)
- {
- ASSERT_VALID(this);
- ASSERT(m_hDC != NULL); // no HDC attached or created?
- cxPerInch = GetDeviceCaps(LOGPIXELSX);
- cyPerInch = GetDeviceCaps(LOGPIXELSY);
- }
- else
- {
- cxPerInch = afxData.cxPixelsPerInch;
- cyPerInch = afxData.cyPixelsPerInch;
- }
- ASSERT(cxPerInch != 0 && cyPerInch != 0);
- lpSize->cx = MulDiv(lpSize->cx, HIMETRIC_INCH, cxPerInch);
- lpSize->cy = MulDiv(lpSize->cy, HIMETRIC_INCH, cyPerInch);
- }
- }
-
- void CDC::HIMETRICtoDP(LPSIZE lpSize) const
- {
- ASSERT(AfxIsValidAddress(lpSize, sizeof(SIZE)));
-
- int nMapMode;
- if (this != NULL && (nMapMode = GetMapMode()) < MM_ISOTROPIC &&
- nMapMode != MM_TEXT)
- {
- // when using a constrained map mode, map against physical inch
- ((CDC*)this)->SetMapMode(MM_HIMETRIC);
- LPtoDP(lpSize);
- ((CDC*)this)->SetMapMode(nMapMode);
- }
- else
- {
- // map against logical inch for non-constrained mapping modes
- int cxPerInch, cyPerInch;
- if (this != NULL)
- {
- ASSERT_VALID(this);
- ASSERT(m_hDC != NULL); // no HDC attached or created?
- cxPerInch = GetDeviceCaps(LOGPIXELSX);
- cyPerInch = GetDeviceCaps(LOGPIXELSY);
- }
- else
- {
- cxPerInch = afxData.cxPixelsPerInch;
- cyPerInch = afxData.cyPixelsPerInch;
- }
- ASSERT(cxPerInch != 0 && cyPerInch != 0);
- lpSize->cx = MulDiv(lpSize->cx, cxPerInch, HIMETRIC_INCH);
- lpSize->cy = MulDiv(lpSize->cy, cyPerInch, HIMETRIC_INCH);
- }
- }
-
- void CDC::LPtoHIMETRIC(LPSIZE lpSize) const
- {
- ASSERT(AfxIsValidAddress(lpSize, sizeof(SIZE)));
-
- LPtoDP(lpSize);
- DPtoHIMETRIC(lpSize);
- }
-
- void CDC::HIMETRICtoLP(LPSIZE lpSize) const
- {
- ASSERT(AfxIsValidAddress(lpSize, sizeof(SIZE)));
-
- HIMETRICtoDP(lpSize);
- DPtoLP(lpSize);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // special CDC drawing primitives/helpers
-
- CBrush* PASCAL CDC::GetHalftoneBrush()
- {
- AfxLockGlobals(CRIT_HALFTONEBRUSH);
- if (_afxHalftoneBrush == NULL)
- {
- WORD grayPattern[8];
- for (int i = 0; i < 8; i++)
- grayPattern[i] = (WORD)(0x5555 << (i & 1));
- HBITMAP grayBitmap = CreateBitmap(8, 8, 1, 1, &grayPattern);
- if (grayBitmap != NULL)
- {
- _afxHalftoneBrush = ::CreatePatternBrush(grayBitmap);
- DeleteObject(grayBitmap);
- }
- }
- AfxUnlockGlobals(CRIT_HALFTONEBRUSH);
- return CBrush::FromHandle(_afxHalftoneBrush);
- }
-
- void CDC::DrawDragRect(LPCRECT lpRect, SIZE size,
- LPCRECT lpRectLast, SIZE sizeLast, CBrush* pBrush, CBrush* pBrushLast)
- {
- ASSERT(AfxIsValidAddress(lpRect, sizeof(RECT), FALSE));
- ASSERT(lpRectLast == NULL ||
- AfxIsValidAddress(lpRectLast, sizeof(RECT), FALSE));
-
- // first, determine the update region and select it
- CRgn rgnNew;
- CRgn rgnOutside, rgnInside;
- rgnOutside.CreateRectRgnIndirect(lpRect);
- CRect rect = *lpRect;
- rect.InflateRect(-size.cx, -size.cy);
- rect.IntersectRect(rect, lpRect);
- rgnInside.CreateRectRgnIndirect(rect);
- rgnNew.CreateRectRgn(0, 0, 0, 0);
- rgnNew.CombineRgn(&rgnOutside, &rgnInside, RGN_XOR);
-
- CBrush* pBrushOld = NULL;
- if (pBrush == NULL)
- pBrush = CDC::GetHalftoneBrush();
- if (pBrushLast == NULL)
- pBrushLast = pBrush;
-
- CRgn rgnLast, rgnUpdate;
- if (lpRectLast != NULL)
- {
- // find difference between new region and old region
- rgnLast.CreateRectRgn(0, 0, 0, 0);
- rgnOutside.SetRectRgn(lpRectLast);
- rect = *lpRectLast;
- rect.InflateRect(-sizeLast.cx, -sizeLast.cy);
- rect.IntersectRect(rect, lpRectLast);
- rgnInside.SetRectRgn(rect);
- rgnLast.CombineRgn(&rgnOutside, &rgnInside, RGN_XOR);
-
- // only diff them if brushes are the same
- if (pBrush->m_hObject == pBrushLast->m_hObject)
- {
- rgnUpdate.CreateRectRgn(0, 0, 0, 0);
- rgnUpdate.CombineRgn(&rgnLast, &rgnNew, RGN_XOR);
- }
- }
- if (pBrush->m_hObject != pBrushLast->m_hObject && lpRectLast != NULL)
- {
- // brushes are different -- erase old region first
- SelectClipRgn(&rgnLast);
- GetClipBox(&rect);
- pBrushOld = SelectObject(pBrushLast);
- PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATINVERT);
- SelectObject(pBrushOld);
- pBrushOld = NULL;
- }
-
- // draw into the update/new region
- SelectClipRgn(rgnUpdate.m_hObject != NULL ? &rgnUpdate : &rgnNew);
- GetClipBox(&rect);
- pBrushOld = SelectObject(pBrush);
- PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATINVERT);
-
- // cleanup DC
- if (pBrushOld != NULL)
- SelectObject(pBrushOld);
- SelectClipRgn(NULL);
- }
-
- void CDC::FillSolidRect(LPCRECT lpRect, COLORREF clr)
- {
- ASSERT_VALID(this);
- ASSERT(m_hDC != NULL);
-
- ::SetBkColor(m_hDC, clr);
- ::ExtTextOut(m_hDC, 0, 0, ETO_OPAQUE, lpRect, NULL, 0, NULL);
- }
-
- void CDC::FillSolidRect(int x, int y, int cx, int cy, COLORREF clr)
- {
- ASSERT_VALID(this);
- ASSERT(m_hDC != NULL);
-
- ::SetBkColor(m_hDC, clr);
- CRect rect(x, y, x + cx, y + cy);
- ::ExtTextOut(m_hDC, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
- }
-
- void CDC::Draw3dRect(LPCRECT lpRect,
- COLORREF clrTopLeft, COLORREF clrBottomRight)
- {
- Draw3dRect(lpRect->left, lpRect->top, lpRect->right - lpRect->left,
- lpRect->bottom - lpRect->top, clrTopLeft, clrBottomRight);
- }
-
- void CDC::Draw3dRect(int x, int y, int cx, int cy,
- COLORREF clrTopLeft, COLORREF clrBottomRight)
- {
- FillSolidRect(x, y, cx - 1, 1, clrTopLeft);
- FillSolidRect(x, y, 1, cy - 1, clrTopLeft);
- FillSolidRect(x + cx, y, -1, cy, clrBottomRight);
- FillSolidRect(x, y + cy, cx, -1, clrBottomRight);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // out-of-line CBrush, CFont, etc. helpers
-
- // nPointSize is actually scaled 10x
- BOOL CFont::CreatePointFont(int nPointSize, LPCTSTR lpszFaceName, CDC* pDC)
- {
- ASSERT(AfxIsValidString(lpszFaceName));
-
- LOGFONT logFont;
- memset(&logFont, 0, sizeof(LOGFONT));
- logFont.lfCharSet = DEFAULT_CHARSET;
- logFont.lfHeight = nPointSize;
- lstrcpyn(logFont.lfFaceName, lpszFaceName, _countof(logFont.lfFaceName));
-
- return CreatePointFontIndirect(&logFont, pDC);
- }
-
- // pLogFont->nHeight is interpreted as PointSize * 10
- BOOL CFont::CreatePointFontIndirect(const LOGFONT* lpLogFont, CDC* pDC)
- {
- ASSERT(AfxIsValidAddress(lpLogFont, sizeof(LOGFONT), FALSE));
- HDC hDC;
- if (pDC != NULL)
- {
- ASSERT_VALID(pDC);
- ASSERT(pDC->m_hAttribDC != NULL);
- hDC = pDC->m_hAttribDC;
- }
- else
- hDC = ::GetDC(NULL);
-
- // convert nPointSize to logical units based on pDC
- LOGFONT logFont = *lpLogFont;
- POINT pt;
- pt.y = ::GetDeviceCaps(hDC, LOGPIXELSY) * logFont.lfHeight;
- pt.y /= 720; // 72 points/inch, 10 decipoints/point
- ::DPtoLP(hDC, &pt, 1);
- POINT ptOrg = { 0, 0 };
- ::DPtoLP(hDC, &ptOrg, 1);
- logFont.lfHeight = -abs(pt.y - ptOrg.y);
-
- if (pDC == NULL)
- ReleaseDC(NULL, hDC);
-
- return CreateFontIndirect(&logFont);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // out-of-line CRect, CSize, etc. helpers
-
- void CRect::NormalizeRect()
- {
- int nTemp;
- if (left > right)
- {
- nTemp = left;
- left = right;
- right = nTemp;
- }
- if (top > bottom)
- {
- nTemp = top;
- top = bottom;
- bottom = nTemp;
- }
- }
-
- void CRect::InflateRect(LPCRECT lpRect)
- {
- left -= lpRect->left;
- top -= lpRect->top;
- right += lpRect->right;
- bottom += lpRect->bottom;
- }
-
- void CRect::InflateRect(int l, int t, int r, int b)
- {
- left -= l;
- top -= t;
- right += r;
- bottom += b;
- }
-
- void CRect::DeflateRect(LPCRECT lpRect)
- {
- left += lpRect->left;
- top += lpRect->top;
- right -= lpRect->right;
- bottom -= lpRect->bottom;
- }
-
- void CRect::DeflateRect(int l, int t, int r, int b)
- {
- left += l;
- top += t;
- right -= r;
- bottom -= b;
- }
-
- CRect CRect::MulDiv(int nMultiplier, int nDivisor) const
- {
- return CRect(
- ::MulDiv(left, nMultiplier, nDivisor),
- ::MulDiv(top, nMultiplier, nDivisor),
- ::MulDiv(right, nMultiplier, nDivisor),
- ::MulDiv(bottom, nMultiplier, nDivisor));
- }
-
- /////////////////////////////////////////////////////////////////////////////
-