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

📄 xgraph.cpp

📁 Displaying large amounts of technical data in a chart can be a frustrating task. You can find tons o
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	if (abs(measureRect.Height()) > pDC->GetTextExtent(cMarker).cy)
		pDC->DrawText(cMarker, measureRect, DT_RIGHT | DT_SINGLELINE | DT_VCENTER | DT_NOCLIP);

	pDC->SetBkColor(nOldBkColor);
}

void CXGraph::DrawZoom (CDCEx* pDC)
{
	CRect zoomRect(m_MouseDownPoint.x, m_MouseDownPoint.y, m_CurrentPoint.x, m_CurrentPoint.y);

	zoomRect.NormalizeRect ();

	zoomRect.left = max(zoomRect.left, m_clInnerRect.left);
	zoomRect.top = max(zoomRect.top, m_clInnerRect.top);
	zoomRect.right = min(zoomRect.right, m_clInnerRect.right);
	zoomRect.bottom = min(zoomRect.bottom, m_clInnerRect.bottom);


	// If not in doublebuffer mode and zoomrect is not empty delete old zoomrect
	if (!m_bDoubleBuffer && !m_clCurrentZoom.IsRectEmpty ())
		pDC->DrawFocusRect (m_clCurrentZoom);

	m_clCurrentZoom = zoomRect;

	if (m_bDoubleBuffer)
	{
		// In db-mode we use a semi-transparent zoomrect ...
		CBrushSelector bs(RGB(150,150,255), pDC);
		COLORREF crOldBkColor = pDC->SetBkColor (m_crInnerColor); 
		int	nOldROP2 = pDC->SetROP2 (R2_NOTXORPEN);

		pDC->Rectangle(zoomRect);
		pDC->SetBkColor (crOldBkColor);
		pDC->SetROP2 (nOldROP2);
		
	}
	
	pDC->DrawFocusRect (m_clCurrentZoom);
	
}

CXGraphLabel& CXGraph::InsertLabel(CRect rect, CString cText)
{
	CXGraphLabel *pLabel = new CXGraphLabel;

	pLabel->m_clRect = rect;
	pLabel->m_cText  = cText;
	pLabel->m_pGraph = this;
	
	m_Objects.AddTail (pLabel);

	return *pLabel;
}

CXGraphLabel& CXGraph::InsertLabel(CString cText)
{
	CXGraphLabel *pLabel = new CXGraphLabel;

	CRect rect(m_clInnerRect.CenterPoint().x - 50,m_clInnerRect.CenterPoint().y - 50,
		       m_clInnerRect.CenterPoint().x + 50,m_clInnerRect.CenterPoint().y + 50);
	
	pLabel->m_clRect = rect;
	pLabel->m_cText  = cText;
	pLabel->m_pGraph = this;
	
	m_Objects.AddTail (pLabel);

	return *pLabel;
}

void CXGraph::Cursor()
{
	Pan();
	m_nSnappedCurve = m_nForcedSnapCurve;
	m_oldCursorPoint = CPoint(-1, -1);
	m_opOperation = opCursor;
	
	if (m_nCursorFlags & XGC_LEGEND)
		m_CursorLabel.m_clRect.SetRect(m_clInnerRect.left + 1, m_clInnerRect.top , m_clInnerRect.left + 150, m_clInnerRect.top + 50);
	

}

void CXGraph::Measure()
{
	m_opOperation = opMeasure;
	m_clCurrentMeasure.SetRectEmpty();
	Invalidate();
}

void CXGraph::Zoom()
{
	m_CursorLabel.m_bVisible = false;
	m_clCurrentZoom.SetRectEmpty ();
	m_opOperation = opZoom;
	Invalidate();
}

void CXGraph::Edit()
{
	m_opOperation = opEditCurve;
	Invalidate();
}

void CXGraph::ResetZoom()
{
	m_CursorLabel.m_bVisible = false;
	for (int y = 0; y < static_cast<int>(m_YAxis.size()); y++)
		m_YAxis[y].Reset();
	for (int x = 0; x < static_cast<int>(m_XAxis.size()); x++)
		m_XAxis[x].Reset();
	Invalidate();
}

void CXGraph::NoOp()
{
	m_CursorLabel.m_bVisible = false;
	m_opOperation = opNone;
	Invalidate();
}

void CXGraph::Pan()
{
	m_CursorLabel.m_bVisible = false;
	m_opOperation = opPan;

	for (int y = 0; y < static_cast<int>(m_YAxis.size()); y++)
		m_YAxis[y].m_bAutoScale = false;
	
	for (int x = 0; x < static_cast<int>(m_XAxis.size()); x++)
		m_XAxis[x].m_bAutoScale = false;

	Invalidate();
}

void CXGraph::DoPan(CPoint point)
{
	for (int y = 0; y < static_cast<int>(m_YAxis.size()); y++)
	{
		double fY1 = m_YAxis[y].GetValueForPos (point.y);
		double fY2 = m_YAxis[y].GetValueForPos (m_OldPoint.y);
		double fOffset = fY1 - fY2;
		VERIFY(m_YAxis[y].SetCurrentRange(m_YAxis[y].m_fCurMin - fOffset,m_YAxis[y].m_fCurMax - fOffset));
	}

	for (int x = 0; x < static_cast<int>(m_XAxis.size()); x++)
	{
		double fX1 = m_XAxis[x].GetValueForPos (point.x);
		double fX2 = m_XAxis[x].GetValueForPos (m_OldPoint.x);
		double fOffset = fX1 - fX2;
		VERIFY(m_XAxis[x].SetCurrentRange(m_XAxis[x].m_fCurMin - fOffset,m_XAxis[x].m_fCurMax - fOffset));
	}

	m_OldPoint = point;

	Invalidate();
}

void CXGraph::DoZoom()
{		
	if (m_clCurrentZoom.Width () < MIN_ZOOM_PIXELS ||
		m_clCurrentZoom.Height () < MIN_ZOOM_PIXELS)
		return;

	ZOOM zoom;
			
	for (UINT y = 0; y < m_YAxis.size(); y++)
	{
		double fMin, fMax;

		fMin = m_YAxis[y].GetValueForPos(min(m_clCurrentZoom.bottom, m_clInnerRect.bottom));
		fMax = m_YAxis[y].GetValueForPos(max(m_clCurrentZoom.top, m_clInnerRect.top));

		if ((fMax - fMin) != 0.0)
		{			
			zoom.fMin = m_YAxis[y].m_fCurMin;
			zoom.fMax = m_YAxis[y].m_fCurMax;
	
			m_YAxis[y].m_ZoomHistory.push_back (zoom);

			m_YAxis[y].m_fCurMin = fMin;
			m_YAxis[y].m_fCurMax = fMax;
			m_YAxis[y].SetBestStep ();

		}
	}

	for (UINT x = 0; x < m_XAxis.size(); x++)
	{
		double fMin, fMax;

		fMin = m_XAxis[x].GetValueForPos(max(m_clCurrentZoom.left, m_clInnerRect.left));
		fMax = m_XAxis[x].GetValueForPos(min(m_clCurrentZoom.right, m_clInnerRect.right));
		
		if ((fMax - fMin) != 0.0)
		{
			zoom.fMin = m_XAxis[x].m_fCurMin;
			zoom.fMax = m_XAxis[x].m_fCurMax;
	
			m_XAxis[x].m_ZoomHistory.push_back (zoom);
	
			m_XAxis[x].m_fCurMin = fMin;
			m_XAxis[x].m_fCurMax = fMax;
			m_XAxis[x].SetBestStep();
			
		}
	}

	::PostMessage(GetParent()->m_hWnd, XG_ZOOMCHANGE, 0, (long) this);
	
	m_clCurrentZoom.SetRectEmpty ();
}

int CXGraph::GetZoomDepth()
{
	if (m_XAxis.size() > 0)
		return m_XAxis[0].m_ZoomHistory.size();

	return 0;

}
void CXGraph::RestoreLastZoom()
{		
	for (UINT y = 0; y < m_YAxis.size(); y++)
	{
		if (m_YAxis[y].m_ZoomHistory.size() > 0)
		{
			m_YAxis[y].m_fCurMin = m_YAxis[y].m_ZoomHistory[m_YAxis[y].m_ZoomHistory.size() - 1].fMin;
			m_YAxis[y].m_fCurMax = m_YAxis[y].m_ZoomHistory[m_YAxis[y].m_ZoomHistory.size() - 1].fMax;
			m_YAxis[y].m_ZoomHistory.pop_back ();
			m_YAxis[y].SetBestStep ();

		}
	}

	for (UINT x = 0; x < m_XAxis.size(); x++)
	{
		if (m_XAxis[x].m_ZoomHistory.size() > 0)
		{
			m_XAxis[x].m_fCurMin = m_XAxis[x].m_ZoomHistory[m_XAxis[x].m_ZoomHistory.size() - 1].fMin;
			m_XAxis[x].m_fCurMax = m_XAxis[x].m_ZoomHistory[m_XAxis[x].m_ZoomHistory.size() - 1].fMax;
			m_XAxis[x].m_ZoomHistory.pop_back ();
			m_XAxis[x].SetBestStep ();

		}
	}
	
	::PostMessage(GetParent()->m_hWnd, XG_ZOOMCHANGE, 0, (long) this);
	
	m_clCurrentZoom.SetRectEmpty ();

	Invalidate();

}



/////////////////////////////////////////////////////////////////////////////
// Behandlungsroutinen f黵 Nachrichten CXGraph 

void CXGraph::DrawLegend(CDCEx *pDC, CRect& ChartRect)
{
	int nLegendWidth = 0;
	int nLegendHeight = 0;
	int nItemHeight = 0;

	CQuickFont font("Arial", 13, FW_NORMAL);
	{
		CFontSelector fs(&font, pDC, false);

		for (UINT i = 0; i < m_Data.size(); i++)
		{
			if (!m_Data[i].m_bVisible)
				continue;

			CString cLegend;
			cLegend.Format(_T("%02d %s"), i + 1, m_Data[i].m_cLabel);
			nLegendWidth = __max(nLegendWidth, pDC->GetTextExtent (cLegend).cx);
			nLegendHeight += (nItemHeight = pDC->GetTextExtent (cLegend).cy);
		}
	}

	CFontSelector fs(&font, pDC);

	nLegendWidth += 16;

	CRect legendRect;
	
	if (m_LegendAlignment == left)
	{
		legendRect.SetRect (ChartRect.left + 10, ChartRect.top + 10, ChartRect.left + 10 + nLegendWidth, ChartRect.top + 12 + nLegendHeight);
		ChartRect.left += (nLegendWidth + 20);
	}
	
	if (m_LegendAlignment == right)
	{
		legendRect.SetRect (ChartRect.right - 10 - nLegendWidth, ChartRect.top + 10, ChartRect.right - 10, ChartRect.top + 12 + nLegendHeight);
		ChartRect.right -= (nLegendWidth + 20);
	}

	CPenSelector ps(0, 1, pDC);

	COLORREF brushColor = pDC->m_bMono ? RGB(255,255,255) : ::GetSysColor(COLOR_WINDOW);

	CBrushSelector bs(brushColor, pDC);
	
	pDC->Rectangle(legendRect);

	legendRect.DeflateRect (1,1,1,1);
	
	int nItem = 0;

	m_SelectByMarker.clear();

	for (UINT i = 0; i < m_Data.size(); i++)
	{
		SelectByMarker sbm;

		if (!m_Data[i].m_bVisible)
			continue;

		CString cLegend;
		cLegend.Format(_T("%02d %s"), i + 1, m_Data[i].m_cLabel);
		CRect itemRect(legendRect.left + 12, legendRect.top + nItemHeight * nItem, legendRect.right, legendRect.top + nItemHeight * nItem + nItemHeight);

		sbm.markerRect = itemRect;
		sbm.markerRect.left -= 12;
		sbm.pObject = &m_Data[i];

		m_SelectByMarker.push_back(sbm);
				
		if (pDC->m_bMono)
			pDC->SetBkColor(RGB(255,255,255));
		else
			pDC->SetBkColor(::GetSysColor(COLOR_WINDOW));

		pDC->DrawText(cLegend, itemRect, DT_LEFT);

		if (m_Data[i].m_bSelected)
			pDC->DrawFocusRect (sbm.markerRect);

		itemRect.left = legendRect.left + 2;
		itemRect.right = legendRect.left + 10;
		itemRect.DeflateRect (0,1,0,2);

		if (m_Data[i].m_nMarkerType == 0)
			pDC->FillSolidRect (itemRect, pDC->m_bMono ? 0L : m_Data[i].m_crColor);
		else
			m_YAxis[0].DrawMarker (pDC, CPoint(itemRect.left - 1, itemRect.top + 1), m_Data[i].m_nMarker, 8, pDC->m_bMono ? 0L : m_Data[i].m_crColor, true);
	
		nItem++;
	}
}


void CXGraph::OnDraw(CDC *pDC)
{
	CDCEx dc;
	
	dc.Attach (pDC->m_hDC);
	dc.Prepare (pDC->m_hAttribDC);
	
	m_pDrawDC = &dc;
	m_pDrawDC->m_bMono = false;
	m_pDrawDC->m_bPrinting = false;
	m_pDrawDC->m_bPrintPreview = false;
	
	m_clPrintRect.SetRect(0, 0, pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));

	OnPaint();

	m_pDrawDC = NULL;

	dc.Detach();
}


	
void CXGraph::OnPaint() 
{
	CDCEx*    pDC   = new CDCEx;
	CMemDC*   pmdc  = NULL;
	CPaintDC* pdc   = new CPaintDC(this);
	CRect     clRect, clChartRect;
	int		  nSaveDC;

	m_oldCursorPoint = CPoint(-1, -1);

	if(m_pDrawDC != NULL)
	{
		pDC = (CDCEx*) m_pDrawDC;
	}
	else
	if (m_bDoubleBuffer)
	{
		pmdc = new CMemDC(pdc);
		pDC->Attach(pmdc->m_hDC);
		nSaveDC = pDC->SaveDC();
		pDC->m_bMono = false;
		pDC->m_bPrinting = false;
		pDC->m_bPrintPreview = false;
	}
	else
	{
		pDC->Attach(pdc->m_hDC);
		nSaveDC = pDC->SaveDC();
		pDC->m_bMono = false;
		pDC->m_bPrinting = false;
		pDC->m_bPrintPreview = false;
	}

	

	
	m_oldCursorPoint = CPoint(-1, -1);

	
	// Background
	if (pDC->m_bPrinting)
		clRect = m_clPrintRect;
	else
		GetClientRect(clRect);

	if (pDC->m_bMono)
		pDC->FillSolidRect(clRect, RGB(255,255,255));
	else
		pDC->FillSolidRect(clRect, m_crBackColor);
	
	// Chart
	clChartRect.left   = clRect.left + m_nLeftMargin;
	clChartRect.top    = clRect.top + m_nTopMargin;
	clChartRect.right  = clRect.right - m_nRightMargin;
	clChartRect.bottom = clRect.bottom - m_nBottomMargin;

	if (m_bShowLegend)
		DrawLegend(pDC, clChartRect);

	if (pDC->m_bMono)
		pDC->FillSolidRect(clChartRect, RGB(255,255,255));
	else
		pDC->FillSolidRect(clChartRect, m_crGraphColor);

	int nLeft   = clChartRect.left;
	int nRight  = clChartRect.right;
	int nBottom = clChartRect.bottom;

	CXGraphAxis::EAxisPlacement lastPlacement = CXGraphAxis::apAutomatic;

	// Calculate layout, prepare automatic axis
	for (UINT nYAxis = 0; nYAxis < m_YAxis.size (); nYAxis++)
	{
		if (m_YAxis[nYAxis].m_Placement == CXGraphAxis::apAutomatic)
		{
			if (lastPlacement == CXGraphAxis::apLeft)
			{
				lastPlacement = CXGraphAxis::apRight;
				m_YAxis[nYAxis].m_Placement = CXGraphAxis::apRight;
			}
			else
			{
				lastPlacement = CXGraphAxis::apLeft;
				m_YAxis[nYAxis].m_Placement = CXGraphAxis::apLeft;
			}
		}
	}

	// Y-Axis, left side
	for (nYAxis = 0; nYAxis < m_YAxis.size (); nYAxis++)
	{
		if (m_YAxis[nYAxis].m_Placement != CXGraphAxis::apLeft)
			continue;
	
		int nTickWidth  = m_YAxis[nYAxis].GetMaxLabelWidth (pDC); 
		int nLabelWidth = (m_YAxis[nYAxis].GetTitleSize (pDC).cx + m_YAxis[nYAxis].m_nArcSize);

		if (m_YAxis[nYAxis].m_bVisible)
			nLeft += (max (nTickWidth, nLabelWidth) + m_nAxisSpace );

		m_YAxis[nYAxis].m_nLeft   = nLeft;
		m_YAxis[nYAxis].m_clChart = clChartRect;
	}
	
	// Y-Axis, right side
	for (nYAxis = 0; nYAxis < m_YAxis.size (); nYAxis++)
	{
		if (m_YAxis[nYAxis].m_Placement != CXGraphAxis::apRight)
			continue;

		int nTickWidth  = m_YAxis[nYAxis].GetMaxLabelWidth (pDC); 
		int nLabelWidth = m_YAxis[nYAxis].GetTitleSize (pDC).cx;
	
		if (m_YAxis[nYAxis].m_bVisible)
			nRight -= (max (nTickWidth, nLabelWidth) + m_nAxisSpace );
		
		m_YAxis[nYAxis].m_nLeft   = nRight;
		m_YAxis[nYAxis].m_clChart = clChartRect;
	}

	// X-Axis
	for (UINT nXAxis = 0; nXAxis < m_XAxis.size (); nXAxis++)
	{
		if (m_XAxis[nXAxis].m_bVisible)
			nBottom -= (m_XAxis[nXAxis].GetMaxLabelHeight (pDC) + m_nAxisSpace);

		m_XAxis[nXAxis].m_nTop    = nBottom;
		m_XAxis[nXAxis].m_nLeft   = nLeft;
		m_XAxis[nXAxis].m_clChart = clChartRect;
	}

	// Draw Inner Rect
	// 

	m_clInnerRect.SetRect (nLeft + 1, clChartRect.top, nRight, nBottom);
	if (pDC->m_bMono)
		pDC->FillSolidRect(m_clInnerRect, RGB(255,255,255));
	else
		pDC->FillSolidRect(m_clInnerRect, m_crInnerColor);
	
	// Draw axis
	// Y-Axis

⌨️ 快捷键说明

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