实时动态绘制曲线,在各种设备的状态统计中都会看到,动态曲线可以在最近的一段时间内观看状态变化情况。以前打算自己实现一下,后来总是没有去做,感觉不亲手做出来,虽然知道简单,但是心理总有一个坎。既然也经常会用到,那么就做出来,分享出来,以后应用上了,直接拿去用。
下面是内存使用情况的动态曲线图:
【连续开10个VS,然后迅速关掉10个VS的内存使用情况】
当走势图走到右边的时候,整个曲线会向左移动,和任务管理器的动态曲线效果差不多:
【任务管理器的动态曲线图】
画曲线也就是将连续的多个点划线连接起来就行了。而要动起来,就需要定时刷新界面,然后重新绘制界面了。新手可能不知道如何动起来,其实很简单。只要始终绘制后面的点就行了。当点越来越多,超出你要绘制的点数时,就只绘制后面的哪些点。在绘制前,将绘制区刷掉就行。这样绘制的内容和上次的内容,就有一个位置错位。定时的绘制,就形成了动感的动态曲线。
这里我们用MFC实现,其他环境看流程思路,具体实现方法就看你的环境的做法了。所以我们需要一个定时器,我们在窗口初始化的时候,启动一个定时器,调用函数SetTimer即可。指定要给定时间隔时间为1000毫秒,回调函数设置为0.这样,定时器消息就会发给标准的定时器消息处理函数OnTimer。我们直接使用向导添加WM_TIMER消息处理就行了。
在OnTimer函数里,我们将当前的内存使用比例存入容器std:vector,然后将这个容器的数据画成连线。获取内存使用比例的方法,参考文章《C++获取系统当前的内存使用情况信息代码实现》。绘制曲线需要注意起始点的问题,一定是取后面数量的点来划线。
下面是绘制连线的代码:
void DrawLine()
{
CDC *pDC = GetDC();
CRect rt;
GetClientRect(&rt);
pDC->FillRect(&rt,&CBrush(RGB(0,0,0)));
int width = rt.Width();
int height = rt.Height();
CPen pen(PS_SOLID,1,RGB(100,100,100));
pDC->SelectObject(&pen);
for (int i=0;i<10;i++)
{
pDC->MoveTo(0,i*height/10);
pDC->LineTo(width,i*height/10);
}
CPen pen2(PS_SOLID,1,RGB(255,255,0));
pDC->SelectObject(&pen2);
size_t count = m_used.size();
int start = 0;
int len = width/10+1;
if (count>len)
{
start = count - len;
}
pDC->MoveTo(0,height - m_used[start]*height/100);
for (size_t i=start;i<count;i++)
{
int len = m_used[i]*height/100;
int y = height - len;
pDC->LineTo((i-start)*10,y);
}
}
计时器里的代码如下:
void Ctmp_memlineDlg::OnTimer(UINT_PTR nIDEvent)
{
m_used.push_back(GetMemInfo());
DrawLine();
CDialogEx::OnTimer(nIDEvent);
}
获取内存的代码如下:
int Ctmp_memlineDlg::GetMemInfo()
{
MEMORYSTATUSEX status;
status.dwLength = sizeof(MEMORYSTATUSEX);
GlobalMemoryStatusEx(&status);
return status.dwMemoryLoad;
}
自定动手试试吧。