前言

目的:使用控制台程序带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. 【NX二次开发】指定矢量控件,记住上次选择的方向

    block UI控件如果有RetainValue属性,就用这个属性.没有这个属性可以参考下面这种方法.以矢量控件为例: 1.在apply_cb回调中,将控件值保存到文本中 double TopForT ...

  2. Redis与DB的数据一致性解决方案(史上最全)

    文章很长,而且持续更新,建议收藏起来,慢慢读! 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 + 社群大片好评 < Java 高并发 三 ...

  3. 【dp】状压dp

    二进制的力量 状态压缩DP 愤怒的小鸟 第一次接触状态压缩DP是在NOIP2016的愤怒的小鸟,当时菜得连题目都没看懂,不过现在回过头来看还是挺简单的,那么我们再来看看这道题吧. 题意&数据范 ...

  4. 性能工具之linux三剑客awk、grep、sed详解

    前言 linux 有很多工具可以做文本处理,例如:sort, cut, split, join, paste, comm, uniq, column, rev, tac, tr, nl, pr, he ...

  5. 精尽Spring Boot源码分析 - Jar 包的启动实现

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  6. Spring官方发布新成员:Spring GraphQL

    近日,在GraphQL Java诞生6周年的时候,Spring社区通过博客宣布正式创建全新项目:Spring GraphQL,同时还发布了这个新项目的里程碑1.0版本. 博客原文:https://sp ...

  7. Flyway:Spring Boot中使用Flyway来管理数据库版本

    Flyway简介 Flyway是一个简单开源数据库版本控制器(约定大于配置),主要提供migrate.clean.info.validate.baseline.repair等命令.它支持SQL(PL/ ...

  8. spring boot j集成seagger 加入拦截器后 swagger 不能访问

    一开始我是这样排除拦截的,但是发现没用 后来我发现swagger的真实访问路径是这样的 转自: https://blog.csdn.net/ab1991823/article/details/7906 ...

  9. shell中的特殊变量IFS

    shell中特殊变量IFS的使用 IFS是内部字段分隔符(internal field separator).默认情况下,bash shell会将空格.制表符.换行符 当做字段分隔符. IFS=$'\ ...

  10. Python中的json学习

    p.p1 { margin: 0; font: 14px ".PingFang SC"; color: rgba(53, 53, 53, 1) } p.p2 { margin: 0 ...