前言

目的:使用控制台程序带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绘制动态曲线的更多相关文章

  1. C++第四十五篇 -- MFC关闭调用的窗口

    调用窗体的方法: // chart是一个MFC的窗体类 chart *chartdialog = new chart; //调用窗体,获取返回值 int ReturnValue = chartdial ...

  2. 第四十四个知识点:在ECC密码学方案中,描述一些基本的防御方法

    第四十四个知识点:在ECC密码学方案中,描述一些基本的防御方法 原文地址:http://bristolcrypto.blogspot.com/2015/08/52-things-number-44-d ...

  3. NeHe OpenGL教程 第四十四课:3D光晕

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  4. 网站开发进阶(四十四)input type="submit" 和"button"的区别

    网站开发进阶(四十四)input type="submit" 和"button"的区别   在一个页面上画一个按钮,有四种办法: 这就是一个按钮.如果你不写ja ...

  5. Gradle 1.12用户指南翻译——第四十四章. 分发插件

    本文由CSDN博客貌似掉线翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  6. SQL注入之Sqli-labs系列第四十一关(基于堆叠注入的盲注)和四十二关四十三关四十四关四十五关

    0x1普通测试方式 (1)输入and1=1和and1=2测试,返回错误,证明存在注入 (2)union select联合查询 (3)查询表名 (4)其他 payload: ,( ,( 0x2 堆叠注入 ...

  7. “全栈2019”Java第四十四章:继承

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  8. 孤荷凌寒自学python第四十四天Python操作 数据库之准备工作

     孤荷凌寒自学python第四十四天Python操作数据库之准备工作 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天非常激动地开始接触Python的数据库操作的学习了,数据库是系统化设计 ...

  9. Android项目实战(四十四):Zxing二维码切换横屏扫描

    原文:Android项目实战(四十四):Zxing二维码切换横屏扫描 Demo链接 默认是竖屏扫描,但是当我们在清单文件中配置横屏显示的时候: <activity android:name=&q ...

随机推荐

  1. 技能篇:shell教程及脚本编写

    前言 我们常时不会见到shell脚本,但是需要阅读开发linux脚本时,这又是一项必不可少的技能.本文在于提供基础的shell编程语法和简单的实例,帮助同学快速开发,可当做shell手册使用也非常善 ...

  2. 【NX二次开发】Block UI 指定轴

    属性说明 属性   类型   描述   常规           BlockID    String    控件ID    Enable    Logical    是否可操作    Group    ...

  3. HTTP请求方法及响应状态码详解

    HTTP请求方法和响应状态详解 HTTP请求方法 HTTP1.0/1.1支持的所有请求方法如下所示: GET 用来请求访问已被URI识别的资源.指定的资源经服务器解析后返回响应内容. POST POS ...

  4. Huawei USG6530防火墙

    CF卡:(Compact Flash)最初是一种用于便携式电子设备的数据存储设备.作为一种存储设备,它革命性的使用了闪存 与sd卡的区别:SD卡的优点是安全.体积小巧,价格较之CF卡相对比较低,适合用 ...

  5. SpringBoot实战:10分钟快速搞定环境

    什么是 springboot Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程. 该框架使用了特定的方式来进行配置,从而使开发人 ...

  6. js(if else)分数等级查询

    <!DOCTYPE html><html><head><meta charset="utf-8"><title>文档标题 ...

  7. Kubernetes自动伸缩pod-HPA

    在运维中,虽然能预先知道负载何时会飙升,或者如果负载的变化是较长时间内逐渐发生的,手动扩容也是可以接受的,但指望靠人工干预来处理突发而不可预测的流量增长,仍然不够理想. 幸运的是,Kubernetes ...

  8. 温故知新Docker概念及Docker Desktop For Windows v3.1.0安装

    Docker 简介 什么是Docker? Docker是一个开放源代码软件项目,项目主要代码在2013年开源于GitHub.它是云服务技术上的一次创新,让应用程序布署在软件容器下的工作可以自动化进行, ...

  9. hdu 6034 贪心模拟 好坑

    关键在排序!!! 数组间的排序会超时,所以需要把一个数组映射成一个数字,就可以了 #include <bits/stdc++.h> using namespace std; typedef ...

  10. POJ 1681 高斯消元 枚举自由变元

    题目和poj1222差不多,但是解法有一定区别,1222只要求出任意一解,而本题需要求出最少翻转次数.所以需要枚举自由变元,变元数量为n,则枚举的次数为1<<n次 #include < ...