// This is a part of the Microsoft Foundation Classes C++ library. // Copyright (C) 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" AFX_STATIC_DATA HBRUSH _afxHalftoneBrush = 0; void AFX_CDECL AfxWingdixTerm() { AfxDeleteObject((HGDIOBJ*)&_afxHalftoneBrush); } char _afxWingdixTerm = 0; ///////////////////////////////////////////////////////////////////////////// // 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))); #ifndef _WIN32_WCE 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); } #else // !_WIN32_WCE double lfLogX = GetDeviceCaps(LOGPIXELSX); // pts/in double lfLogY = GetDeviceCaps(LOGPIXELSY); // pts/in // convert: pts in cm .01mm lpSize->cx = (int)(lpSize->cx / lfLogX * 2.54 * 1000.0); lpSize->cy = (int)(lpSize->cy / lfLogY * 2.54 * 1000.0); #endif // !_WIN32_WCE } void CDC::HIMETRICtoDP(LPSIZE lpSize) const { ASSERT(AfxIsValidAddress(lpSize, sizeof(SIZE))); #ifndef _WIN32_WCE // because of MM_TEXT assumption 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); } #else // !_WIN32_WCE double lfLogX = GetDeviceCaps(LOGPIXELSX); // pts/in double lfLogY = GetDeviceCaps(LOGPIXELSY); // pts/in // convert: .01mm cm in pts lpSize->cx = (int)(lpSize->cx / 1000.0 * lfLogX / 2.54 ); lpSize->cy = (int)(lpSize->cy / 1000.0 * lfLogY / 2.54 ); #endif // !_WIN32_WCE } void CDC::LPtoHIMETRIC(LPSIZE lpSize) const { ASSERT(AfxIsValidAddress(lpSize, sizeof(SIZE))); #ifndef _WIN32_WCE // because of MM_TEXT assumption LPtoDP(lpSize); #endif // !_WIN32_WCE DPtoHIMETRIC(lpSize); } void CDC::HIMETRICtoLP(LPSIZE lpSize) const { ASSERT(AfxIsValidAddress(lpSize, sizeof(SIZE))); HIMETRICtoDP(lpSize); #ifndef _WIN32_WCE // because of MM_TEXT assumption DPtoLP(lpSize); #endif // !_WIN32_WCE } ///////////////////////////////////////////////////////////////////////////// // 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); } } if (!_afxWingdixTerm) _afxWingdixTerm = (char)!atexit(&AfxWingdixTerm); 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(); } ENSURE(pBrush); 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) { ENSURE_VALID(this); ENSURE(m_hDC != NULL); ENSURE(lpRect); ::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; Checked::tcsncpy_s(logFont.lfFaceName, _countof(logFont.lfFaceName), lpszFaceName, _TRUNCATE); 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; #ifndef _AFX_NO_GDITRANSFORM_SUPPORT POINT pt; // 72 points/inch, 10 decipoints/point pt.y = ::MulDiv(::GetDeviceCaps(hDC, LOGPIXELSY), logFont.lfHeight, 720); pt.x = 0; ::DPtoLP(hDC, &pt, 1); POINT ptOrg = { 0, 0 }; ::DPtoLP(hDC, &ptOrg, 1); logFont.lfHeight = -abs(pt.y - ptOrg.y); #else // DP and LP are always the same on CE logFont.lfHeight = ::GetDeviceCaps(hDC, LOGPIXELSY) * logFont.lfHeight; logFont.lfHeight /= 720; // 72 points/inch, 10 decipoints/point if(logFont.lfHeight > 0) { logFont.lfHeight *= -1; } #endif // !_AFX_NO_GDITRANSFORM_SUPPORT if (pDC == NULL) ReleaseDC(NULL, hDC); return CreateFontIndirect(&logFont); } /////////////////////////////////////////////////////////////////////////////