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 >
Wrap
C/C++ Source or Header
|
1998-06-16
|
9KB
|
353 lines
// 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));
}
/////////////////////////////////////////////////////////////////////////////