⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dcprev.cpp

📁 vc6.0完整版
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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_PRINT_SEG
#pragma code_seg(AFX_PRINT_SEG)
#endif

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define new DEBUG_NEW

/////////////////////////////////////////////////////////////////////////////
// Helper functions

AFX_STATIC long AFXAPI _AfxMultMultDivDiv(
	int factor, int num1, int num2,
	int den1, int den2)
{
#ifdef _AFX_PORTABLE
	// make sure that (num1 * num2) does not overflow 31-bits.
	long temp = num1 < 0 ? -num1 : num1;
	for (int nBitsResult = 0; temp != 0; nBitsResult++)
		temp >>= 1;
	temp = num2 < 0 ? -num2 : num2;
	for (; temp != 0; nBitsResult++)
		temp >>= 1;
	if (nBitsResult > 31)
	{
		num1 >>= nBitsResult - 31;
		num2 >>= nBitsResult - 31;
	}

	// make sure that (den1 * den2) does not overflow 31-bits
	temp = den1 < 0 ? -den1 : den1;
	for (nBitsResult = 0; temp != 0; nBitsResult++)
		temp >>= 1;
	temp = den2 < 0 ? -den2 : den2;
	for (; temp != 0; nBitsResult++)
		temp >>= 1;
	if (nBitsResult > 31)
	{
		den1 >>= nBitsResult - 31;
		den2 >>= nBitsResult - 31;
	}

	long numerator = (long)num1 * (long)num2;   // no overflow
	long denominator = (long)den1 * (long)den2; // no overflow
#else
	__int64 numerator = (__int64)num1 * (__int64)num2;   // no overflow
	__int64 denominator = (__int64)den1 * (__int64)den2; // no overflow
	__int64 temp;
#endif

	temp = numerator < 0 ? -numerator : numerator;
	for (int nBitsInNum = 0; temp != 0; nBitsInNum++)
		temp >>= 1;

	temp = factor < 0 ? -factor : factor;
	for (int nBitsInFactor = 0; temp != 0; nBitsInFactor++)
		temp >>= 1;

	nBitsInNum += nBitsInFactor;

	//
	// normalizing the denominator to positive results in an easier
	// determination of whether there is overflow
	//
	if (denominator < 0)
	{
		denominator = -denominator;
		numerator = -numerator;
	}

	// Get the product of factor * numerator representable in a long/__int64
	// while distributing loss of presision across all three numerator terms
	// Adjust denominator as well
	//
	while (nBitsInNum-- > 31)
	{
		numerator >>= 1;
		denominator >>= 1;
		if (nBitsInNum-- <= 31)
			break;
		numerator >>= 1;
		denominator >>= 1;
		if (nBitsInNum-- <= 31)
			break;
		factor >>= 1;
		denominator >>= 1;
	}
	numerator *= factor;

	if (denominator == 0)
		return numerator < 0 ? LONG_MIN : LONG_MAX;

	return (long) ((numerator + denominator/2) / denominator);
}

/////////////////////////////////////////////////////////////////////////////
// Print Preview DC (CPreviewDC)

CPreviewDC::CPreviewDC()
{
	// Initial scale factor and top-left offset
	m_nScaleNum = m_nScaleDen = 1;
	m_sizeTopLeft.cx = m_sizeTopLeft.cy = 8;
	m_hFont = m_hPrinterFont = NULL;
}

void CPreviewDC::SetOutputDC(HDC hDC)
{
	ASSERT(hDC != NULL);
	m_nSaveDCIndex = ::SaveDC(hDC); // restore in ReleaseOutputDC()
	CDC::SetOutputDC(hDC);

	if (m_hAttribDC != NULL)
	{
		MirrorMappingMode(FALSE);

		if (m_hFont)
			::SelectObject(m_hDC, m_hFont);
		else
			MirrorFont();
		MirrorAttributes();
	}
}

void CPreviewDC::ReleaseOutputDC()
{
	ASSERT(m_hDC != NULL);
	::RestoreDC(m_hDC, m_nSaveDCIndex); // Saved in SetOutputDC()
	CDC::ReleaseOutputDC();
}

void CPreviewDC::SetAttribDC(HDC hDC)
{
	ASSERT(hDC != NULL);
	CDC::SetAttribDC(hDC);

	MirrorMappingMode(TRUE);
	MirrorFont();
	MirrorAttributes();
}

CPreviewDC::~CPreviewDC()
{
	ASSERT(m_hDC == NULL);      // Should not have a screen DC at this time
	AfxDeleteObject((HGDIOBJ*)&m_hFont);
}

void CPreviewDC::SetScaleRatio(int nNumerator, int nDenominator)
{
	m_nScaleNum = nNumerator;
	m_nScaleDen = nDenominator;
	if (m_hAttribDC != NULL)
	{
		MirrorMappingMode(TRUE);
		MirrorFont();
	}
}

// Implementation support
#ifdef _DEBUG
void CPreviewDC::AssertValid() const
{
	CDC::AssertValid();
}


void CPreviewDC::Dump(CDumpContext& dc) const
{
	CDC::Dump(dc);

	dc << "Scale Factor: " << m_nScaleNum << "/" << m_nScaleDen;
	dc << "\n";
}
#endif

int CPreviewDC::SaveDC()
{
	ASSERT(m_hAttribDC != NULL);
	int nAttribIndex = ::SaveDC(m_hAttribDC);
	if (m_hDC != NULL)
	{
		// remove font from object
		::SelectObject(m_hDC, GetStockObject(SYSTEM_FONT));
		m_nSaveDCDelta = ::SaveDC(m_hDC) - nAttribIndex;
		// Select font back in after save
		::SelectObject(m_hDC, m_hFont);
	}
	else
	{
		m_nSaveDCDelta = 0x7fff;        // impossibly high value
	}
	return nAttribIndex;
}

BOOL CPreviewDC::RestoreDC(int nSavedDC)
{
	ASSERT(m_hAttribDC != NULL);
	BOOL bSuccess = ::RestoreDC(m_hAttribDC, nSavedDC);
	if (bSuccess)
	{
		if (m_nSaveDCDelta != 0x7fff)
		{
			ASSERT(m_hDC != NULL);      // removed Output DC after save

			if (nSavedDC != -1)
				nSavedDC += m_nSaveDCDelta;
			bSuccess = ::RestoreDC(m_hDC, nSavedDC);
			MirrorFont();               // mirror the font
		}
		else
		{
			ASSERT(m_hDC == NULL);      // Added the Output DC after save
		}
	}
	return bSuccess;
}

void CPreviewDC::MirrorAttributes()
{
	ASSERT(m_hAttribDC != NULL);

	if (m_hDC != NULL)
	{
		// extract and re-set Pen and Brush
		HGDIOBJ hTemp = ::SelectObject(m_hAttribDC, ::GetStockObject(BLACK_PEN));
		::SelectObject(m_hAttribDC, hTemp);
		::SelectObject(m_hDC, hTemp);
		hTemp = ::SelectObject(m_hAttribDC, ::GetStockObject(BLACK_BRUSH));
		::SelectObject(m_hAttribDC, hTemp);
		::SelectObject(m_hDC, hTemp);

		SetROP2(GetROP2());
		SetBkMode(GetBkMode());
		SetTextAlign(GetTextAlign());
		SetPolyFillMode(GetPolyFillMode());
		SetStretchBltMode(GetStretchBltMode());
		SetTextColor(GetNearestColor(GetTextColor()));
		SetBkColor(GetNearestColor(GetBkColor()));
	}
}

CGdiObject* CPreviewDC::SelectStockObject(int nIndex)
{
	ASSERT(m_hAttribDC != NULL);

	HGDIOBJ hObj = ::GetStockObject(nIndex);

	switch (nIndex)
	{
	case ANSI_FIXED_FONT:
	case ANSI_VAR_FONT:
	case DEVICE_DEFAULT_FONT:
	case OEM_FIXED_FONT:
	case SYSTEM_FONT:
	case SYSTEM_FIXED_FONT:
	case DEFAULT_GUI_FONT:
		// Handle the stock fonts correctly
		{
			CGdiObject* pObject = CGdiObject::FromHandle(
							::SelectObject(m_hAttribDC, hObj));

			// Don't re-mirror screen font if this is the same font.
			if (m_hPrinterFont == (HFONT) hObj)
				return pObject;

			m_hPrinterFont = (HFONT) hObj;

			ASSERT(m_hPrinterFont != NULL); // Do not allow infinite recursion

			MirrorFont();
			return pObject;
		}

	default:
		if (m_hDC != NULL)
			::SelectObject(m_hDC, hObj);
		return CGdiObject::FromHandle(::SelectObject(m_hAttribDC, hObj));
	}
}

void CPreviewDC::MirrorFont()
{
	if (m_hAttribDC == NULL)
		return;         // Can't do anything without Attrib DC

	if (m_hPrinterFont == NULL)
	{
		SelectStockObject(DEVICE_DEFAULT_FONT); // will recurse
		return;
	}

	if (m_hDC == NULL)
		return;         // can't mirror font without a screen DC

	LOGFONT logFont;
	// Fill the logFont structure with the original info
	::GetObject(m_hPrinterFont, sizeof(LOGFONT), (LPVOID)&logFont);

	TEXTMETRIC tm;

	GetTextFace(LF_FACESIZE, (LPTSTR)&logFont.lfFaceName[0]);
	GetTextMetrics(&tm);

	// Set real values based on the Printer's text metrics.

	if (tm.tmHeight < 0)
		logFont.lfHeight = tm.tmHeight;
	else
		logFont.lfHeight = -(tm.tmHeight - tm.tmInternalLeading);

	logFont.lfWidth = tm.tmAveCharWidth;
	logFont.lfWeight = tm.tmWeight;
	logFont.lfItalic = tm.tmItalic;
	logFont.lfUnderline = tm.tmUnderlined;
	logFont.lfStrikeOut = tm.tmStruckOut;
	logFont.lfCharSet = tm.tmCharSet;
	logFont.lfPitchAndFamily = tm.tmPitchAndFamily;

	HFONT hNewFont = ::CreateFontIndirect(&logFont);
	::SelectObject(m_hDC, hNewFont);

	::GetTextMetrics(m_hDC, &tm);

	// Is the displayed font too large?

	int cyDesired = -logFont.lfHeight;
	int cyActual;
	if (tm.tmHeight < 0)
		cyActual = -tm.tmHeight;
	else
		cyActual = tm.tmHeight - tm.tmInternalLeading;

	CSize sizeWinExt;
	VERIFY(::GetWindowExtEx(m_hDC, &sizeWinExt));
	CSize sizeVpExt;
	VERIFY(::GetViewportExtEx(m_hDC, &sizeVpExt));

	// Only interested in Extent Magnitudes, not direction
	if (sizeWinExt.cy < 0)
		sizeWinExt.cy = -sizeWinExt.cy;
	if (sizeVpExt.cy < 0)
		sizeVpExt.cy = -sizeVpExt.cy;

	// Convert to screen device coordinates to eliminate rounding
	// errors as a source of SmallFont aliasing

	cyDesired = MulDiv(cyDesired, sizeVpExt.cy, sizeWinExt.cy);
	cyActual = MulDiv(cyActual, sizeVpExt.cy, sizeWinExt.cy);

	ASSERT(cyDesired >= 0 && cyActual >= 0);

	if (cyDesired < cyActual)
	{
		logFont.lfFaceName[0] = 0;      // let the mapper find a good fit

		if ((logFont.lfPitchAndFamily & 0xf0) == FF_DECORATIVE)
			logFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DECORATIVE;
		else
			logFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;

		HFONT hTempFont = ::CreateFontIndirect(&logFont);
		::SelectObject(m_hDC, hTempFont);           // Select it in.
		::DeleteObject(hNewFont);
		hNewFont = hTempFont;
	}

	AfxDeleteObject((HGDIOBJ*)&m_hFont);  // delete the old logical font
	m_hFont = hNewFont;         // save the new one
}

CFont* CPreviewDC::SelectObject(CFont* pFont)
{
	if (pFont == NULL)
		return NULL;

	ASSERT(m_hAttribDC != NULL);
	ASSERT_VALID(pFont);

	CFont* pOldFont = (CFont*) CGdiObject::FromHandle(
				::SelectObject(m_hAttribDC, pFont->m_hObject));

	// If same as already selected, don't re-mirror screen font
	if (m_hPrinterFont != pFont->m_hObject)
	{
		m_hPrinterFont = (HFONT)pFont->m_hObject;
		MirrorFont();
	}

	return pOldFont;
}

/////////////////////////////////////////////////////////////////////////////
// Drawing-Attribute Functions

COLORREF CPreviewDC::SetBkColor(COLORREF crColor)
{
	ASSERT(m_hAttribDC != NULL);
	if (m_hDC != NULL)
		::SetBkColor(m_hDC, ::GetNearestColor(m_hAttribDC, crColor));
	return ::SetBkColor(m_hAttribDC, crColor);
}

COLORREF CPreviewDC::SetTextColor(COLORREF crColor)
{
	ASSERT(m_hAttribDC != NULL);
	if (m_hDC != NULL)
		::SetTextColor(m_hDC, ::GetNearestColor(m_hAttribDC, crColor));
	return ::SetTextColor(m_hAttribDC, crColor);
}

int CPreviewDC::SetMapMode(int nMapMode)
{
	ASSERT(m_hAttribDC != NULL);
	int nModeOld = ::SetMapMode(m_hAttribDC, nMapMode);
	MirrorMappingMode(TRUE);
	return nModeOld;
}

CPoint CPreviewDC::SetViewportOrg(int x, int y)
{
	ASSERT(m_hAttribDC != NULL);
	CPoint ptOrgOld;
	VERIFY(::SetViewportOrgEx(m_hAttribDC, x, y, &ptOrgOld));
	MirrorViewportOrg();
	return ptOrgOld;
}

CPoint CPreviewDC::OffsetViewportOrg(int nWidth, int nHeight)
{
	ASSERT(m_hAttribDC != NULL);
	CPoint ptOrgOld;
	VERIFY(::OffsetViewportOrgEx(m_hAttribDC, nWidth, nHeight, &ptOrgOld));
	MirrorViewportOrg();
	return ptOrgOld;
}

CSize CPreviewDC::SetViewportExt(int x, int y)
{
	ASSERT(m_hAttribDC != NULL);
	CSize sizeExtOld;
	VERIFY(::SetViewportExtEx(m_hAttribDC, x, y, &sizeExtOld));
	MirrorMappingMode(TRUE);
	return sizeExtOld;
}

CSize CPreviewDC::ScaleViewportExt(int xNum, int xDenom, int yNum, int yDenom)
{
	ASSERT(m_hAttribDC != NULL);
	CSize sizeExtOld;
	VERIFY(::ScaleViewportExtEx(m_hAttribDC, xNum, xDenom,
		yNum, yDenom, &sizeExtOld));
	MirrorMappingMode(TRUE);
	return sizeExtOld;
}

CSize CPreviewDC::SetWindowExt(int x, int y)
{
	ASSERT(m_hAttribDC != NULL);
	CSize sizeExtOld;
	VERIFY(::SetWindowExtEx(m_hAttribDC, x, y, &sizeExtOld));
	MirrorMappingMode(TRUE);
	return sizeExtOld;
}

CSize CPreviewDC::ScaleWindowExt(int xNum, int xDenom, int yNum, int yDenom)
{
	ASSERT(m_hAttribDC != NULL);
	CSize sizeExtOld;
	VERIFY(::ScaleWindowExtEx(m_hAttribDC, xNum, xDenom, yNum, yDenom,
		&sizeExtOld));
	MirrorMappingMode(TRUE);
	return sizeExtOld;
}

/////////////////////////////////////////////////////////////////////////////
// Text Functions

// private helpers for TextOut functions

AFX_STATIC int AFXAPI _AfxComputeNextTab(int x, UINT nTabStops, LPINT lpnTabStops,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -