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

有好些朋友给我反映,就是一个窗体中加入好几个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对象都处理一遍就能够了。

好了,如今下课喽。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值