📄 xgraph.cpp
字号:
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 + -