MFC+MSChart动态显示曲线

MFC 专栏收录该内容
13 篇文章 0 订阅

  最近需要用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  return   0 ;
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的大小

转自:http://www.cnblogs.com/wy-wangyan/archive/2011/05/13/2045851.html

  • 6
    点赞
  • 3
    评论
  • 11
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值