C++第四十四篇 -- MFC使用ChartCtrl绘制动态曲线
前言
目的:使用控制台程序带MFC类库画一个动态曲线图
参考链接:
https://blog.csdn.net/sinat_29890433/article/details/105360032
https://github.com/jobschu/waveDisplayUseChartCtrl
操作步骤
1. 创建一个勾选MFC类库的控制台程序
上一章讲过,此处不做赘述。
2. 新建一个窗口程序
3. 编写动态折线图
chart.cpp


// chart.cpp : implementation file
//
#include "pch.h"
#include "stdafx.h"
#include "CPUUsage.h"
#include "chart.h"
#include "afxdialogex.h" // chart dialog IMPLEMENT_DYNAMIC(chart, CDialog) chart::chart(CWnd* pParent /*=nullptr*/)
: CDialog(IDD_chart, pParent)
{
} chart::~chart()
{
} void chart::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_CUSTOM_CHART, m_ChartCtrl);
} BEGIN_MESSAGE_MAP(chart, CDialog)
ON_WM_SIZE()
ON_WM_TIMER()
ON_WM_PAINT()
END_MESSAGE_MAP() #define DATA_SHOW_LENGHT 2000 //总共显示的点个数
#define DATA_UPDATE_LENGHT 10 //每次更新的点个数
#define DATA_SHOW_X_AXIS 2000 //X轴显示的点最大值
#define DATA_SHOW_Y_AXIS 1000 //Y轴显示的点最大值
//要显示点的缓冲数据
static double xBuff[DATA_SHOW_LENGHT] = { 0 };
static double yBuff[DATA_SHOW_LENGHT] = { 0 }; //显示点数据包初始化
void chart::DataBuffInit(void)
{
for (int i = 0; i < DATA_SHOW_LENGHT; i++) {
xBuff[i] = i;
yBuff[i] = 50;// cos((i)) * 10 + 50;
}
} //初始化画图界面窗口
void chart::ChartCtrlInit(void) {
//手动创建显示窗口
//CRect rect, rectChart;
//GetDlgItem(IDC_CUSTOM_SHOW)->GetWindowRect(&rect);
//ScreenToClient(rect);
//rectChart = rect;
//rectChart.top = rect.bottom + 3;
//rectChart.bottom = rectChart.top + rect.Height();
//m_ChartCtrl2.Create(this, rectChart, IDC_CUSTOM_SHOW2);
//m_ChartCtrl2.ShowWindow(SW_SHOWNORMAL);
///////////////////////显示主题/////////////////////////////
m_ChartCtrl.GetTitle()->AddString(_T("CPU Usage"));
///////////////////////创建坐标xy标识/////////////////////////////
//m_ChartCtrl.GetBottomAxis()->GetLabel()->SetText(_T("强度"));
//m_ChartCtrl.GetLeftAxis()->GetLabel()->SetText(_T("采样点"));
///////////////////////创建坐标显示范围/////////////////////////////
CChartAxis *pAxis = NULL;
pAxis = m_ChartCtrl.CreateStandardAxis(CChartCtrl::BottomAxis);
pAxis->SetMinMax(0, DATA_SHOW_X_AXIS);
pAxis = m_ChartCtrl.CreateStandardAxis(CChartCtrl::LeftAxis);
pAxis->SetMinMax(0, DATA_SHOW_Y_AXIS);
} // CmyApplicationDlg 消息处理程序
BOOL chart::OnInitDialog()
{
CDialog::OnInitDialog();
//获取显示的对话框大小
CRect rect;
GetClientRect(&rect);
oldPiont.x = rect.right - rect.left;
oldPiont.y = rect.bottom - rect.top;
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作 // TODO: 在此添加额外的初始化代码
DataBuffInit();
ChartCtrlInit(); SetTimer(0, 100, NULL);
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
} // 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。 void chart::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2; }
else
{
CDialog::OnPaint();
}
} void chart::Resize(void) {
float fsp[2];
POINT newPoint;//获取当前对话框大小
CRect newRect;//获取当前对话框的坐标
GetClientRect(&newRect);
newPoint.x = newRect.right - newRect.left;
newPoint.y = newRect.bottom - newRect.top;
fsp[0] = (float)newPoint.x / oldPiont.x;
fsp[1] = (float)newPoint.y / oldPiont.y; int woc;
CRect rect;
CPoint oldTLPoint, newTLPoint;//左上角
CPoint oldBRPoint, newBRPoint;//右下角
//列出所有的子空间
HWND hwndChild = ::GetWindow(m_hWnd, GW_CHILD);
while (hwndChild) {
woc = ::GetDlgCtrlID(hwndChild);//取得ID
GetDlgItem(woc)->GetWindowRect(rect);
ScreenToClient(rect); oldTLPoint = rect.TopLeft();
newTLPoint.x = long(oldTLPoint.x*fsp[0]);
newTLPoint.y = long(oldTLPoint.y*fsp[1]);
oldBRPoint = rect.BottomRight();
newBRPoint.x = long(oldBRPoint.x*fsp[0]);
newBRPoint.y = long(oldBRPoint.y*fsp[1]); rect.SetRect(newTLPoint, newBRPoint);
GetDlgItem(woc)->MoveWindow(rect, TRUE);
hwndChild = ::GetWindow(hwndChild, GW_HWNDNEXT);
}
oldPiont = newPoint;
return;
}
void chart::OnSize(UINT nType, int cx, int cy) {
//窗体大小发生变动。处理函数resize
if (nType == SIZE_RESTORED || nType == SIZE_MAXIMIZED)
{
Resize();
}
}
void chart::DataShow(double *xb, double *yb, int len) {
m_ChartCtrl.EnableRefresh(false);
CChartLineSerie *pLineSerie;
m_ChartCtrl.RemoveAllSeries();
pLineSerie = m_ChartCtrl.CreateLineSerie();
pLineSerie->SetSeriesOrdering(poNoOrdering);//设置为无序
pLineSerie->AddPoints(xb, yb, len);
UpdateWindow();
m_ChartCtrl.EnableRefresh(true);
}
void chart::OnTimer(UINT nIDEvent) {
static int offset = 0;
for (int m = 0; m < DATA_SHOW_LENGHT - DATA_UPDATE_LENGHT; m++)
{
//xd[m] = xd[DATA_UPDATE_LENGHT + m];
yBuff[m] = yBuff[DATA_UPDATE_LENGHT + m];
}
int index = DATA_SHOW_LENGHT - DATA_UPDATE_LENGHT;
for (int i = 0; i < DATA_UPDATE_LENGHT; i++)
{
//yd[index + i] = cos((index + i + w)/5) * 50 + 100+rand() / 1000;
yBuff[index + i] = cos((i + offset) / 5) * DATA_SHOW_Y_AXIS / 4 + rand() / 1000 + DATA_SHOW_Y_AXIS / 2;
}
DataShow(xBuff, yBuff, DATA_SHOW_LENGHT);
offset++;
if (offset > 10000) {
offset = 0;
}
}
chart.h


#pragma once
#include "ChartCtrl/ChartCtrl.h"
#include "ChartCtrl/ChartTitle.h"
#include "ChartCtrl/ChartLineSerie.h"
#include "ChartCtrl/ChartAxisLabel.h" // chart dialog class chart : public CDialog
{
DECLARE_DYNAMIC(chart) public:
chart(CWnd* pParent = nullptr); // standard constructor
virtual ~chart(); // Dialog Data
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_chart };
#endif protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support // 实现
protected: // 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnTimer(UINT nIDEvent);
DECLARE_MESSAGE_MAP() public:
POINT oldPiont;
void Resize(void);
CChartCtrl m_ChartCtrl;
void ChartCtrlInit(void);
void DataBuffInit(void);
void DataShow(double *xb, double *yb, int len);
};
4. 控制台调用动态折线图


chart *chartdialog = new chart;
int ReturnValue = chartdialog->DoModal(); // Show the dialog
printf("%d", ReturnValue);
效果图
可能出现的问题
1. 在编译的时候,ChartCtrl里面的cpp老是出现没有"pch.h"即预编译头的问题,所以干脆取消了预编译头进行编译。
2. 将ChartCtrl库放到项目里。添加之后取名为ChartCtrl,然后将文件都已Add --> Existing Item的方式加进项目里。ChartCtrl文件夹的存放路径与控制台的cpp文件同目录。
源码:
CPUUsage.cpp


// CPUUsage.cpp : This file contains the 'main' function. Program execution begins and ends there.
// #include "pch.h"
#include "framework.h"
#include "chart.h"
#include "CPUUsage.h" #ifdef _DEBUG
#define new DEBUG_NEW
#endif // The one and only application object CWinApp theApp; using namespace std; int main()
{
int nRetCode = 0; HMODULE hModule = ::GetModuleHandle(nullptr); if (hModule != nullptr)
{
// initialize MFC and print and error on failure
if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0))
{
// TODO: code your application's behavior here.
wprintf(L"Fatal Error: MFC initialization failed\n");
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
chart *chartdialog = new chart;
int ReturnValue = chartdialog->DoModal(); // Show the dialog
printf("%d", ReturnValue);
}
}
else
{
// TODO: change error code to suit your needs
wprintf(L"Fatal Error: GetModuleHandle failed\n");
nRetCode = 1;
} return nRetCode;
}
OK.
C++第四十四篇 -- MFC使用ChartCtrl绘制动态曲线的更多相关文章
- C++第四十五篇 -- MFC关闭调用的窗口
调用窗体的方法: // chart是一个MFC的窗体类 chart *chartdialog = new chart; //调用窗体,获取返回值 int ReturnValue = chartdial ...
- 第四十四个知识点:在ECC密码学方案中,描述一些基本的防御方法
第四十四个知识点:在ECC密码学方案中,描述一些基本的防御方法 原文地址:http://bristolcrypto.blogspot.com/2015/08/52-things-number-44-d ...
- NeHe OpenGL教程 第四十四课:3D光晕
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- 网站开发进阶(四十四)input type="submit" 和"button"的区别
网站开发进阶(四十四)input type="submit" 和"button"的区别 在一个页面上画一个按钮,有四种办法: 这就是一个按钮.如果你不写ja ...
- Gradle 1.12用户指南翻译——第四十四章. 分发插件
本文由CSDN博客貌似掉线翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...
- SQL注入之Sqli-labs系列第四十一关(基于堆叠注入的盲注)和四十二关四十三关四十四关四十五关
0x1普通测试方式 (1)输入and1=1和and1=2测试,返回错误,证明存在注入 (2)union select联合查询 (3)查询表名 (4)其他 payload: ,( ,( 0x2 堆叠注入 ...
- “全栈2019”Java第四十四章:继承
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- 孤荷凌寒自学python第四十四天Python操作 数据库之准备工作
孤荷凌寒自学python第四十四天Python操作数据库之准备工作 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天非常激动地开始接触Python的数据库操作的学习了,数据库是系统化设计 ...
- Android项目实战(四十四):Zxing二维码切换横屏扫描
原文:Android项目实战(四十四):Zxing二维码切换横屏扫描 Demo链接 默认是竖屏扫描,但是当我们在清单文件中配置横屏显示的时候: <activity android:name=&q ...
随机推荐
- 十一、diff和patch打补丁
diff制作补丁文件的原理:告诉我们怎么修改第一个文件后能得到第二个文件. diff命令常用选项: -u 输出统一内容的头部信息(打补丁使用),计算机知道是哪个文件需要修改 -r 递归对比目录中 ...
- 面试常问的Java虚拟机内存模型,看这篇就够了!
一.虚拟机 同样的java代码在不同平台生成的机器码肯定是不一样的,因为不同的操作系统底层的硬件指令集是不同的. 同一个java代码在windows上生成的机器码可能是0101.......,在lin ...
- Redis 面霸篇:高频问题横扫核心知识点
「码哥字节」从高频面试问题跟大家一起横扫 Redis 核心知识点,从根本上理解 Redis ,不做八股文的工具人,做扭转乾坤的大神. 码哥到如今已经写了 9 篇 Redis 连载,后台有小伙伴也让我写 ...
- org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element(识别不到想要的元素) 想获取 ...
- JDK并发包一
JDK并发包一 同步控制是并发程序必不可少的重要手段,synchronized是一种最简单的控制方法.但JDK提供了更加强大的方法----重入锁 重入锁 重入锁使用java.util.concurre ...
- 解决git同步每次都需要输入用户名、密码
打开 git bash 执行命令: git config --global credential.helper store
- Algorithm:Java加密解密之MAC(消息认证码)
MD5 消息摘要(数字摘要) 它是把一个文本/文件 通过摘要函数(hash函数)计算出一个结果.然后把文本/文件和摘要结果一同发给接受者接受者接收到文件之后,也进行摘要,把两个摘要结果进行对比.如果一 ...
- WebService:java配置类形式发布WebService接口及遇见的问题总结
配置WebService前需要以下依赖jar包 #版本只供参考,具体看项目 <dependency> <grouId>org.apache.cxf</grouId> ...
- 学习/etc/group /etc/passwd 和 /etc/shadow
/etc/passwd 管理用户信息的系统文件 /etc/shadow 管理用户密码信息的系统文件 /etc/group 管理用户组信息的系统文件 1./etc/group 将用户分组是Linux系统 ...
- Java实验项目六——使用DAO模式实现对职工表的操作
Program: 利用JDBC访问职工信息表,实现对职工信息的添加.更新.删除.按照职工号查找.查找全部职工的功能. Description:在这里我采用了DAO设计模式完成对职工表的操作,下面介绍一 ...