[MFC]使用ChartCtrl类绘图

本文是基于博主最近在进行的一个项目,项目要求利用MFC绘制出相应的力监测软件,在上网查阅了相关的资料之后,发现网上关于MFC中ChartCtrl绘制曲线的内容鱼龙混杂,故在此对之前学习的一些知识进行总结,希望能帮助到大家学习.

目录

MFC介绍

利用ChartCtrl类进行绘制曲线图

一.利用ChartCtrl类进行绘制静态曲线

二.利用ChartCtrl类进行绘制动态曲线 

 程序源码


MFC介绍

MFC(MicrosoftFoundationClasses)是微软基础类库的简称,是微软公司实现的一个C++类库,主要封装了大部分的windows API函数,vc++是微软公司开发的c/c++的集成开发环境,所谓集成开发环境,就是说利用它可以编辑,编译,调试,而不是使用多种工具轮换操作,灵活性较大。vc也指它的内部编译器,集成开发环境必须有一个编译器内核,例如DevC++其中一个编译器内核就是gcc。 MFC除了是一个类库以外,还是一个框架,在vc++里新建一个MFC的工程,开发环境会自动帮你产生许多文件,同时它使用了mfcxx.dll。xx是版本,它封装了mfc内核,所以你在你的代码看不到原本的SDK编程中的消息循环等等东西,因为MFC框架帮你封装好了,这样你就可以专心的考虑你程序的逻辑,而不是这些每次编程都要重复的东西,但是由于是通用框架,没有最好的针对性,当然也就丧失了一些灵活性和效率。但是MFC的封装很浅,所以效率上损失不大。

刚开始入门的同学可以参考鸡啄米老师对于MFC空间的详细介绍:
《鸡啄米 ----- VS2010/MFC编程入门教程之目录和总结》

网址如下:VS2010/MFC编程入门教程之目录和总结-软件开发-鸡啄米

利用ChartCtrl类进行绘制曲线图

在数据采集中,有的时候需要将采集数据以曲线的方式显示出来,MFC并没有提供容易使用的曲线显示控件,好在有好心人写了ChartCtrl控件,可以很方便的绘制曲线。其代码公开在CodeProject网站:High-speed Charting Control - CodeProject,大家自行下载即可,我也会把我自行绘制的动态曲线图源码贴在文中,下载不了的同学可以参考我的源码进行使用ChartCtrl类.

一.利用ChartCtrl类进行绘制静态曲线

绘制静态曲线是绘制动态曲线的基础,在此我们结合图片向大家演示如何绘制出一个静态曲线图.老版本的VC使用stdafx.h作为预编译头,VS2019使用pch.h作为预编译头,为了方便,干脆取消掉预编译头:属性->c/c+±>预编译头->不使用预编译头,如下图所示:

 将ChartCtrl类里的相关文件分类导入到头文件与源文件中,并生成解决方案,查看是否存在错误.正常编译过之后,添加一个Custom Control控件,曲线控件使用Custom Control作为载体,在窗体上放置Custom Control后,需要设置stytle属性为0x52010000,将Custom Control控件的类设置为ChartCtrl,并修改其合适的ID.

 为Custom Control添加一个合适的变量,在这里我们给变量起名为m_chart.注意控件类型要设置成ChartCtrl,否则有可能会出现与预期结果不一致的情况.

在刚开始需要在头文件中定义我们需要用到的一些变量,比如两条曲线以及为Botton控件添加事件处理程序:

修改MFC中OnInitDialog这个类,这个类主要是实现对基础控件的初始化,对曲线的初始化可以从以下的四部分进行介绍:

  1. 设置标题
  2. 设置坐标轴的属性
  3. 其他设置
  4. 设置曲线

在这里我们以显示北京、哈尔滨、广州三座城市的全年温度曲线图为例,向大家说明一下代码各自实现的功能:

 //在这部分添加初始化后的曲线
	//1.设置标题
	CChartTitle* title = m_chart.GetTitle();//获取指针
	title->AddString(_T("全年温度曲线图"));
	title->SetColor(RGB(0, 0, 0));//设置颜色
	title->SetFont(150, _T("黑体"));//设置字体


	//2. 设置X轴
	CChartAxis* pXAxis = m_chart.CreateStandardAxis(CChartCtrl::BottomAxis);
	pXAxis->SetMinMax(1, 12);//设置极值
	pXAxis->SetAutomatic(false);//设置X轴为不可缩放
	//设置标题
	pXAxis->GetLabel()->SetText(_T("月份"));
	pXAxis->GetLabel()->SetColor(RGB(0, 0, 0));
	pXAxis->GetLabel()->SetFont(140, _T("黑体"));
	//设置栅格颜色
	//pXAxis->GetGrid()->SetColor(RGB(255, 0, 0));
	//设置颜色
	//pXAxis->SetTextColor(RGB(0, 0, 255));
	//设置是否可显
	//pXAxis->SetVisible(false);


	//3.设置Y轴
	CChartAxis* pYAxis = m_chart.CreateStandardAxis(CChartCtrl::LeftAxis);
	pYAxis->SetMinMax(-10, 40);//设置极值
	pYAxis->SetAutomatic(false);//设置Y轴为不可缩放
	//设置标题
	pYAxis->GetLabel()->SetText(_T("温度(℃)"));
	/*pYAxis->GetLabel()->SetColor(RGB(0, 0, 0));
	pYAxis->GetLabel()->SetFont(140, _T("黑体"));*/
	//设置栅格颜色
	//pYAxis->GetGrid()->SetColor(RGB(255, 0, 0));
	//设置颜色
	//pYAxis->SetTextColor(RGB(0, 0, 255));
	//设置是否可显
	//pYAxis->SetVisible(false);

	//4.其他设置
	m_chart.GetLegend()->SetVisible(true);//设置图例显示
	m_chart.SetPanEnabled(false);//设置为不可拖动
	m_chart.SetZoomEnabled(false);//设置为不可缩放
	//去除边框
	m_chart.SetEdgeType(0);


	//5.设置曲线
	//创建曲线
	m_pLineSerie = m_chart.CreateLineSerie();
	m_pLineSerie2 = m_chart.CreateLineSerie();
	//设置宽度
	m_pLineSerie->SetWidth(2);
	m_pLineSerie2->SetWidth(2);
	//设置颜色
    //曲线1为红色
	m_pLineSerie->SetColor(RGB(255, 0, 0));
    //曲线2为蓝色
	m_pLineSerie2->SetColor(RGB(0, 0, 255));
	//设置阴影
	m_pLineSerie->EnableShadow(true);
	m_pLineSerie2->EnableShadow(true);
	//图例曲线含义
	m_pLineSerie->SetName(_T("日均最高气温"));
	m_pLineSerie2->SetName(_T("日均最低气温"));
	//默认显示北京温度
	OnBnClickedButtonBeijing();

为Botton1、Botton2、Botton3分贝添加事件处理程序用于显示北京、哈尔滨、广州的全年温度曲线.因为是温度曲线图,所以X轴输入月份,Y轴输入温度,两条曲线分别最高和最低的温度曲线.

void CStaticLine2Dlg::OnBnClickedButtonBeijing()
{
	// TODO: 在此添加控件通知处理程序代码
    //清除标题
	m_chart.GetTitle()->RemoveAll();
    //设置标题
	m_chart.GetTitle()->AddString(_T("北京-全年温度曲线图"));
	//清除数据
	m_pLineSerie->ClearSerie();
	m_pLineSerie2->ClearSerie();
	//X轴数据
	double xMonth[12] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
	//Y轴极值
	m_chart.GetLeftAxis()->SetMinMax(-10, 40);
    //最高温度值
	double highTemp[12] = { 1,3,10,18,28,34,38,35,26,17,10,3 };
	//最低温度值
	double lowTemp[12] = { -6,-4,3,10,12,23,23,16,10,6,2,-1 };
   //绘制曲线
	m_pLineSerie->AddPoints(xMonth, highTemp, 12);
	m_pLineSerie2->AddPoints(xMonth, lowTemp, 12);
}

静态曲线绘制结果如下所示,图中数据并未经过官方考核,仅用于显示温度曲线,与实际情况存在偏差.

二.利用ChartCtrl类进行绘制动态曲线 

动态曲线图和静态曲线图在基础属性设置上基本一致,本文以"实时力监测软件"为例,进行说明动态曲线图的绘制.力监测软件的初始界面如下:

 因为整个监测软件采用Modbus TCP协议进行传输数据,因此需要输入相应的IP地址和对应的端口号,并点击"开始采集"按钮,右侧Custom Control自定义控件显示六十组相关数据,当超过六十组数据,X轴进行自更新,显示后续的数据.右上角进行显示力控法兰的实时受力数据.

对于MFC中OnInitDialog类,将原来静态曲线图中的两条曲线修改成一条曲线,其余部分变动不大,在此就不进行过多介绍.

动态曲线图的绘制关键在于MFC中的定时器Timer,相应的函数类型有SetTimer和KillTimer等.

SetTimer相关参数的介绍: 

第一个参数代表定时器的代号,以0、1、2等数字进行表示,第二个参数代表每次间隔的毫秒数,第三个参数可以设置成NULL即可.为"开始采集"按钮添加事件处理程序并启动定时器程序.

void CStaticLine2Dlg::OnTimer(UINT_PTR nIDEvent)
{
	//清空曲线
	m_pLineSerie->ClearSerie();
	//初始化定义m_Tick参数
	m_Tick++;
	if (m_Tick <= 60)
	{
		//X轴范围[0-60]
		m_chart.GetBottomAxis()->SetMinMax(0, 60);
		m_chart.GetBottomAxis()->SetAutomatic(false);//不可缩放
		//Y轴范围[0-2000]
		m_chart.GetLeftAxis()->SetMinMax(0, 2000);
		//输入X轴数据
		for (int i = 0; i < m_Tick; i++)
		{
			m_XSecond[i] = i;
		}
        //输入Y轴数据
		if (m_Tick == 1)
		{
			m_YTemperature[0] = 0;
		}
		else
		{
			number= rand() % 100 + 1000;
			m_YTemperature[m_Tick - 1] = number;
            //实时力控显示
			SetDlgItemInt(IDC_EDIT_POWER, number);
		}
	}
	else
	{
        //设置X轴可缩放
		m_chart.GetBottomAxis()->SetAutomatic(true);
		//Y轴范围
		m_chart.GetLeftAxis()->SetMinMax(0, 2000);
        //X轴数据更迭
		for (int i = 1; i < 60; i++)
		{
            //覆盖数据
			m_XSecond[i - 1] = m_XSecond[i];

		}
		//填充新数据
		m_XSecond[59] = m_Tick;
        //Y轴数据更迭
		for (int i = 1; i < 60; i++)
		{
			m_YTemperature[i - 1] = m_YTemperature[i];
		}
		m_YTemperature[59] = rand() % 100 + 1000;
		SetDlgItemInt(IDC_EDIT_POWER, m_YTemperature[59]);

	}

	//绘制曲线
	if (m_Tick >= 60)
	{
        //绘制60个点
		m_pLineSerie->AddPoints(m_XSecond, m_YTemperature, 60);
	}
	else
	{
        //绘制m_Tick个点
		m_pLineSerie->AddPoints(m_XSecond, m_YTemperature, m_Tick);
	}
	CDialogEx::OnTimer(nIDEvent);
}

绘制完成之后,点击"停止采集"按钮,关闭定时器程序.程序运行示意图如下:

前六十组数据采集:

后续数据采集:

 程序源码

如需程序源码,请移步Gittee:MFC: MFC静态曲线和动态曲线绘制 

<think>嗯,用户想了解如何在MFC项目中使用ChartCtrl,特别是使用方法和示例教程。让我先回忆一下之前学过的相关知识。 首先,ChartCtrl是一个MFC的图表控件,可以用来绘制各种图表,比如曲线图、柱状图等。用户可能需要在他们的应用程序中显示数据可视化,所以需要知道如何集成和使用这个控件。根据用户提供的引用,特别是引用[1]、[2]、[3],里面提到了添加库、配置轴和示例代码。 我需要先整理步骤。第一步应该是如何将ChartCtrl添加到项目中。根据引用[1],用户需要添加ChartCtrl库,这可能包括头文件和库文件的路径设置,以及链接库。然后,在代码中初始化控件,设置轴属性,如引用[2]中的例子,创建左轴并设置范围和标签。 接下来是具体的绘图步骤。例如,添加数据系列,比如曲线或柱状图。引用[3]提到了波形显示的实例源码,可能涉及如何动态更新数据。用户可能需要知道如何创建系列、设置数据点以及如何更新图表。 还要考虑常见问题,比如控件不显示或者数据不更新,这可能涉及到重绘或数据刷新机制。此外,引用提供的示例项目地址可能对用户有帮助,可以建议他们下载源码参考。 需要确保回答结构清晰,分步骤说明,同时引用相关的引用内容。例如,在添加库的部分引用[1],在设置轴时引用[2],在示例部分提到引用[3]的源码。可能还需要提醒用户注意MFC的基础操作,比如对话框控件的添加和变量关联。 最后,生成相关的问题,比如如何动态更新数据或者处理大量数据,这样用户可以进一步探索。同时确保所有数学公式按照要求使用$...$格式,不过在这个主题中可能用不上数学公式,但需要检查是否有其他需要格式化的地方。</think>### Chart控件使用指南 ### 一、环境配置 1. **添加库文件**:将ChartCtrl头文件(.h)和源文件(.cpp)复制到项目目录,在stdafx.h中添加`#include "ChartCtrl.h"`[^1] 2. **控件初始化**:在对话框的`OnInitDialog()`中创建控件: ```cpp m_ChartCtrl.Create(WS_CHILD | WS_VISIBLE, CRect(10,10,400,300), this, IDC_CHARTCTRL); ``` ### 二、基础图表绘制 #### 曲线图示例 ```cpp // 创建数据系列 CChartLineSerie* pSeries = m_ChartCtrl.CreateLineSerie(); double x[] = {1,2,3,4,5}; double y[] = {10,25,30,15,40}; pSeries->SetPoints(x, y, 5); // 配置坐标轴 CChartStandardAxis* pBottomAxis = m_ChartCtrl.CreateStandardAxis(CChartCtrl::BottomAxis); pBottomAxis->SetMinMax(1, 5); pBottomAxis->SetText(_T("时间(秒)")); CChartStandardAxis* pLeftAxis = m_ChartCtrl.CreateStandardAxis(CChartCtrl::LeftAxis); pLeftAxis->SetMinMax(0, 50); pLeftAxis->SetText(_T("温度(℃)")); // 引用[2]的轴配置方法 ``` #### 柱状图实现 ```cpp CChartBarSerie* pBarSeries = m_ChartCtrl.CreateBarSerie(); pBarSeries->SetPoints(y, 5); // 直接设置Y值 pBarSeries->SetBarColor(RGB(0,150,200)); // X轴标签设置 CChartAxisLabel* pLabels = pBottomAxis->GetLabel(); pLabels->SetText(_T("月份")); pLabels->SetAngle(45); // 倾斜显示标签 ``` ### 三、高级功能 1. **动态更新**:通过定时器刷新数据点 ```cpp void CMyDialog::OnTimer(UINT_PTR nIDEvent) { if(nIDEvent == 1) { CChartLineSerie* pSeries = m_ChartCtrl.GetSerie(0); pSeries->AddPoint(newX, newY); // 引用[3]的波形更新方法 m_ChartCtrl.RefreshCtrl(); } } ``` 2. **样式定制**: ```cpp // 设置网格线 pLeftAxis->SetGrid(true, PS_DOT, 1, RGB(200,200,200)); // 修改曲线样式 pSeries->SetColor(RGB(255,0,0)); pSeries->SetWidth(2); ``` ### 四、常见问题解决 1. **控件不显示**:检查WS_VISIBLE样式是否添加 2. **数据不刷新**:调用RefreshCtrl()后需要Invalidate() 3. **内存泄漏**:使用ClearSerie()替代直接删除系列
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胡须不排序H

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值