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

📄 rulerdrawer.cpp

📁 虚拟打印机
💻 CPP
字号:
/* * * rulerdrawer.cpp *   Copyright (C) 2006 Michael H. Overlin   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA      Contact at poster_printer@yahoo.com */#include "rulerdrawer.h"#include "fontkeeper.h"#include "mathutils.h"#include "utils.h"#include <windows.h>#include <strsafe.h>#include <vector>RulerDrawer::RulerDrawer(	IN const std::vector<uint>& vTicks, 	IN uint uiMinTickPixelSeparation,	IN uint uiMinLabelPixelSeparation,	IN double dUnits, 	IN int iLabelMult,	IN const tstring& tstrUnitLabel,	IN int iStart,	IN int iStop	) {	m_vTicks = vTicks;	m_uiMinTickPixelSeparation = uiMinTickPixelSeparation;	m_uiMinLabelPixelSeparation = uiMinLabelPixelSeparation;	m_dUnits = dUnits;	m_iLabelMult = iLabelMult;	m_tstrUnitLabel = tstrUnitLabel;	m_iStart = iStart;	m_iStop = iStop;	m_hpen = (HPEN) ::GetStockObject(BLACK_PEN);	m_cTicksPerDiv = 1;	// CALCULATE THE TOTAL NUMBER OF TICKS	// CALCULATE TOTAL NUMBER OF SMALLEST TICKS BETWEEN k'th TICK LEVEL	m_vuiTickMults.insert(m_vuiTickMults.begin(), m_vTicks.size(), 0);	for(uint k = 0; k < m_vTicks.size(); ++k) {		m_cTicksPerDiv *= m_vTicks[m_vTicks.size() - k - 1];		//m_cTicksPerDiv *= m_vTicks[k];		m_vuiTickMults[m_vTicks.size() - k - 1] = m_cTicksPerDiv;	}	// WE HAVE ONE FINAL TICK FOR END POINT m_iStop SO "+1"	m_cTicks = m_cTicksPerDiv * (m_iStop - m_iStart) + 1;	// FOR EACH TICK, CALCULATE HOW BIG (WHICH LEVEL) IT IS	m_viTickLevels.reserve(m_cTicks);	for(uint k = 0; k < m_cTicks; ++k) {		uint iLevel = 0;		for(uint t = 0; t < m_vuiTickMults.size(); ++t) {			iLevel += ( (k % m_vuiTickMults[t]) == 0 ? 1 : 0 );		}		m_viTickLevels.push_back(iLevel);	}	// ALLOCATE SPACE FOR LABEL STRINGS FOR MAJOR TICKS	// CALCULATE FOR BIGGEST TICK VALUE ITS NUMBER OF DIGITS	// INITIALIZE TO ZERO, SO THAT LABELS USING LESS CHARACTERS	// THAN THE MAXIMUM ARE EFFECTIVELY NULL-TERMINATED	uint kLabelMax = max(abs(m_iStart), abs(m_iStop)) * iLabelMult; 	m_cMaxLabelDigits = 2; // +2 IN CASE WE NEED A "-" SIGN W/SPACE	while(kLabelMax != 0) {		kLabelMax /= 10;		++m_cMaxLabelDigits;	}	uint nLabels = m_iStop - m_iStart + 1;	uint nLabelCch = m_cMaxLabelDigits * nLabels;	m_ptstrLabels = new TCHAR[nLabelCch];	ZeroMemory(m_ptstrLabels, nLabelCch*sizeof(TCHAR));	// WRITE THE LABEL STRINGS	m_vuiLabelSizes.reserve(nLabels);	for(uint k = 0; k < nLabels; ++k) {		StringCchPrintf(			m_ptstrLabels + k*m_cMaxLabelDigits, m_cMaxLabelDigits, TEXT("%d"), (LONG) (m_iStart+k)*m_iLabelMult);		int iLen = lstrlen(m_ptstrLabels + k*m_cMaxLabelDigits);		m_vuiLabelSizes.push_back(iLen);	}}RulerDrawer::~RulerDrawer() {	// 7/4	// delete m_ptstrLabels;	delete [] m_ptstrLabels;}BOOL RulerDrawer::CanDraw(IN const RulerPlacementSpec &rps, IN OUT LogFontKeeper& lfk) const {	SIZE szDest = { RW(rps.m_rDest), RH(rps.m_rDest) };	double dTopLeft = rps.m_dTopLeft;	double dBottomRight = rps.m_dBottomRight;	RulerPlacementSpec::Direction dir = rps.m_dir;	//double dExtSrc = dBottomRight - dTopLeft;	double dExtSrc = (dBottomRight - dTopLeft) / m_dUnits;	double dExtDest = 0;	switch(dir) {	case RulerPlacementSpec::eHorizontal: 		dExtDest = szDest.cx;		break;	case RulerPlacementSpec::eVertical:		dExtDest = szDest.cy;		break;	default:		ASSERTFAIL();		break;	}	double dTickSep =  dExtDest / dExtSrc;	BOOL bRetValue = (RoundToLong(dTickSep) >= m_uiMinLabelPixelSeparation);	return bRetValue;}VOID RulerDrawer::Draw(OUT HDC hdc, IN const RulerPlacementSpec &rps, IN OUT LogFontKeeper& lfk) const {	RECT rDest = rps.m_rDest;	double dTopLeft = rps.m_dTopLeft;	double dBottomRight = rps.m_dBottomRight;	RulerPlacementSpec::Direction dir = rps.m_dir;	dTopLeft /= m_dUnits;	dBottomRight /= m_dUnits;	double dSrcOrg = dTopLeft;	double dExtSrc = dBottomRight - dTopLeft ;	RECT rPaint = rDest;	LONG lTickSpace;	double dDestOrg;	double dExtDest;	switch(dir) {	case RulerPlacementSpec::eHorizontal: 		dDestOrg = rDest.left;		dExtDest = RW(rDest);		//::InflateRect(&rPaint, 0,-2);		lTickSpace = RH(rPaint);		lfk.m_lfNew.lfEscapement = 0;		break;	case RulerPlacementSpec::eVertical:		dDestOrg = rDest.top;		dExtDest = RH(rDest);		//::InflateRect(&rPaint, -2, 0);		lTickSpace = RW(rPaint);		lfk.m_lfNew.lfEscapement = 900;		break;	default:		ASSERTFAIL();		break;	}	lfk.m_lfNew.lfHeight = lTickSpace / 2;	//HBRUSH hBrushOld = (HBRUSH) ::SelectObject(hdc, ::GetStockObject(LTGRAY_BRUSH));	//::PatBlt(hdc, rDest.left, rDest.top, RW(rDest), RH(rDest), PATCOPY);	//::SelectObject(hdc, hBrushOld);	//::PatBlt(hdc, rPaint.left, rPaint.top, RW(rPaint), RH(rPaint), WHITENESS);	double dScaleFactor  = dExtDest / dExtSrc;	uint uiMinTickLevel = 0;	uint uiTickMults = m_cTicksPerDiv;	for(; uiMinTickLevel < m_vTicks.size(); ++uiMinTickLevel) {		double dTickSep = dScaleFactor / uiTickMults;		uint uiMinSep = /*(uiMinTickLevel == m_vTicks.size() - 1) ? */			this->m_uiMinTickPixelSeparation/*: m_uiMinLabelPixelSeparation*/;		if (RoundToLong(dTickSep) >= uiMinSep) {			break;		}		uiTickMults /= m_vuiTickMults[m_vTicks.size() - uiMinTickLevel - 1];	}	std::vector<int> viTickSize(m_vTicks.size()+1);	for(uint k = 0; k < viTickSize.size(); ++k) {		//viTickSize[viTickSize.size() - k - 1] = lTickSpace / (k+2);		viTickSize[viTickSize.size() - k - 1] = lTickSpace / (1 << (k ? k : 1));	}	LONG lTextDisp = lTickSpace / 2;	//COLORREF clrBkOld = ::SetBkColor(hdc, COLOR_BTNFACE);	COLORREF clrBkOld = ::SetBkColor(hdc, ::GetSysColor(COLOR_BTNFACE));	int iOldBkMode = /*::SetBkMode(hdc, TRANSPARENT);*/ ::SetBkMode(hdc, OPAQUE);	HPEN hPenOld = (HPEN) SelectObject(hdc, m_hpen);	HFONT hFontOld = (HFONT) SelectObject(hdc, lfk.GetFont());	UINT uiOldAlign = ::SetTextAlign(hdc, TA_CENTER | TA_BOTTOM );	//HRGN hRgnOld = ::CreateRectRgn(0,0,1,1);	//int iClipCode = ::GetClipRgn(hdc, hRgnOld);	//::IntersectClipRect(hdc, rPaint.left, rPaint.top, rPaint.right, rPaint.bottom);	// I SHOULD CALCULATE WHICH TICKS ARE VISIBLE INSTEAD	// MAYBE SHOULD NOT PRECALCULATE LABELS THE WAY I DO ALSO		PTSTR ptstr = m_ptstrLabels;	uint uiLabel = 0;	for(uint k = 0; k < m_cTicks; ++k) {		double dSrcTickPos = m_iStart + (double) k / m_cTicksPerDiv;		double dDestTickPos = (dSrcTickPos - dSrcOrg) * dScaleFactor + dDestOrg;		LONG lDestTickPos = RoundToLong(dDestTickPos);		uint iTickLevel = m_viTickLevels[k];		//7/8 WANT THE LAST TICK		//BOOL bDrawTick = 		//	iTickLevel >= uiMinTickLevel && 		//	(	(dir == RulerPlacementSpec::eHorizontal) ? 		//		(rPaint.left <= lDestTickPos && lDestTickPos < rPaint.right) :		//		(rPaint.top <= lDestTickPos && lDestTickPos < rPaint.bottom)		//	);		BOOL bDrawTick = 			iTickLevel >= uiMinTickLevel && 			(	(dir == RulerPlacementSpec::eHorizontal) ? 				(rPaint.left <= lDestTickPos && lDestTickPos <= rPaint.right) :				(rPaint.top <= lDestTickPos && lDestTickPos <= rPaint.bottom)			);		if (bDrawTick) {			uint iTickSize = k ? viTickSize[iTickLevel] : (lTickSpace * 2 / 3);					POINT ptTickFrom, ptTickTo, ptText;			switch(dir) {			case RulerPlacementSpec::eHorizontal:				ptTickFrom.x = ptTickTo.x = ptText.x = lDestTickPos;				ptTickFrom.y = rPaint.bottom;				ptTickTo.y = rPaint.bottom - iTickSize;				//ptText.y = rPaint.bottom - lTextDisp;				ptText.y = rPaint.bottom - lTextDisp / 3;				if (k == 0) {					::MoveToEx(hdc, ptTickFrom.x+1, ptTickFrom.y, NULL);					::LineTo(hdc, ptTickTo.x+1, ptTickTo.y);				}				break;			case RulerPlacementSpec::eVertical:				ptTickFrom.y = ptTickTo.y = ptText.y = lDestTickPos;				ptTickFrom.x = rPaint.right;				ptTickTo.x = rPaint.right - iTickSize;				//ptText.x = rPaint.right - lTextDisp;				ptText.x = rPaint.right - lTextDisp / 3;				if (k == 0) {					::MoveToEx(hdc, ptTickFrom.x, ptTickFrom.y+1, NULL);					::LineTo(hdc, ptTickTo.x, ptTickTo.y+1);				}				break;			default:				break;			}			::MoveToEx(hdc, ptTickFrom.x, ptTickFrom.y, NULL);			::LineTo(hdc, ptTickTo.x, ptTickTo.y);			if (iTickLevel == m_vTicks.size()) {				uint uiLen = this->m_vuiLabelSizes[uiLabel ++];				// CHECK LABEL FULLY FALLS WITHIN THE CLIPPING REGION -- OTHERWISE LOOKS UGLY				//DWORD dwExt = ::GetTabbedTextExtent(hdc, ptstr, uiLen, 0, NULL);				//WORD cx = LOWORD(dwExt);				//WORD cy = HIWORD(dwExt);				//RECT rText = { ptText.x, ptText.y, ptText.x, ptText.y };				//::InflateRect(&rText, cx/2, cy/2);				//RECT rTemp;				//::IntersectRect(&rTemp, &rText, &rPaint);				//if (::EqualRect(&rTemp, &rText)) {				if (k!=0) {					TextOut(hdc, ptText.x, ptText.y, ptstr, uiLen);				}				//}				ptstr += m_cMaxLabelDigits;			}		} else if (iTickLevel == m_vTicks.size()) {			ptstr += m_cMaxLabelDigits;			++uiLabel;		}	}	//::SelectClipRgn(hdc, (iClipCode == 1) ? hRgnOld : NULL);	//::DeleteObject(hRgnOld);	::SetTextAlign(hdc, uiOldAlign);	::SelectObject(hdc, hFontOld);	::SelectObject(hdc, hPenOld);	::SetBkColor(hdc, clrBkOld);	//::SetBkColor(hdc, clrBkOld);	::SetBkMode(hdc, iOldBkMode);}// ********************************************************************************************************// **  class Ruler  ***************************************************************************************// ********************************************************************************************************BOOL Ruler::Set(const RulerDrawer *prd, const RulerPlacementSpec& rps, LogFontKeeper *plfk) {	BOOL bRetValue = FALSE;	if (m_prd != prd || m_rps != rps || m_plfk != plfk) {		bRetValue = TRUE;		m_prd = prd;		m_rps = rps;		m_plfk = plfk;		if (m_prd != NULL) {			m_bCanDraw = m_prd->CanDraw(m_rps, *m_plfk);		} else {			m_bCanDraw = FALSE;		}	}	return bRetValue;}void Ruler::Draw(OUT HDC hdc) {	m_prd->Draw(hdc, m_rps, *m_plfk);}BOOL Ruler::operator !=(const Ruler &r) const {	//return		//m_bCanDraw ^ r.CanDraw()	|| 		//m_bCanDraw && r.CanDraw()	&& 		//(	m_rps != r.GetPlacement()	||		//	m_prd != r.m_prd			||		//	m_plfk != r.m_plfk		//);	BOOL bRetValue = 		lxor(m_bCanDraw, r.CanDraw())	|| 		m_bCanDraw && r.CanDraw()	&& 		(	m_rps != r.GetPlacement()	||			m_prd != r.m_prd			||			m_plfk != r.m_plfk		);	return bRetValue;}// ********************************************************************************************************// **  MODULE PUBLIC ROUTINES  ****************************************************************************// ********************************************************************************************************BOOL RulerUnitLabelChanged(const Ruler &rNew, const Ruler &rOld) {	//return 	//	rNew.CanDraw() ^ rOld.CanDraw() || 	//	rNew.CanDraw() && rOld.CanDraw() && rNew.GetUnitLabel() != rOld.GetUnitLabel();	BOOL bRetValue = 		lxor(rNew.CanDraw(), rOld.CanDraw()) || 		rNew.CanDraw() && rOld.CanDraw() && rNew.GetUnitLabel() != rOld.GetUnitLabel();	return bRetValue;}

⌨️ 快捷键说明

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