[MFC]使用ChartCtrl类绘图

发布于:2023-01-04 ⋅ 阅读:(1269) ⋅ 点赞:(1)

本文是基于博主最近在进行的一个项目,项目要求利用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静态曲线和动态曲线绘制 

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到