您好,欢迎来到九壹网。
搜索
您的当前位置:首页C++第四十四篇--MFC使用ChartCtrl绘制动态曲线

C++第四十四篇--MFC使用ChartCtrl绘制动态曲线

来源:九壹网
C++第四⼗四篇--MFC使⽤ChartCtrl绘制动态曲线

前⾔

⽬的:使⽤控制台程序带MFC类库画⼀个动态曲线图参考链接:

操作步骤

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(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; }}

View Code 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);};

View Code

4. 控制台调⽤动态折线图

chart *chartdialog = new chart;

int ReturnValue = chartdialog->DoModal(); // Show the dialogprintf(\"%d\", ReturnValue);

View Code

效果图

可能出现的问题

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 objectCWinApp 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;}

View Code OK.

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- 91gzw.com 版权所有 湘ICP备2023023988号-2

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务