MsChart实现无闪烁动态曲线(MFC)

转载 2012年03月26日 17:01:34
最近需要用MFC做一个界面动态显示曲线,自己画坐标轴画曲线太费时间,网上也有很多已实现的动态曲线接口,但是也不太灵活。正好微软有个现成的MSChart,功能比较全面,查了一些资料,总算实现了无闪烁的动态曲线。关于MSChart的安装可以参考上篇文章http://www.cnblogs.com/wy-wangyan/archive/2011/05/06/2038981.html

      实现的效果截图:

     

      实现的原理:MSChart如果要实现动态的曲线就只能在设置的定时器中根据RowCount,到一定的列数后在最后一列插入新一列(m_Chart.GetDataGrid().InsertRows),将最早出现的那一列删除(m_Chart.GetDataGrid().DeleteRows)。对于无闪烁刷新的实现类似于一般MFC画图中创建双缓冲画图避免屏幕闪烁的方法,这里是用CStatic动态创建一个Picture Control图像控件,将它设定和要画的MSChart一样大,然后把mschart的内容利用m_Chart.EditCopy()复制到剪贴板,然后再在picture control中显示出来。

     下面是全部的实现的代码:

MSChart需要在view的oncreate中创建出mschart:

1 int CRTDBView::OnCreate(LPCREATESTRUCT lpCreateStruct)
2 {
3 if (CView::OnCreate(lpCreateStruct)== -1)
4 return-1;
5
6 // TODO: Add your specialized creation code here
7 CRect rc;
8 GetClientRect(&rc);
9 VERIFY(m_Picture.Create(_T(""),SS_BITMAP|WS_CHILD|WS_EX_TRANSPARENT| WS_VISIBLE,CRect(0,0,1200,600),this,IDC_PICTURE));
10 if(!m_Chart.Create(_T("RTDB"),WS_CHILD| WS_VISIBLE, CRect(0,0,1200,600),this, 10))
11 return-1;
12
13
14 return0;
15 }

在ONSIZE中设置mschart的位置:

1 void CRTDBView::OnSize(UINT nType,int cx, int cy)
2 {
3 CView::OnSize(nType, cx, cy);
4
5 // TODO: Add your message handler code here
6 if( m_Chart.GetSafeHwnd())
7 m_Chart.MoveWindow(0, 0, cx, cy );
8 }

下面是主要实现部分的代码了,InitChart函数实现了mschart的背景、标题、XY坐标刻度以及颜色字体大小、曲线设定颜色以及数据点的显示等。主要是chart的初始化。

1 void CRTDBView::InitChart(void)
2 {
3 // 设置标题
4 m_Chart.SetTitleText(_T("RTDB"));
5
6 // 设置标题颜色
7 m_Chart.GetTitle().GetVtFont().GetVtColor().Set(0,255,0);
8
9 // 改变字体大小
10 m_Chart.GetTitle().GetVtFont().SetSize(14);
11
12 // 改变背景色
13 m_Chart.GetBackdrop().GetFill().SetStyle(1);
14 m_Chart.GetBackdrop().GetFill().GetBrush().GetFillColor().Set(0,0,0);
15
16 // 显示图例
17 m_Chart.SetShowLegend(TRUE);
18 m_Chart.SetColumn(1);
19 m_Chart.SetColumnLabel((LPCTSTR)_T("point num"));
20
21 // 设置图例颜色
22 m_Chart.GetLegend().GetVtFont().GetVtColor() .Set(0,255,0);
23
24 // 初始化设置row
25 m_Chart.SetRowCount(15);
26 m_Chart.SetRow(1);
27 m_Chart.SetRowLabel((LPCTSTR)_T(""));
28 for (UINT i=1;i<=m_Chart.GetRowCount();i++)
29 {
30 m_Chart.GetDataGrid().SetData(i,1,0,0);
31 }
32
33
34 // 显示类型 组合的方式 0为3D 1为2D
35 m_Chart.SetChartType(1|2);
36 m_Chart.SetSeriesType(11);
37
38 // 栈模式
39 m_Chart.SetStacking(FALSE);
40
41 VARIANT var;
42
43 // X、Y轴名称
44 m_Chart.GetPlot().GetAxis(0,var).GetAxisTitle().SetText(_T("时间(s)"));// X轴名称
45 m_Chart.GetPlot().GetAxis(1,var).GetAxisTitle().SetText(_T("点数"));// Y轴名称
46
47 // X轴设置
48 m_Chart.GetPlot().GetAxis(0,var).GetCategoryScale().SetAuto(FALSE);// 不自动标注X轴刻度
49 m_Chart.GetPlot().GetAxis(0,var).GetCategoryScale().SetDivisionsPerLabel(1);// 每刻度一个标注
50 m_Chart.GetPlot().GetAxis(0,var).GetCategoryScale().SetDivisionsPerTick(1);// 每刻度一个刻度线
51
52 // X轴每刻度竖线,0为不设置、1为设置
53 m_Chart.GetPlot().GetAxis(0,var).GetAxisGrid().GetMajorPen().SetStyle(0);
54
55 // 曲线个数
56 m_Chart.SetColumnCount(1);
57
58 // 曲线颜色
59 m_Chart.GetPlot().GetSeriesCollection().GetItem(1).GetPen().GetVtColor().Set(0,255,0);
60
61 // 曲线宽度(对点线图有效)
62 m_Chart.GetPlot().GetSeriesCollection().GetItem(1).GetPen().SetWidth(30);
63
64 // 数据点类型显示数据值的模式(对柱柱状图和点线图有效)
65 // 0: 不显示 1: 显示在柱状图外
66 // 2: 显示在柱状图内上方 3: 显示在柱状图内中间 4: 显示在柱状图内下方
67 m_Chart.GetPlot().GetSeriesCollection().GetItem(1).GetDataPoints().GetItem(-1).GetDataPointLabel().SetLocationType(1);
68
69 // 设置曲线上数据点颜色
70 m_Chart.GetPlot().GetSeriesCollection().GetItem(1).GetDataPoints().GetItem(-1).GetDataPointLabel().GetVtFont().GetVtColor().Set(0,255,0);
71
72 // 曲线设置十字标记
73 m_Chart.GetPlot().GetSeriesCollection().GetItem(1).GetSeriesMarker().SetAuto(FALSE);// MUST!!
74 m_Chart.GetPlot().GetSeriesCollection().GetItem(1).GetDataPoints().GetItem(-1)
75 .GetMarker().SetVisible(TRUE);
76
77 // 0横杠,1十字,2是叉,3是星,4是圆圈,5是方块,6菱形
78 // 7三角,8倒三角,9实心点,10实心方块,11实心菱形,12实心三角,13实心倒三角,14泛光的点
79 m_Chart.GetPlot().GetSeriesCollection().GetItem(1).GetDataPoints().GetItem(-1)
80 .GetMarker().SetStyle(1);
81
82 // 设置曲线上十字颜色
83 m_Chart.GetPlot().GetSeriesCollection().GetItem(1).GetDataPoints().GetItem(-1)
84 .GetMarker().GetFillColor().Set(255,0,0);
85 m_Chart.GetPlot().GetSeriesCollection().GetItem(1).GetDataPoints().GetItem(-1)
86 .GetMarker().GetPen().GetVtColor().Set(255,0,0);
87
88 // 设定坐标轴颜色
89 m_Chart.GetPlot().GetAxis(0,var).GetPen().GetVtColor().Set(0,255,0);
90 m_Chart.GetPlot().GetAxis(1,var).GetPen().GetVtColor().Set(0,255,0);
91 m_Chart.GetPlot().GetAxis(2,var).GetPen().GetVtColor().Set(0,255,0);
92
93 // 设置坐标轴轴刻度值颜色
94 m_Chart.GetPlot().GetAxis(1,var).GetLabels().GetItem(1).GetVtFont().GetVtColor().Set(0,255,0);
95 m_Chart.GetPlot().GetAxis(0,var).GetLabels().GetItem(1).GetVtFont().GetVtColor().Set(0,255,0);
96 m_Chart.GetPlot().GetAxis(2,var).GetLabels().GetItem(1).GetVtFont().GetVtColor().Set(0,255,0);
97
98 // 设定坐标轴宽度
99 m_Chart.GetPlot().GetAxis(0,var).GetPen().SetWidth(30);
100 m_Chart.GetPlot().GetAxis(1,var).GetPen().SetWidth(30);
101
102 //设定X、Y轴标题颜色
103 m_Chart.GetPlot().GetAxis(1,var).GetAxisTitle().GetVtFont().GetVtColor().Set(0,255,0);
104 m_Chart.GetPlot().GetAxis(0,var).GetAxisTitle().GetVtFont().GetVtColor().Set(0,255,0);
105
106 // 设置Y轴坐标横线颜色
107 m_Chart.GetPlot().GetAxis(1,var).GetAxisGrid().GetMajorPen().GetVtColor().Set(0,255,0);
108
109 // 设置Y轴
110 m_Chart.GetPlot().GetAxis(1,var).GetValueScale().SetAuto(FALSE);// 不自动标注Y轴刻度
111 m_Chart.GetPlot().GetAxis(1,var).GetValueScale().SetMaximum(100);// Y轴最大刻度
112 m_Chart.GetPlot().GetAxis(1,var).GetValueScale().SetMinimum(-100);// Y轴最小刻度
113 m_Chart.GetPlot().GetAxis(1,var).GetValueScale().SetMajorDivision(10);// Y轴刻度5等分
114 m_Chart.GetPlot().GetAxis(1,var).GetValueScale().SetMinorDivision(1);// 每刻度一个刻度线
115
116 // 设置Y轴名称大小、类型
117 m_Chart.GetPlot().GetAxis(1,var).GetAxisTitle().GetVtFont().SetStyle(0);
118 m_Chart.GetPlot().GetAxis(1,var).GetAxisTitle().GetVtFont().SetSize(12);
119
120 // 隐藏第二Y轴
121 m_Chart.GetPlot().GetAxis(2,var).GetAxisScale().SetHide(FALSE);
122
123 // 刷新
124 m_Chart.Refresh();
125
126 }

最后在OnTimer函数中是动态曲线的实现以及无闪烁的实现:

1 void CRTDBView::OnTimer(UINT_PTR nIDEvent)
2 {
3
4 //TODO: Add your message handler code here and/or call default
5 m_Picture.BringWindowToTop();
6 m_Picture.ShowWindow(SW_SHOW);
7 HANDLE hDib;
8 pDC = GetDlgItem(IDC_PICTURE)->GetDC();
9 int m_rowPos=m_Chart.GetRowCount()+1;
10
11 // 插入新一列
12 m_Chart.GetDataGrid().InsertRows(m_rowPos,1);
13 m_Chart.SetRow(m_rowPos);
14 char buf[32];
15 for (int i=0;i<sizeof(buf);i++)
16 {
17 buf[i]=0;
18 }
19 sprintf(buf,"%d",m_iCount);
20
21 // X轴坐标值
22 m_Chart.SetRowLabel((LPCTSTR)CString(buf));
23
24 // 数据设置(随机)
25 m_Chart.GetDataGrid().SetData(m_rowPos,1,rand()* 100/ RAND_MAX,0);
26
27 // 大于15列就开始删除最后一列
28 if (m_Chart.GetRowCount()>15)
29 {
30 m_Chart.GetDataGrid().DeleteRows(m_rowPos-15,1);
31 }
32 m_iCount++;
33
34 // 把更新复制到粘贴板,在picture中显示
35 m_Chart.EditCopy();
36 if(OpenClipboard())
37 {
38 hDib = GetClipboardData(CF_DIB);
39 CloseClipboard();
40 }
41 BITMAPINFO* pbi= (BITMAPINFO*)GlobalLock(hDib);
42 if (pbi!= NULL)
43 {
44 BYTE* data= (BYTE*)(pbi->bmiColors);
45 if (pbi->bmiHeader.biBitCount<= 8)
46 {
47 int nColor= (pbi->bmiHeader.biClrUsed==0)?
48 1<<(pbi->bmiHeader.biBitCount) : pbi->bmiHeader.biClrUsed;// nColor颜色表中的颜色数
49 data+= sizeof(RGBQUAD)*nColor;
50 }
51 StretchDIBits(pDC->GetSafeHdc(),1,1, pbi->bmiHeader.biWidth-1,
52 pbi->bmiHeader.biHeight-1,0,0, pbi->bmiHeader.biWidth,
53 pbi->bmiHeader.biHeight, data, pbi, DIB_RGB_COLORS, SRCCOPY);// 显示,我为了保留外面的方框,前面宽度和高度都减了1
54 GlobalUnlock(hDib);
55 }
56 m_Chart.Refresh();
57 CView::OnTimer(nIDEvent);
58 }

另外,在动态创建picture control时候一定要注意创建的picture control的大小

MFC+MSChart动态显示曲线

最近需要用MFC做一个界面动态显示曲线,自己画坐标轴画曲线太费时间,网上也有很多已实现的动态曲线接口,但是也不太灵活。正好微软有个现成的MSChart,功能比较全面,查了一些资料,总算实现了无闪烁的动...
  • ZXGIS
  • ZXGIS
  • 2012年01月13日 15:20
  • 6603

使用MSChart实时动态显示折线图

先说一下怎么设置主要属性。  chart1.ChartAreas[0].AxisX.ScrollBar.IsPositionedInside=true;//指滚动条位于图表区内还是图表区外  ch...
  • Shining0
  • Shining0
  • 2013年07月17日 17:56
  • 14131

MsChart实现无闪烁动态曲线(MFC)

实现的原理:MSChart如果要实现动态的曲线就只能在设置的定时器中根据RowCount,到一定的列数后在最后一列插入新一列(m_Chart.GetDataGrid().InsertRows),将最早...
  • misakahina
  • misakahina
  • 2014年01月23日 16:41
  • 2235

MFC下MSChart控件重绘曲线时清除原曲线方法

这段时间用mschart控件,需要不停的绘制曲线,而新的曲线要覆盖掉旧曲线,在网上查了很多相关的方法,要么是重绘mschart控件,要不就是对曲线的值赋0。 而对于动态绘制曲线时,第一种方法效率太低...
  • cindylx422
  • cindylx422
  • 2011年11月14日 14:44
  • 4269

用Microsoft Chart Controls(MSChart)实现曲线图,并支持拖动放大到秒

本文用MSChart实现Winform曲线图的绘制,本文结合自己的实际项目,每个点需要显示到秒(这也是本文需要解决的关键点),刚开始照着网上的例子实现了一下,样子是出来了,但是当数据一多并且显示到秒时...
  • dezhen
  • dezhen
  • 2016年06月18日 14:36
  • 3355

ASP.NET中实现动态曲线图的视频教程

点击下面的入口可以在线观看视频  最近在项目中有个需求,把从数据库中读到的数据输出折线图并且是随着时间的推移动态的显示不同位置的数据这就要用到了动态折线图。刚开始项目中大部分的折线图都是用的MS...
  • enoch_service
  • enoch_service
  • 2012年03月19日 15:23
  • 4475

VC++6.0中使用MsChart总结

说明:本文将网上一些MSChart的使用方法进行了一个总结,按下面的步骤可以实现一个产生三条曲线(每条曲线6个随机数点)的表。 1 在工程中加入 mschart    MSChart是VC++...
  • youoran
  • youoran
  • 2013年01月03日 12:55
  • 11191

mschart绘制曲线图

前台代码
  • pridescc
  • pridescc
  • 2011年12月14日 09:26
  • 3035

MFC 动态曲线 支持缩放 显示图例(CStatic派生类)(续)

前面的文章已经介绍了在MFC环境下绘制动态曲线的方法(双缓冲绘图)和基本的步骤(分三步),以及用到的库函数。下面就介绍一下布局和鼠标响应事件,这里我做过一点 小小的创新(至少我没有看到有前人做过,哈...
  • nuaazdh
  • nuaazdh
  • 2012年08月12日 20:55
  • 7811

MFC中绘制动态曲线

在工控监测领域,经常需要动态绘制曲线,观察曲线的变化趋势,绘制波形图,绘制频谱等。在前面4讲中介绍了MFC经常用的TeeChart控件和Hight-Speed Chart Ctrl,这两个都是MF...
  • zang141588761
  • zang141588761
  • 2016年01月18日 15:02
  • 15850
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:MsChart实现无闪烁动态曲线(MFC)
举报原因:
原因补充:

(最多只允许输入30个字)