📄 graphctl.c
字号:
SelectObject(m_dcGrid, oldFont);
/* y units */
oldFont = (HFONT)SelectObject(m_dcGrid, yUnitFont);
SetTextAlign(m_dcGrid, TA_CENTER|TA_BASELINE);
TextOut(m_dcGrid, (m_rectClient.left+m_rectPlot.left)/2,
(m_rectPlot.bottom+m_rectPlot.top)/2, m_strYUnitsString, _tcslen(m_strYUnitsString));
SelectObject(m_dcGrid, oldFont);
#endif
/* at this point we are done filling the the grid bitmap, */
/* no more drawing to this bitmap is needed until the setting are changed */
/* if we don't have one yet, set up a memory dc for the plot */
if (this->m_dcPlot == NULL)
{
this->m_dcPlot = CreateCompatibleDC(dc);
this->m_bitmapPlot = CreateCompatibleBitmap(dc, this->m_nClientWidth, this->m_nClientHeight);
this->m_bitmapOldPlot = (HBITMAP)SelectObject(this->m_dcPlot, this->m_bitmapPlot);
}
else if(bResize)
{
// the size of the drawing area has changed
// so create a new bitmap of the appropriate size
if(this->m_bitmapPlot != NULL)
{
this->m_bitmapPlot = (HBITMAP)SelectObject(this->m_dcPlot, this->m_bitmapOldPlot);
DeleteObject(this->m_bitmapPlot);
this->m_bitmapPlot = CreateCompatibleBitmap(dc, this->m_nClientWidth, this->m_nClientHeight);
SelectObject(this->m_dcPlot, this->m_bitmapPlot);
}
}
/* make sure the plot bitmap is cleared */
SetBkColor(this->m_dcPlot, this->m_crBackColor);
FillRect(this->m_dcPlot, &this->m_rectClient, this->m_brushBack);
/* finally, force the plot area to redraw */
InvalidateRect(this->m_hParentWnd, &this->m_rectClient, TRUE);
ReleaseDC(this->m_hParentWnd, dc);
}
double GraphCtrl_AppendPoint(TGraphCtrl* this,
double dNewPoint0, double dNewPoint1,
double dNewPoint2, double dNewPoint3)
{
/* append a data point to the plot & return the previous point */
double dPrevious;
dPrevious = this->m_dCurrentPosition[0];
this->m_dCurrentPosition[0] = dNewPoint0;
this->m_dCurrentPosition[1] = dNewPoint1;
this->m_dCurrentPosition[2] = dNewPoint2;
this->m_dCurrentPosition[3] = dNewPoint3;
GraphCtrl_DrawPoint(this);
/* Invalidate(); */
return dPrevious;
}
void GraphCtrl_Paint(TGraphCtrl* this, HWND hWnd, HDC dc)
{
HDC memDC;
HBITMAP memBitmap;
HBITMAP oldBitmap; /* bitmap originally found in CMemDC */
/* RECT rcClient; */
/* GetClientRect(hWnd, &rcClient); */
/* FillSolidRect(dc, &rcClient, RGB(255, 0, 255)); */
/* m_nClientWidth = rcClient.right - rcClient.left; */
/* m_nClientHeight = rcClient.bottom - rcClient.top; */
/* no real plotting work is performed here, */
/* just putting the existing bitmaps on the client */
/* to avoid flicker, establish a memory dc, draw to it */
/* and then BitBlt it to the client */
memDC = CreateCompatibleDC(dc);
memBitmap = (HBITMAP)CreateCompatibleBitmap(dc, this->m_nClientWidth, this->m_nClientHeight);
oldBitmap = (HBITMAP)SelectObject(memDC, memBitmap);
if (memDC != NULL)
{
/* first drop the grid on the memory dc */
BitBlt(memDC, 0, 0, this->m_nClientWidth, this->m_nClientHeight, this->m_dcGrid, 0, 0, SRCCOPY);
/* now add the plot on top as a "pattern" via SRCPAINT. */
/* works well with dark background and a light plot */
BitBlt(memDC, 0, 0, this->m_nClientWidth, this->m_nClientHeight, this->m_dcPlot, 0, 0, SRCPAINT); /* SRCPAINT */
/* finally send the result to the display */
BitBlt(dc, 0, 0, this->m_nClientWidth, this->m_nClientHeight, memDC, 0, 0, SRCCOPY);
}
SelectObject(memDC, oldBitmap);
DeleteObject(memBitmap);
DeleteDC(memDC);
}
void GraphCtrl_DrawPoint(TGraphCtrl* this)
{
/* this does the work of "scrolling" the plot to the left
* and appending a new data point all of the plotting is
* directed to the memory based bitmap associated with m_dcPlot
* the will subsequently be BitBlt'd to the client in Paint
*/
int currX, prevX, currY, prevY;
HPEN oldPen;
RECT rectCleanUp;
int i;
if (this->m_dcPlot != NULL)
{
/* shift the plot by BitBlt'ing it to itself
* note: the m_dcPlot covers the entire client
* but we only shift bitmap that is the size
* of the plot rectangle
* grab the right side of the plot (exluding m_nShiftPixels on the left)
* move this grabbed bitmap to the left by m_nShiftPixels
*/
BitBlt(this->m_dcPlot, this->m_rectPlot.left, this->m_rectPlot.top+1,
this->m_nPlotWidth, this->m_nPlotHeight, this->m_dcPlot,
this->m_rectPlot.left+this->m_nShiftPixels, this->m_rectPlot.top+1,
SRCCOPY);
/* establish a rectangle over the right side of plot */
/* which now needs to be cleaned up proir to adding the new point */
rectCleanUp = this->m_rectPlot;
rectCleanUp.left = rectCleanUp.right - this->m_nShiftPixels;
/* fill the cleanup area with the background */
FillRect(this->m_dcPlot, &rectCleanUp, this->m_brushBack);
/* draw the next line segement */
for (i = 0; i < MAX_PLOTS; i++)
{
/* grab the plotting pen */
oldPen = (HPEN)SelectObject(this->m_dcPlot, this->m_penPlot[i]);
/* move to the previous point */
prevX = this->m_rectPlot.right-this->m_nPlotShiftPixels;
prevY = this->m_rectPlot.bottom -
(long)((this->m_dPreviousPosition[i] - this->m_dLowerLimit) * this->m_dVerticalFactor);
MoveToEx(this->m_dcPlot, prevX, prevY, NULL);
/* draw to the current point */
currX = this->m_rectPlot.right-this->m_nHalfShiftPixels;
currY = this->m_rectPlot.bottom -
(long)((this->m_dCurrentPosition[i] - this->m_dLowerLimit) * this->m_dVerticalFactor);
LineTo(this->m_dcPlot, currX, currY);
/* Restore the pen */
SelectObject(this->m_dcPlot, oldPen);
/* if the data leaks over the upper or lower plot boundaries
* fill the upper and lower leakage with the background
* this will facilitate clipping on an as needed basis
* as opposed to always calling IntersectClipRect
*/
if ((prevY <= this->m_rectPlot.top) || (currY <= this->m_rectPlot.top))
{
RECT rc;
rc.bottom = this->m_rectPlot.top+1;
rc.left = prevX;
rc.right = currX+1;
rc.top = this->m_rectClient.top;
FillRect(this->m_dcPlot, &rc, this->m_brushBack);
}
if ((prevY >= this->m_rectPlot.bottom) || (currY >= this->m_rectPlot.bottom))
{
RECT rc;
rc.bottom = this->m_rectClient.bottom+1;
rc.left = prevX;
rc.right = currX+1;
rc.top = this->m_rectPlot.bottom+1;
/* RECT rc(prevX, m_rectPlot.bottom+1, currX+1, m_rectClient.bottom+1); */
FillRect(this->m_dcPlot, &rc, this->m_brushBack);
}
/* store the current point for connection to the next point */
this->m_dPreviousPosition[i] = this->m_dCurrentPosition[i];
}
}
}
void GraphCtrl_Resize(TGraphCtrl* this)
{
/* NOTE: Resize automatically gets called during the setup of the control */
GetClientRect(this->m_hWnd, &this->m_rectClient);
/* set some member variables to avoid multiple function calls */
this->m_nClientHeight = this->m_rectClient.bottom - this->m_rectClient.top;/* m_rectClient.Height(); */
this->m_nClientWidth = this->m_rectClient.right - this->m_rectClient.left;/* m_rectClient.Width(); */
/* the "left" coordinate and "width" will be modified in */
/* InvalidateCtrl to be based on the width of the y axis scaling */
#if 0
this->m_rectPlot.left = 20;
this->m_rectPlot.top = 10;
this->m_rectPlot.right = this->m_rectClient.right-10;
this->m_rectPlot.bottom = this->m_rectClient.bottom-25;
#else
this->m_rectPlot.left = 0;
this->m_rectPlot.top = -1;
this->m_rectPlot.right = this->m_rectClient.right-0;
this->m_rectPlot.bottom = this->m_rectClient.bottom-0;
#endif
/* set some member variables to avoid multiple function calls */
this->m_nPlotHeight = this->m_rectPlot.bottom - this->m_rectPlot.top;/* m_rectPlot.Height(); */
this->m_nPlotWidth = this->m_rectPlot.right - this->m_rectPlot.left;/* m_rectPlot.Width(); */
/* set the scaling factor for now, this can be adjusted */
/* in the SetRange functions */
this->m_dVerticalFactor = (double)this->m_nPlotHeight / this->m_dRange;
}
#if 0
void TGraphCtrl::Reset()
{
/* to clear the existing data (in the form of a bitmap) */
/* simply invalidate the entire control */
InvalidateCtrl();
}
#endif
extern TGraphCtrl PerformancePageCpuUsageHistoryGraph;
extern TGraphCtrl PerformancePageMemUsageHistoryGraph;
extern HWND hPerformancePageCpuUsageHistoryGraph;
extern HWND hPerformancePageMemUsageHistoryGraph;
INT_PTR CALLBACK
GraphCtrl_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
RECT rcClient;
HDC hdc;
PAINTSTRUCT ps;
switch (message)
{
case WM_ERASEBKGND:
return TRUE;
/*
* Filter out mouse & keyboard messages
*/
/* case WM_APPCOMMAND: */
case WM_CAPTURECHANGED:
case WM_LBUTTONDBLCLK:
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MBUTTONDBLCLK:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_MOUSEACTIVATE:
case WM_MOUSEHOVER:
case WM_MOUSELEAVE:
case WM_MOUSEMOVE:
/* case WM_MOUSEWHEEL: */
case WM_NCHITTEST:
case WM_NCLBUTTONDBLCLK:
case WM_NCLBUTTONDOWN:
case WM_NCLBUTTONUP:
case WM_NCMBUTTONDBLCLK:
case WM_NCMBUTTONDOWN:
case WM_NCMBUTTONUP:
/* case WM_NCMOUSEHOVER: */
/* case WM_NCMOUSELEAVE: */
case WM_NCMOUSEMOVE:
case WM_NCRBUTTONDBLCLK:
case WM_NCRBUTTONDOWN:
case WM_NCRBUTTONUP:
/* case WM_NCXBUTTONDBLCLK: */
/* case WM_NCXBUTTONDOWN: */
/* case WM_NCXBUTTONUP: */
case WM_RBUTTONDBLCLK:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
/* case WM_XBUTTONDBLCLK: */
/* case WM_XBUTTONDOWN: */
/* case WM_XBUTTONUP: */
case WM_ACTIVATE:
case WM_CHAR:
case WM_DEADCHAR:
case WM_GETHOTKEY:
case WM_HOTKEY:
case WM_KEYDOWN:
case WM_KEYUP:
case WM_KILLFOCUS:
case WM_SETFOCUS:
case WM_SETHOTKEY:
case WM_SYSCHAR:
case WM_SYSDEADCHAR:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
return 0;
case WM_NCCALCSIZE:
return 0;
case WM_SIZE:
if (hWnd == hPerformancePageMemUsageHistoryGraph)
{
GraphCtrl_Resize(&PerformancePageMemUsageHistoryGraph);
GraphCtrl_InvalidateCtrl(&PerformancePageMemUsageHistoryGraph, TRUE);
}
if (hWnd == hPerformancePageCpuUsageHistoryGraph)
{
GraphCtrl_Resize(&PerformancePageCpuUsageHistoryGraph);
GraphCtrl_InvalidateCtrl(&PerformancePageCpuUsageHistoryGraph, TRUE);
}
return 0;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rcClient);
if (hWnd == hPerformancePageMemUsageHistoryGraph)
GraphCtrl_Paint(&PerformancePageMemUsageHistoryGraph, hWnd, hdc);
if (hWnd == hPerformancePageCpuUsageHistoryGraph)
GraphCtrl_Paint(&PerformancePageCpuUsageHistoryGraph, hWnd, hdc);
EndPaint(hWnd, &ps);
return 0;
}
/*
* We pass on all non-handled messages
*/
return CallWindowProc((WNDPROC)OldGraphCtrlWndProc, hWnd, message, wParam, lParam);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -