有好些朋友给我反映,就是一个窗体中加入好几个CChartWnd之后。工作不正常。这个的确是这样,CChartWnd会接管原来窗体的消息循环,加入多个CChartWnd之后,就相当于出租房转手好几道,消息循环乱套了。尽管道理上能够给二房东立规矩。但笨笨尚未想到一个万全之策,所以在眼下的状况下。请大家不要在一个窗体上Attach多个CChartWnd。

(笨笨注:上述描写叙述已经是老黄历了,新版本号的CChart已经实现了在一个窗体上多次Attach。只是这里的方法仍然很具有參考价值。

可是不是就不能在一个窗体的多个区域同一时候画图呢?非也非也。请不要忘了,CChartWnd的基础是CChart类,往往越是原始的东西功能就越强大。

以下笨笨就给大家简单示范一下利用CChart在单窗体的多个区域画图。计划分三种情况,即普通窗体,对话框窗体,duilib窗体。供大伙參考。

本课先介绍在普通窗体下分区域画图。

笨笨已经提供了一种分裂视图。实际就是一种分区域画图的方式。

但眼下分裂视图的各个子视图的类型是一样的。假设想在一个子视图画曲线图。还有一个子视图画饼图,笨笨仅仅能说抱歉了。

本课介绍的分区域画图能够克服这个缺点。

笨笨新近在CChart中添加了一种画图类型,就是等高线图和云图的合体版,顺便在本课一起介绍了。

本课的演示样例代码将在一个MFC窗体中分两块区域画图,一块绘制饼图,一块绘制等高线云图。

如今開始。

仍然以实例的形式。

第一步。打开VC。建立一个基于MFC AppWizard(exe)向导的项目LessonA06,向导中不做不论什么更改,直接点Finish。

第二步。拷贝库文件到LessonA06目录。

第三步,在VC中打开LessonA06View.h文件。在其头部加入例如以下代码。

#include "Chart.h"
#ifdef _DEBUG
# if defined(_UNICODE) || defined(UNICODE)
# pragma comment(lib, "PlotDll_ud.lib")
# else
# pragma comment(lib, "PlotDll_d.lib")
# endif
#else
# if defined(_UNICODE) || defined(UNICODE)
# pragma comment(lib, "PlotDll_u.lib")
# else
# pragma comment(lib, "PlotDll.lib")
# endif
#endif

第四步,在LessonA06View.h文件里,给CLessonA06View类加入两个CChart变量。

CChart m_Chart1, m_Chart2;

第五步,利用ClassWizard给CLessonA06View类加入OnCreate消息处理函数。并改动OnCreate函数例如以下。

int CLessonA06View::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1; // TODO: Add your specialized creation code here
m_Chart1.SetType(kTypePie);
m_Chart1.AddPie(4, "王菲");
m_Chart1.AddPie(3, "张柏芝");
m_Chart1.AddPie(2, "Irene"); m_Chart2.SetType(kTypeContour);
m_Chart2.SetContourByPoints();
m_Chart2.AddContourPoint(-1, -1, 5);
m_Chart2.AddContourPoint(-1, 1, 5);
m_Chart2.AddContourPoint(1, -1, 5);
m_Chart2.AddContourPoint(1, 1, 5);
m_Chart2.AddContourPoint(-1, 0, -5);
m_Chart2.AddContourPoint(0, -1, -5);
m_Chart2.AddContourPoint(1, 0, -5);
m_Chart2.AddContourPoint(0, 1, -5);
m_Chart2.AddContourPoint(0, 0, 10);
m_Chart2.SetPlotRange(-1.5, 1.5, -1.5, 1.5);
m_Chart2.SetContourPrecision(8);
m_Chart2.SetContourLineNum(20);
m_Chart2.SetUseLegend(false); return 0;
}

这里请大家注意等高线云图的使用方法。

首先。它的代码是kTypeContour。

其次,画等高线云图和等高线图、云图一样,须要一个原型为double f(double x, double y);的场函数。

因为好几位朋友问到,他们仅仅有数据点,能不能画等高线图。一直在道理上都是能够的,就是须要编写一个场函数,在场函数里面用数据点插值即可。但这个可能比較麻烦。近期笨笨在CChart中内置了插值函数。採用双线性的方式插值。精度可能没有二次以上的方式的高,但够用即可吧。

注意到这一行了吗。

m_Chart2.SetContourByPoints();

这就是表示等高线採用笨笨内置的插值函数绘制,不须要再提供场函数。但须要提供数据点。提供数据点的函数例如以下。

void	CChart::AddContourPoint(double x, double y, double h);

当中x,y就是坐标,h是高度。

以下这个函数表示等高线的绘制范围。

void	CChart::SetPlotRange(double xl, double xu, double yl, double yu);

以下这个函数表示等高线的绘制精度,在曾经的课程中已经介绍了。

void	CChart:: SetContourPrecision (int precision);

以下这个函数表示等高线的绘制时的高度数,在曾经的课程中也已经出现了。

void	CChart::SetContourLineNum(int num);

等高线的新功能介绍就结束了。

第六步,重载OnSize函数例如以下。

void CLessonA06View::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy); // TODO: Add your message handler code here
CRect rect;
GetClientRect(&rect);
CRect rt1, rt2;
rt1 = rect;
rt1.right = (rect.left + rect.right)/2;
m_Chart1.SetConfineRect(rt1);
rt2 = rect;
rt2.left = (rect.left + rect.right)/2;
m_Chart2.SetConfineRect(rt2);
}

这里就是分配各个视图所占的窗体区域。在本例中。m_Chart1占领窗体的左半。m_Chart2占领窗体的右半。

主要须要利用到这个函数。

void CChart::SetConfineRect(RECT rect);

第七步。改动OnDraw例如以下。

void CLessonA06View::OnDraw(CDC* pDC)
{
CLessonA06Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
m_Chart1.OnDraw(pDC->m_hDC);
m_Chart2.OnDraw(pDC->m_hDC);
}

如今能够执行了,效果例如以下。

刚启动的时候可能有点慢。由于须要初始化等高线。

有同学要问了,鼠标没有反应呀?我们这里没有採用CChartWnd,所以须要自己处理消息。

第八步,重载OnLButtonDown,OnLButtonUp,OnLButtonDblClk。OnMouseMove,OnContextMenu,OnEraseBkgnd这几个函数,并改动例如以下。

void CLessonA06View::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_Chart1.OnLButtonDownR(m_hWnd, point, nFlags);
m_Chart2.OnLButtonDownR(m_hWnd, point, nFlags);
} void CLessonA06View::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_Chart1.OnLButtonUpR(m_hWnd, point, nFlags);
m_Chart2.OnLButtonUpR(m_hWnd, point, nFlags);
} void CLessonA06View::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_Chart1.OnLButtonDblClkR(m_hWnd, point, nFlags);
m_Chart2.OnLButtonDblClkR(m_hWnd, point, nFlags);
} void CLessonA06View::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_Chart1.OnMouseMoveR(m_hWnd, point, nFlags);
m_Chart2.OnMouseMoveR(m_hWnd, point, nFlags);
} void CLessonA06View::OnContextMenu(CWnd* pWnd, CPoint point)
{
// TODO: Add your message handler code here
m_Chart1.OnContextMenuR(NULL, m_hWnd, point);
m_Chart2.OnContextMenuR(NULL, m_hWnd, point);
} BOOL CLessonA06View::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
return TRUE;
//return CView::OnEraseBkgnd(pDC);
}

消息响应回来了。!

大家能够比較一下这里和第15课里面消息响应代码的异同。

实际上。就是在各个消息的响应代码里面,把每一个CChart对象都处理一遍就能够了。

好了,如今下课喽。

深入浅出CChart 每日一课——快乐高四第六课 二丫的青梅,返璞归真之普通窗体多区域画图的更多相关文章

  1. 深入浅出CChart 每日一课——快乐高四第九课 于无声处,CChart内置功能介绍之数据存取篇

    笨笨长期以来一直使用Origin软件画图和处理数据,但Origin软件没有编程语言的接口.笨笨开发CChart的一个潜在的目标.是想实现Origin软件的功能.当然这是一个不可能达到的目标.Origi ...

  2. NeHe OpenGL教程 第四十六课:全屏反走样

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

  3. 深入浅出CChart 每日一课——第十六课 实习之旅,百年老店之新锐WTL

    上节课笨笨给大家介绍了CChart在微软MFC框架下的应用,本节课的内容仍然和百年老店微软相关,只不过主角换成WTL了. 不了解WTL的同学可以先找度娘温习一下.度娘在怀,今生何求.郎君啊,你是不是闷 ...

  4. 深入浅出CChart 每日一课——第十八课 女神的套娃,玩转对话框

    前面笨笨已经给大家展示了CChart编程的N个例子.这些例子中,我们的CChart图像都是绘制在程序的主窗口中的. 在很多情况下,我们面对的情形不是这样的.这节课笨笨就给大家介绍一下怎样在对话框中用C ...

  5. 第四十六课:MVC和MVVM的开发区别

    实现MVC的目的就是为了让M和V相分离.前端的MVC无法做到View和Model的相分离,而MVVM可以. 我们先来看一个用MVC模式开发的经典例子:(一定要深入了解这种开发的思想,而不是看懂代码) ...

  6. 潭州课堂25班:Ph201805201 django 项目 第四十六课 查错 补缺 (课堂笔记

    从讲项目开始,查找错误,完善笔记,尽可能 翻译没一句代码(以后台为主), 本项目亮点,也是重点 Django ORM中对数据查询的优化(only.defer.select_related) redis ...

  7. python第四十六课——函数重写

    3.函数重写(override) 前提:必须有继承性 原因: 父类中的功能(函数),子类需要用,但是父类中函数的函数体内容和我现在要执行的逻辑还不相符 那么可以将函数名保留(功能还是此功能),但是将函 ...

  8. JAVA学习第四十六课 — 其它对象API(二)Date类 & Calendar类(重点掌握)

    Date类(重点) 开发时,会时常遇见时间显示的情况,所以必须熟练Date的应用 <span style="font-family:KaiTi_GB2312;font-size:18p ...

  9. NeHe OpenGL教程 第四十二课:多重视口

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

随机推荐

  1. JavaScript的数组详解

    #转载请留言联系 创建数组 1.通过new Array()进行创建 var arr1=new Array(); 2.通过中括号进行创建 var arr2=[]; 计算数组的长度 var arr3=[' ...

  2. python多线程实现多任务

    #转载请联系 1.什么是线程? 进程是操作系统分配程序执行资源的单位,而线程是进程的一个实体,是CPU调度和分配的单位.一个进程肯定有一个主线程,我们可以在一个进程里创建多个线程来实现多任务. --- ...

  3. KVM(三)I/O 全虚拟化和准虚拟化

    在 QEMU/KVM 中,客户机可以使用的设备大致可分为三类: 1. 模拟设备:完全由 QEMU 纯软件模拟的设备. 2. Virtio 设备:实现 VIRTIO API 的半虚拟化设备. 3. PC ...

  4. 转载 Ofbiz 入门教程

    1.Ofbiz 介绍: Ofbiz(http://www.ofbiz.org) 是 Open Source 的商务软件系统,充分利用了各优秀的的Open Source 项目,像 Tomcat, Ant ...

  5. 从dao层查出的数据到页面时数值都是零的异常

    异常问题: IllegalArgumentException: argument type mismatch at cn.tedu.utils.BeanListHandler.handle(BeanL ...

  6. 通过Cookie来记住用户名出现乱码问题(URL编码)

    在登录时,提交一个中文名的用户名到服务器并返回到客户端的Cookie中时, 这个过程会后台会报 java.lang.IllegalArgumentException (非法数据异常) -->在给 ...

  7. flutter演示项目:游侠客户端

    使用flutter实现的游侠客户端. 还有一些页面没写,最主要的问题是无法解析html富文本. https://github.com/axel10/flutter_ali213_client_demo

  8. 洛谷——P1495 曹冲养猪

    题目描述 自从曹冲搞定了大象以后,曹操就开始捉摸让儿子干些事业,于是派他到中原养猪场养猪,可是曹冲满不高兴,于是在工作中马马虎虎,有一次曹操想知道母猪的数量,于是曹冲想狠狠耍曹操一把.举个例子,假如有 ...

  9. [Codeforces 15E] Triangle

    Brief Introduction: 求从N出发,回到N且不包含任何黑色三角的路径数 Algorithm:假设从N点到第二层中间的节点M的路径数为k,易知总路径数为(k*k+1)*2 而从第第四层开 ...

  10. SD 一轮集训 day1 carcar

    可以发现每条边只能选一次或者两次,并且最后每个点的度数(∑邻接边选的次数和)都是偶数(代表有欧拉回路). 然后根据题意列一个 n 行 m+1 列的01矩阵,每一行代表一个异或方程组(每个点的度数是偶数 ...