📄 2dpushgraph.cpp
字号:
if (nGreatest >= m_nMaxCoords)
{
m_nMoveOffset =
(m_nMoveOffset - (((nGreatest-m_nMaxCoords)+1)*m_usLineInterval))
% m_nGridSize;
}
RedrawWindow();
}
// ===================================================================
void C2DPushGraph::OnPaint()
{
CPaintDC paintDC(this);
/* First we create the back buffer */
CDC &dc = internal_InitBackBuffer(paintDC);
/* Ensure we don't draw out of our client rectangle */
CRect &rectClient = getClientRect();
dc.IntersectClipRect(&rectClient);
/* Fill the background */
dc.FillSolidRect(&rectClient, m_crBGColor);
dc.SetBkMode(TRANSPARENT);
if (m_bShowMinMax)
{
/* Show maximum and minimum labels */
internal_DrawMinMax(dc, rectClient);
}
if (m_bShowGrid)
{
/* Show the grid overlay */
internal_DrawGrid(dc, rectClient);
}
internal_DrawLines(dc, rectClient);
internal_FreeBackBuffer(paintDC);
if (m_bStylesModified)
{
/* Reset styles if resized */
GetParent()->ModifyStyle(WS_CLIPCHILDREN, 0);
ModifyStyle(WS_CLIPSIBLINGS, 0);
m_bStylesModified = false;
}
}
// ===================================================================
CDC& C2DPushGraph::internal_InitBackBuffer(CPaintDC &dc)
{
/* Create the offscreen DC and associated bitmap */
m_dcBack.CreateCompatibleDC(&dc);
m_bmBack.CreateCompatibleBitmap(&dc, getClientRect().Width(),
getClientRect().Height());
m_pOldBitmap = m_dcBack.SelectObject(&m_bmBack);
return m_dcBack;
}
// ===================================================================
void C2DPushGraph::internal_FreeBackBuffer(CPaintDC &dc)
{
/* Copy the offscreen buffer to the onscreen CPaintDC.
Then free the back buffer objects. */
dc.BitBlt(getClientRect().left, getClientRect().top,
getClientRect().Width(), getClientRect().Height(),
&m_dcBack, getClientRect().left, getClientRect().top,
SRCCOPY);
dc.SelectObject(m_pOldBitmap);
m_bmBack.DeleteObject();
m_dcBack.DeleteDC();
}
// ===================================================================
PushGraphLine* C2DPushGraph::internal_LineFromID( UINT uiLineID )
{
/* Find the corresponding line to the passed ID */
int k=m_aLines.GetSize()-1;
for (int n = m_aLines.GetSize()-1; n >= 0; --n)
{
if (m_aLines[n]->uiID == uiLineID)
{
return m_aLines[n];
}
}
return NULL;
}
// ===================================================================
void C2DPushGraph::internal_DrawMinMax( CDC &dc, CRect& rect)
{
CSize MaxSize=dc.GetTextExtent(m_strMaxLabel);
CSize MinSize=dc.GetTextExtent(m_strMinLabel);
CString strMidLabel="";
strMidLabel.Format("%d",(atoi(m_strMaxLabel)-atoi(m_strMinLabel))/2) ;
int nTextWidth =
((MaxSize.cx > MinSize.cx) ? MaxSize.cx : MinSize.cx) + 6;
/* Draw the labels (max: Top) (min: Bottom) */
dc.SetTextColor(m_crTextColor);
dc.TextOut(nTextWidth/2-(MaxSize.cx/2), 2, m_strMaxLabel);
dc.TextOut(nTextWidth/2-(MaxSize.cx/2), (rect.Height()-MinSize.cy-2)/2, strMidLabel);
dc.TextOut(nTextWidth/2-(MinSize.cx/2),rect.Height()-MinSize.cy, m_strMinLabel);
/* Draw the bordering line */
CPen penBorder(PS_SOLID, 1, m_crGridColor);
CPen *pOldPen = dc.SelectObject(&penBorder);
dc.MoveTo(nTextWidth + 6, 0);
dc.LineTo(nTextWidth + 6, rect.Height());
dc.SelectObject(pOldPen);
penBorder.DeleteObject();
/* Offset the graph rectangle so it doesn't overlap the labels */
rect.left = nTextWidth + 6;
}
// ===================================================================
void C2DPushGraph::internal_DrawLines( CDC &dc, CRect& rect)
{
CPen penLine;
CPen *pOldPen = NULL;
int nGreatest = 0;
if (m_nMaxCoords == -1)
{
/* Maximum push points not yet calculated */
m_nMaxCoords = (rect.Width() / m_usLineInterval) + 2
+ (rect.Width()%m_usLineInterval ? 1 : 0);
if (m_nMaxCoords <= 0)
{
m_nMaxCoords = 1;
}
}
for (int n=0; n < m_aLines.GetSize(); ++n)
{
if (nGreatest < m_aLines[n]->aMagnitudes.GetSize())
{
nGreatest = m_aLines[n]->aMagnitudes.GetSize();
}
}
if (nGreatest == 0)
{
return; // No lines to draw
}
for (n = 0; n < m_aLines.GetSize(); ++n)
{
/* If the line has less push points than the line with the greatest
number of push points, new push points are appended with
the same magnitude as the previous push point. If no push points
exist for the line, one is added with the least magnitude possible. */
PushGraphLine *pLine = m_aLines[n];
if (!pLine->aMagnitudes.GetSize())
{
pLine->aMagnitudes.Add(m_nMinPeek);
}
while (pLine->aMagnitudes.GetSize() < nGreatest)
{
pLine->aMagnitudes.Add(
pLine->aMagnitudes[pLine->aMagnitudes.GetSize()-1]);
}
while (m_aLines[n]->aMagnitudes.GetSize() >= m_nMaxCoords)
{
m_aLines[n]->aMagnitudes.RemoveAt(0);
}
if (!m_aLines[n]->aMagnitudes.GetSize())
{
/* No push points to draw */
return;
}
/* Now prepare to draw the line or bar */
penLine.CreatePen(PS_SOLID, 1, m_aLines[n]->crLine);
pOldPen = dc.SelectObject(&penLine);
if (pLine->bShowAsBar)
{
dc.MoveTo(rect.left, rect.Height());
}
else
{
// int m=pLine->aMagnitudes[0] ;
// int k=rect.Height()-(pLine->aMagnitudes[0] * rect.Height()/(m_nMaxPeek-m_nMinPeek));
dc.MoveTo(rect.left, nGreatest == 1 ? rect.Height()+3 : rect.Height()-(pLine->aMagnitudes[0] * rect.Height()/(m_nMaxPeek-m_nMinPeek)));
}
for (int n2 = 0; n2 < pLine->aMagnitudes.GetSize(); ++n2)
{
if (pLine->bShowAsBar)
{
/* The line is set to be shown as a bar graph, so
first we get the bars rectangle, then draw the bar */
CRect rectBar;
rectBar.left = rect.left + (n2*(m_usLineInterval)) + 1;
rectBar.right = rectBar.left + GetInterval() - 1;
rectBar.bottom = rect.Height();
rectBar.top = rect.Height() -
(pLine->aMagnitudes[n2] * rect.Height() /
(m_nMaxPeek-m_nMinPeek));
internal_DrawBar(dc, rectBar, *pLine);
}
else
{
/* Draw a line */
dc.LineTo(rect.left + (n2*m_usLineInterval),
rect.Height() -
(pLine->aMagnitudes[n2] * rect.Height() /
(m_nMaxPeek-m_nMinPeek)) );
/*
dc.FillSolidRect(rect.left + (n2*m_usLineInterval) - 2,
rect.Height() -
(pLine->aMagnitudes[n2] * rect.Height() /
(m_nMaxPeek-m_nMinPeek)) - 2, 4, 4, m_aLines[n]->crLine); */
}
}
dc.SelectObject(pOldPen);
penLine.DeleteObject(); // Free Pen
}
}
// ===================================================================
void C2DPushGraph::internal_DrawBar( CDC &dc, CRect& rect,
PushGraphLine& rLine )
{
COLORREF &crFill = rLine.crLine;
GraphColor gcTopLeft, gcBottomRight;
/* gcTopLeft is the left and top frame color, gcBottomRight
is the right and bottom frame color */
if (GetRValue(crFill))
{
gcTopLeft.bRed = PUSHGRAPH_MAX(GetRValue(crFill)+40, 255, BYTE);
gcBottomRight.bRed = PUSHGRAPH_MIN(GetRValue(crFill) - 40, 0, BYTE);
}
if (GetBValue(crFill))
{
gcTopLeft.bBlue = PUSHGRAPH_MAX(GetBValue(crFill)+40, 255, BYTE);
gcBottomRight.bBlue = PUSHGRAPH_MIN(GetBValue(crFill) - 40, 0, BYTE);
}
if (GetGValue(crFill))
{
gcTopLeft.bGreen = PUSHGRAPH_MAX(GetGValue(crFill)+40, 255, BYTE);
gcBottomRight.bGreen = PUSHGRAPH_MIN(GetGValue(crFill) - 40, 0, BYTE);
}
dc.FillSolidRect(&rect, rLine.crLine);
dc.Draw3dRect(&rect, gcTopLeft, gcBottomRight);
}
// ===================================================================
void C2DPushGraph::internal_DrawGrid( CDC &dc, CRect& rect)
{
/* Draw the grid overlay.
We use rect.left as our x offset instead of zero because
if m_bShowMinMax is true, then rect.left is set to the
first pixel after the labels. */
CPen GridPen( PS_SOLID, 1, m_crGridColor );
CPen *pOldPen = dc.SelectObject(&GridPen);
int k=20;
for (int n = rect.Height()-2; n >= 0; n -= m_nGridSize)
{
dc.MoveTo(rect.left-2, n);
dc.LineTo(rect.right, n);
if (k%5==0)
{
dc.MoveTo(rect.left-4, n);
dc.LineTo(rect.left, n);
}
k--;
}
for (n = rect.left + m_nMoveOffset; n < rect.right; n += m_nGridSize)
{
if (n < rect.left)
{
continue;
}
dc.MoveTo(n, 0);
dc.LineTo(n, rect.Height());
}
dc.SelectObject(pOldPen);
GridPen.DeleteObject();
}
// ===================================================================
CRect& C2DPushGraph::getClientRect()
{
static CRect rectClient;
return (GetClientRect(&rectClient), rectClient);
}
// ===================================================================
BOOL C2DPushGraph::OnEraseBkgnd(CDC*)
{
return FALSE;
}
// ===================================================================
void C2DPushGraph::OnSizing(UINT fwSide, LPRECT pRect)
{
if (GetParent()->GetStyle() & ~WS_CLIPCHILDREN)
{
/* Eliminate flickering */
m_bStylesModified = true;
GetParent()->ModifyStyle(0, WS_CLIPCHILDREN);
}
ModifyStyle(0, WS_CLIPSIBLINGS);
CWnd::OnSizing(fwSide, pRect);
(m_nMaxCoords = -1, Invalidate());
}
// ===================================================================
void C2DPushGraph::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
(m_nMaxCoords = -1, Invalidate());
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -