mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
356 lines
8.9 KiB
356 lines
8.9 KiB
// This is a part of the Microsoft Foundation Classes C++ library.
|
|
// Copyright (C) 1992-1995 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
|
|
|
|
static HBRUSH halftoneBrush;
|
|
|
|
struct _AFX_WINGDIX_TERM
|
|
{
|
|
~_AFX_WINGDIX_TERM()
|
|
{
|
|
AfxDeleteObject((HGDIOBJ*)&halftoneBrush);
|
|
}
|
|
};
|
|
|
|
static const _AFX_WINGDIX_TERM wingdixTerm;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// 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 (halftoneBrush == 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)
|
|
{
|
|
halftoneBrush = ::CreatePatternBrush(grayBitmap);
|
|
DeleteObject(grayBitmap);
|
|
}
|
|
}
|
|
AfxUnlockGlobals(CRIT_HALFTONEBRUSH);
|
|
return CBrush::FromHandle(halftoneBrush);
|
|
}
|
|
|
|
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));
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|