深入浅出CChart 每日一课——快乐高四第五课 梦想的天空,锦上添花之客户区自绘篇

上节课笨笨给大家介绍了CChart的插件菜单功能,这属于定制功能,给了用户发挥的自由。本节课继续介绍CChart的定制功能,这节课的内容要实用得多,因为定制的是客户区。客户区自绘功能将给您插上理想的翅膀,飞上梦想的天空,呵呵。

完全的定制需要子类化功能,这个以后再介绍。本节课先介绍CChart提供的客户区自绘函数。

CChart类有以下两个成员函数。

 void		SetUserDrawingFunc(void	(*fcnUserDrawing)( void *plot, HDC hDC, RECT clientRect, RECT plotRect, void *pPara ), void *pPara);
void		SetUserDrawingFunc(void	(*fcnUserDrawing)( void *plot, HDC hDC, RECT clientRect, RECT plotRect, void *pPara ), void *pPara, int nPlotIndex);

 

先看参数,两个指针,fcnUserDrawing就是用户自绘函数的指针,pPara是需要传入用户自绘函数的参数。

这两个函数的差别仅仅在于后一个用于子图,很好理解。

用户自绘函数到底是什么样的呢?嗯,就这样写就可以了。

void	MyDraw(void *plot, HDC hDC, RECT clientRect, RECT plotRect, void *pPara );

这里有五个参数,其中前四个参数是CChart内部定义好了的,只管用,后一个参数就是前面SetUserDrawingFunc传入的pPara指针。

第一个参数plot指针是保留参数,可以先忽略不管;hDC就是客户区的DC句柄;clientRect表示整个客户区;plotRect表示客户区中用于绘制数据的区域,也就是除去标题区域和上下左右四个坐标轴区域以后剩下那个矩形区。很好理解吧!不用费工夫计算中间那块区域的坐标了,笨笨已经提前准备好。

其实讲到这里,熟悉CChart的同学应该已经学会使用客户区自绘功能,同学们仿照上一课的思路立马就搞定了。因为CChart所有功能的套路都是差不多的,都属于天下武林的新兴门派——笨笨派,笨笨派的特点是内外兼修,以内功为体,外功为用。内功专修Win32API,内力强劲,掌风拂过之处,C#、Delphi无一不纷纷败下阵来。本节课的内容还属于C++,那还不是探囊取物?

下面还是举一个实例吧。这个例子是一位朋友的上位机显示需求,我修改了一下发出来供大家参考。

 

第一步,按照第一课的方法建立一个工程,名为LessonA05,具体步骤不再详述。同时按第二课的介绍,激活鼠标双击功能。

其中WM_CREATE消息的响应例程如下。

 

 
case WM_CREATE:
			chartWnd.Attach(hWnd, kTypeXY);
			{
				int data1[]={0,1,1,0,1,0,1,0,1,1,1,0,0,1,1,1};
				int data2[]={1,0,0,0,1,0,1,1,1,0,1,1,0,1,1,0};
				int data3[]={0,1,0,0,1,1,1,0,0,1,1,0,1,1,0,0};

				int i;
				for(i=0; i<16; i++)
				{
					chartWnd.GetChart()->AddPoint2D((double)i, data1[i]+1, 0);
					chartWnd.GetChart()->AddPoint2D((double)i, data2[i]+3, 1);
					chartWnd.GetChart()->AddPoint2D((double)i, data3[i]+5, 2);
				}
				chartWnd.GetChart()->SetPlotType(2, 0);
				chartWnd.GetChart()->SetPlotType(2, 1);
				chartWnd.GetChart()->SetPlotType(2, 2);
			}
			chartWnd.GetChart()->SetAxisLabelShow(false, 0);
			chartWnd.GetChart()->SetTitle(_T("多通道二进制数据上位机显示"));
			break;
 


上面有一句代码以前没有介绍过,那就是SetPlotType。这个函数的定义如下。

 
void		SetPlotType(int nType, int nDataIndex, int nPlotIndex=0);
 

其中第一个参数表示曲线的类型,共有六种类型,参见Chart.h头部的说明。这里简述如下:0散点图;1 连线图;2 台阶图先水平再竖直;3台阶图先竖直再水平;4 台阶图水平竖直水平;5 台阶图竖直水平竖直;6贝塞尔连线图。

这里为了显示二进制的效果,设置为2,即台阶图,先画水平线再画竖直线。

图像显示效果如下。

第二步,编写客户区自绘函数。

 

 
void	MyDraw( void *plot, HDC hDC, RECT clientRect, RECT plotRect, void *pPara )
{
	TCHAR str[32];
	SIZE textSize;
	RECT textRect;

	int step;
	step = (plotRect.bottom - plotRect.top)/7;

	LOGFONT lf; 
	memset(&lf,0,sizeof(LOGFONT)); 
	lf.lfHeight = -24; 
	lf.lfWeight = FW_NORMAL; 
	lf.lfClipPrecision = CLIP_LH_ANGLES; 
	strcpy(lf.lfFaceName, "宋体"); 
	HFONT hfont = CreateFontIndirect(&lf);
	HFONT hOldFont = (HFONT)SelectObject(hDC, hfont);

	_tcscpy(str, _T("第一通道数据"));
	GetTextExtentPoint32(hDC, str, _tcslen(str), &textSize );
	textRect.left = plotRect.left + 10;
	textRect.right = textRect.left + textSize.cx;
	textRect.bottom = plotRect.bottom - step * 1.5;
	textRect.top = textRect.bottom - textSize.cy;
	DrawText(hDC, str, _tcslen(str), &textRect, DT_CENTER);

	_tcscpy(str, _T("第二通道数据"));
	GetTextExtentPoint32(hDC, str, _tcslen(str), &textSize );
	textRect.left = plotRect.left + 10;
	textRect.right = textRect.left + textSize.cx;
	textRect.bottom = plotRect.bottom - step * 3.5;
	textRect.top = textRect.bottom - textSize.cy;
	DrawText(hDC, str, _tcslen(str), &textRect, DT_CENTER);

	_tcscpy(str, _T("第三通道数据"));
	GetTextExtentPoint32(hDC, str, _tcslen(str), &textSize );
	textRect.left = plotRect.left + 10;
	textRect.right = textRect.left + textSize.cx;
	textRect.bottom = plotRect.bottom - step * 5.5;
	textRect.top = textRect.bottom - textSize.cy;
	DrawText(hDC, str, _tcslen(str), &textRect, DT_CENTER);

	SelectObject(hDC, hOldFont);
	DeleteObject(hfont);
}
 

第三步,将客户区自绘函数插入到CChart的绘图动作序列中。

在WM_CREATE的响应例程中插入下面一行代码。

 

 
chartWnd.GetChart()->SetUserDrawingFunc(MyDraw, 0);
 


好了,现在该下班了。下班之前,先看看效果吧。

 

 

看到了吧,左边三行文字是我们自绘处理的哟。这里笨笨只是简单地写了几行字,同学们可以进行任何绘图操作。

梦想的天空,自由的舞台,欧耶!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值