MFC画折线图,基于x64系统

由于项目的需要,需要画一个折线图。

传统的Teechart、MSChart、HighSpeedChart一般是只能配置在x86系统下,等到使用x64系统下运行就是会报出不知名的错误,这个地方让人很苦恼。

我在进行配置的过程之中,使用Teechart将x86配置好了,可以正常使用,但是嫁接到x64系统下就不可以使用了。HighSpeedChart也是同样在x64系统下使用会出现如下错误,并且在进行设置x轴的时候,x轴类型只能是int类型,贼其难用。配置了半天结果x64位用不了,x64系统真的不建议使用上述控件方式。

经过长时间的思索,还是直接用代码画一个吧,配置环境过于困难。

首先拉出一个Picture Control控件,然后将其ID进行更改为IDC_PIC_CTRL

在自己的.h文件之中进行定义变量

    CStatic m_PicCtrl2;
    CRect m_rect;

然后在相应的按钮下进行功能的定义(以依次修改按钮为例)

// TODO: 在此添加控件通知处理程序代码
int click = 6;
std::vector<CString> use;
std::vector<std::string> xAxisLabels = { "0"};
std::vector<double> yAxisValues = { 0 };




void CMFCApplication2Dlg::OnBnClickedButton5()
{
	
	CPaintDC dc(this); // 使用设备上下文绘制

					   // 清空窗口
	CRect rect;
	GetClientRect(&rect); // 获取绘制区域大小
	dc.FillSolidRect(rect, RGB(255, 255, 255)); // 填充白色背景

												// 绘制图形的代码
												// ...
	CWnd* pWnd = GetDlgItem(IDC_PIC_CTRL); // 获取Picture Control的指针
	pWnd->GetClientRect(&rect); // 获取绘制区域大小

	CDC* pDC = pWnd->GetDC(); // 获取绘图设备上下文

							  // 绘制背景
	pDC->FillSolidRect(rect, RGB(255, 255, 255));


	// 设置坐标轴参数
	int marginX = rect.Width() / 8.0;
	int marginY = rect.Height() / 8.0;


	time_t now = time(0);
	tm* localTime = localtime(&now);
	char buffer[80];
	strftime(buffer, 80, "%Y-%m-%d 仰角角度测量试验", localTime);
	CString cstringTime(buffer);

	CString chartTitle = (cstringTime) ;

	
	CString xAxisTitle = _T("时间(时:分:秒)");
	CString yAxisTitle = _T("角度(°)");
	// 绘制横轴线和纵轴线
	pDC->MoveTo(rect.left + marginX + 3, rect.bottom - marginY * 1.5);
	pDC->LineTo(rect.right - marginX, rect.bottom - marginY * 1.5);
	pDC->MoveTo(rect.left + marginX, rect.top + marginY * 1.5);
	pDC->LineTo(rect.left + marginX, rect.bottom - marginY * 1.5 - 3);


	// 绘制箭头线
	/*
	pDC->MoveTo(rect.right - marginX, rect.bottom - marginY * 1.5);
	pDC->LineTo(rect.right - marginX - 6.0, rect.bottom - marginY * 1.5 - 6.0);
	pDC->MoveTo(rect.right - marginX, rect.bottom - marginY * 1.5);
	pDC->LineTo(rect.right - marginX - 6.0, rect.bottom - marginY * 1.5 + 6.0 );
	*/
	

	
	
	

	// 绘制坐标轴标题
	pDC->SetBkMode(TRANSPARENT);

	// 设置大标题文本颜色
	pDC->SetTextColor(RGB(0, 0, 255)); // 深蓝色
	// 设置大标题文本粗细
	CFont font;
	font.CreateFont(16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
		CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, _T("Arial")); // 创建一个16像素的粗体Arial字体

	pDC->SelectObject(&font); // 设置字体


	pDC->TextOut(rect.Width() / 2, rect.bottom - marginY * 0.5, chartTitle);//大标题

	// 设置大标题文本颜色
	pDC->SetTextColor(RGB(0, 0, 0)); // 黑色
	pDC->TextOut(rect.left + (double)marginX * 7.2, rect.bottom - marginY * 1.6, xAxisTitle);//x轴标题
	pDC->TextOut(rect.left + marginX - 30, rect.top + marginY / 2, yAxisTitle);//Y轴标题


	//std::vector<std::string> xAxisLabels = { "0","北京", "上海", "南京" };
	//std::vector<double> yAxisValues = { 0,0.2, 0.5, 1.8 };
	std::string currentTime = getCurrentTimeAsString();
	//点击次数增加
	if (yAxisValues.size() == 1)
	{
		xAxisLabels.push_back(currentTime);
		
		
			
		yAxisValues.push_back(2.2);
	}
	else if (yAxisValues.size() == 2)
	{
		xAxisLabels.push_back(currentTime);
		yAxisValues.push_back(4.2);
	}
	else if (yAxisValues.size() == 3)
	{
		xAxisLabels.push_back(currentTime);
		yAxisValues.push_back(1.2);

	}
	else if (yAxisValues.size() == 4)
	{
		xAxisLabels.push_back(currentTime);
		yAxisValues.push_back(2.2);
	}
	else if (yAxisValues.size() == 5)
	{
		xAxisLabels.push_back(currentTime);
		yAxisValues.push_back(6.2);
	}
	else if (yAxisValues.size() == 6)
	{
		xAxisLabels.push_back(currentTime);
		yAxisValues.push_back(5.2);
	}
	else
	{
		//当点击次数大于六次
		xAxisLabels.erase(xAxisLabels.begin());
		yAxisValues.erase(yAxisValues.begin());
		xAxisLabels.push_back(currentTime);
		yAxisValues.push_back(8.2);
	}

	int numPoints = yAxisValues.size();
	int xInterval = (rect.Width() - 2 * marginX) / (numPoints - 1);//x轴间隔
	int yInterval = (rect.Height() - 2 * marginY) / (13 - 1);//y轴间隔   这个地方的是纵轴的最大数量

	// 绘制横轴标签刻度
	for (int i = 0; i < numPoints; i++)
	{
		int x = rect.left + marginX + i * xInterval;
		CPen pen;
		pen.CreatePen(PS_SOLID, 1, RGB(0, 0, 210)); // 创建一个红色的实线画笔
		pDC->SelectObject(&pen); // 设置画笔
		
		pDC->MoveTo(x, rect.bottom - marginY * 1.5); //横轴小标记
		pDC->LineTo(x, rect.bottom - marginY * 1.5 + 5);
		pDC->TextOut(x - 10, rect.bottom - marginY * 1.5 + 10, CString(xAxisLabels[i].c_str()));
	}

	//将最大的值进行/12操作,
	for (int i = 0; i < 13; i++)//重新绘制纵轴  这个地方的8是最大值
	{
		// 寻找最大值的迭代器
		auto maxIt = std::max_element(yAxisValues.begin(), yAxisValues.end());

		double maxValue;
		// 如果找到了最大值,则打印它
		if (maxIt != yAxisValues.end())
		{
			maxValue = *maxIt;
		}
		CPen pen;
		pen.CreatePen(PS_SOLID, 1, RGB(0, 0, 210)); // 创建一个红色的实线画笔
		pDC->SelectObject(&pen); // 设置画笔

		double y = (double)(rect.bottom) - (double)marginY * 1.5 - ((double)10.0 / (double)12.0 * (double)i) * (double)yInterval; //根据实际大小进行设定  这个地方需要注意yInterval变量与
		pDC->MoveTo(rect.left + marginX, y);     //纵轴小标记
		pDC->LineTo(rect.left + marginX - 5, y);

		double value = (maxValue / (double)12.0) * (double)i; // 假设i是一个整数变量
		std::stringstream ss;
		ss << std::fixed << std::setprecision(4) << value;
		std::string strValue = ss.str();
		CString cstrValue(strValue.c_str());

		pDC->TextOut(rect.left + marginX * 0.8 - 30, y - 5, cstrValue);
	}

	// 绘制折线
	for (int i = 0; i < numPoints - 1; i++)
	{
		int x1 = rect.left + marginX + i * xInterval;
		int y1 = rect.bottom - marginY * 1.5 - (yAxisValues[i]*12.0/10.0) * yInterval;
		int x2 = rect.left + marginX + (i + 1) * xInterval;
		int y2 = rect.bottom - marginY * 1.5 - (yAxisValues[i + 1]*12.0/10.0) * yInterval;
		CPen pen;
		pen.CreatePen(PS_SOLID, 1, RGB(125, 0, 0)); // 创建一个红色的实线画笔
		pDC->SelectObject(&pen); // 设置画笔
		pDC->MoveTo(x1, y1);
		pDC->LineTo(x2, y2);
		pDC->SetTextColor(RGB(255, 0, 0)); // 深蓝色
		//绘制数值
		pDC->TextOut(x2 - 8, y2 - 20, CString(std::to_string(yAxisValues[i+1]).c_str()));//这个地方的标记需要变成4个小数点
	}

	


	pWnd->ReleaseDC(pDC);
}

在使用上述代码的时候需要进行头文件的引入


#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <atlstr.h>

#include <iostream>
#include <ctime>
#include <cstring>

#include <iostream>
#include <sstream>
#include <chrono>
using namespace std;

最后测试的展示情况是如下所示:

上述的依次添加按钮是按下一次,添加一个折现,只是个示例的过程,也可以改为实时动态的过程,只要添加个定时器就可以了,比较简单。关于界面部分,自己进行修改修改,进行美化一下就可以使用了。上述代码比较通俗易懂,按照自己的逻辑写的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/247862.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

卫星影像5天一更新的地图网站

如果全球影像每5天一更新&#xff0c;并集多种地图数据源于一体的PB级海量地图数据该怎样去管理呢&#xff1f; 这是当我了解到SOAR网站之后&#xff0c;思考过的一个问题。 全球最大的在线地图网站 在SOAR的官方网站&#xff0c;据称它是世界上最大的在线地图网站。 它是集…

大数据Doris(三十六):Duplicate 模型(冗余模型)介绍

文章目录 Duplicate 模型(冗余模型)介绍 一、创建doris表 二、插入数据

Unity中Batching优化的GPU实例化整理总结

文章目录 前言一、GPU Instancing的支持1、硬件支持2、Shader支持3、脚本支持 二、我们来顺着理一下GPU实例化的使用步骤1、GPU实例化前的C#代码准备2、在 appdata 和 v2f 中定义GPU实例化ID3、在顶点着色 和 片元着色器 设置GPU Instance ID&#xff0c;使实例化对象顶点位置正…

05-详解Nacos配置管理中心,配置拉取的方式,热更新,配置共享(优先级)的步骤

Nacos配置管理 新建配置文件 当微服务部署的实例越来越多时,如果需要修改微服务的配置就需要逐个修改配置文件并且还要重启关联的微服务十分繁琐还易出错 项目中的配置文件分为每个项目特有的配置,项目所公用的配置 每个项目特有的配置: 有些项目中需要但有些项目中又不需要…

7. 异常、断言及日志

1.异常 1).什么是异常 异常&#xff0c;就是不正常的意思。指的是程序在执行过程中&#xff0c;出现的非正常的情况&#xff0c;最终会导致JVM的非正常停止。 在Java等面向对象的编程语言中&#xff0c;异常本身是一个类&#xff0c;产生异常就是创建异常对象并抛出了一个异常…

软件测试职业规划

软件测试人员的发展误区【4】 公司开发的产品专业性较强&#xff0c;软件测试人员需要有很强的专业知识&#xff0c;现在软件测试人员发展出现了一种测试管理者不愿意看到的景象&#xff1a; 1、开发技术较强的软件测试人员转向了软件开发(非测试工具开发)&#xff1b; 2、业务…

采埃孚4D成像雷达拆解

1 基本信息 品牌&#xff1a;海外Tier1采埃孚 • 应用&#xff1a;上汽飞凡中高端纯电平台 • 数量&#xff1a;单车2个&#xff0c;安装在前后保内部 • 最远探测距离&#xff1a;350米 拆解来看&#xff0c;4D雷达主要可以分为4个部分&#xff0c;分别为数字接口板及结构件…

mac视频调色 DaVinci Resolve Studio 18 中文 for Mac

DaVinci Resolve Studio 18是一款功能强大、专业可靠的视频编辑软件&#xff0c;适用于各种规模的媒体项目制作。无论是独立制片人还是大型制片公司&#xff0c;都可以借助该软件进行高质量的视频创作和后期制作。 得编辑工作更加高效和灵活。 调色和色彩校正&#xff1a;软件…

CSS的盒子模型(重点)

网页布局的三大核心&#xff1a;盒子模型、浮动、定位 网页布局的过程&#xff1a; 1. 先准备好相关的网页元素&#xff0c;网页元素基本都是盒子 Box 。 2. 利用 CSS 设置好盒子样式&#xff0c;然后摆放到相应位置。 3. 往盒子里面装内容.网页布局的核心本质&#xff1a; 就…

或许是全网最全的延迟队列

什么是延迟队列 作用&#xff1a;用来存储延迟消息延迟消息&#xff1a;生产者发送一个消息给mq&#xff0c;然后mq会经过一段时间&#xff08;延迟时间&#xff09;&#xff0c;然后在把这个消息发送给消费者 应用场景 预定会议后&#xff0c;需要在预定的时间点前十分钟通…

深拷贝、浅拷贝 react的“不可变值”

知识获取源–晨哥&#xff08;现实中的人 嘿嘿&#xff09; react中如果你想让一个值始终不变 或者说其他操作不影响该值 它只是作用初始化的时候 使用了浅拷贝–改变了初始值 会改变初始值(selectList1) 因为使用浅拷贝都指向同一个地址 const selectList1 { title: 大大, …

RabbitMQ入门案例

RabbitMQ 是目前比较主流的MQ消息队列中间件&#xff0c;下面简单总结RabbitMQ入门时所做的一些笔记 1.RabbitMQ 入门案例 需求&#xff1a;用 Java 编写两个程序。发送单个消息的生产者和接收消息并打印出来的消费者 1.1 添加依赖 <!--rabbitmq 依赖客户端--> <de…

开具实习证明:在线实习项目介绍

大数据在线实习项目&#xff0c;是在线上为学生提供实习经验的项目。我们希望能够帮助想要在毕业后从事数据科学类工作的学生更加顺利地适应从教室到职场的转换&#xff1b;也帮助那些在工作中需要处理数据、实现数据价值的其他职能的从业者高效快速地掌握每天都能用起来的数据…

Vue.js 使用基础知识

Vue.js 是一款用于构建用户界面的渐进式框架&#xff0c;它专注于视图层。Vue.js 不同于传统的 JavaScript 框架&#xff0c;它采用了组件化的开发方式&#xff0c;使得开发者可以更加高效和灵活地构建交互式的 Web 应用程序。 目录 什么是 Vue.js安装 Vue.jsVue 实例模板语法插…

2024年天津体育学院专升本专业课网上报名确认缴费安排

天津体育学院2024年高职升本科专业考试报名安排 一、时间安排 1.报名时间&#xff1a;2023年12月19日9&#xff1a;00-12月21日17&#xff1a;00 2.缴费时间&#xff1a;2023年12月26日-27日 &#xff08;考试考务费&#xff1a;体育教育专业&#xff1a;160元/人&#xff…

深入分析ClassLocader工作机制

文章目录 一、ClassLoader简介1. 概念2. ClassLoader类结构分析 二、ClassLoader的双亲委派机制三、Class文件的加载流程1. 简介2. 加载字节码到内存3. 验证与解析4. 初始化Class对象 四、常见加载类错误分析1. ClassNotFoundException2. NoClassDefFoundError3. UnsatisfiledL…

用Excel绘制柱形图

在需要将数据用柱状图表示的时候&#xff0c;可以用Excel进行绘制。不单绘制柱形图&#xff0c;其他数据图也可以用Excel绘制。 接下来用绘制一个销售表的示例演示。 1.将数据输入Excel 数学书 语文书 英语书 一月 80 94 77 二月 95 86 84 三月 130 93 79 四月 …

测出Bug就完了?从4个方面教你Bug根因分析

一现状及场景 1、缺失bug根因分析环节 工作10年&#xff0c;虽然不是一线城市&#xff0c;也经历过几家公司&#xff0c;规模大的、规模小的都有&#xff0c;针对于测试行业很少有Bug根因环节&#xff0c;主流程基本上都是测试提交bug-开发修改-测试验证-发送报告&#xff0c…

2023版本QT学习记录 -2- 标准文件对话框

头文件的使用 #include "QFileDialog"函数原型 getOpenFileName效果 参数 未完待续

工业固体废物智能化综合管控平台

工业固体废物智能化综合管控平台&#xff0c;涵盖产废企业、运输企业、固废处置企 业等不同群体应用&#xff0c;根据不同群体设计不同的业务应用子系统功能&#xff0c;以及各个不 同群体的环保物联网平台子系统功能模块&#xff0c;同时具有移动端的应用APP。 建立产废企业端…