深入浅出CChart 每日一课——快乐高四第四课 冰山上的来客,锦上添花之插件菜单篇

CChart的交互功能很强,笨笨一向引为自豪。交互功能的一个重要组成部分就是右键菜单。

同学们试一试就能知道,CChart的右键菜单功能是非常丰富的。尤其是还有很多功能在包装类中暂时还没有,只能在右键菜单或对话框中使用。

虽然默认的右键菜单功能已经令笨笨自己满意了,但不见得能让所有的人满意。怎么办呢?那就需要用户自己定制。

定制的方法有两种。

一种方法是革命性的的,那就是把默认的菜单全部替换掉。这个想法非常非常好,但是看起来好像不那么容易,是不是要改源码呀?Oh,NO。完全不需要,笨笨已经贴心地为大家提供了子类化功能。子类化不仅可以修改右键菜单,也可以改变默认的消息响应,甚至显示的图像也可以完全按要求定制。关于子类化功能,以后会专门介绍。

另一种方法那就是康有为、梁启超的办法,改良,君主立宪,不修改默认菜单,而是往菜单里面添加新的菜单项。这个看起来似乎更难了,真的是这样吗?

(注:CChart4.8.0.3版本已经增加了一个接口函数,不用子类化也可以完全替换右键菜单,见本节课后续内容。)

下面笨笨就给大家介绍第二种方法,在右键菜单中增添插件菜单。

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

第二步,定义一个菜单的标识ID。

既然是菜单,就必然有ID。

在WndProc函数的上面定义菜单ID,代码如下。

 
const int menuID = 40000;
 

这里定义的ID比较大,是为了避免和CChart默认菜单的ID冲突。一般大于32768即可,当然不能大于65535。

第三步,编写建立插件菜单项的函数。

 
void	AddPluginMenu( void *plot, HMENU addMenu )
{
	AppendMenu(addMenu, MF_SEPARATOR, 0, (LPCTSTR)0 );
	AppendMenu(addMenu, MF_STRING, menuID, _TEXT("附加菜单项1"));
	
	HMENU  subMenu = CreatePopupMenu();
	AppendMenu(subMenu, MF_STRING, menuID+1, _TEXT("附加菜单项2"));		
	AppendMenu(addMenu, MF_POPUP, (UINT) subMenu, _TEXT("附加弹出项"));
	DestroyMenu(subMenu);
}
 

注意函数的形式,包括参数和返回值必须和上面一模一样,否则程序崩溃莫得商量。

可以看见,上面的代码实际增加了两个菜单项,ID分别是menuID和menuID+1,名字分别为“附加菜单项1”和“附加菜单项2”,其中第二个菜单项是放在一个弹出菜单“附加弹出项”中的。

这一套完全是Win32API的玩法,CChart内部所有的右键菜单都是这么做出来的。

第四步,建立菜单项的处理函数。

 
int		IntPluginMenu( void *plot, HWND hWnd, int result )
{
	CChart *pChart = (CChart *)plot;
	if(result == menuID)
	{
		const TCHAR *title = pChart->GetTitle();
		TCHAR str[128];
		_stprintf(str, _T("图像标题为:%s"), title);
		MessageBox(hWnd, str, _T("附加菜单"), MB_OK);
		return -3;
	}
	else if(result == menuID + 1)
	{
		static int count = 4;
		pChart->AddPoint2D((double)count, (double)count*count);
		count++;
		return -3;
	}
	return -2;
}
 

(注:CChart 4.8.0.3以前的版本,由于一个小Bug,GetTitle函数总是返回空字符串,上述代码工作不正常。目前已修订。)

注意上面的代码中,把一个void*指针转换成了我们需要的CChart*指针,有了这个CChart*指针,我们想干啥就可以干啥了,上面第一个菜单项获取了图像标题并显示在消息框里,第二个菜单项在屏幕的曲线上增加一个数据点。真的是很方便呀。

那么,这个指针是从哪里来的呢?别慌,答案在第五步。

还有这里返回值的含义,-3表示更新视图,-2表示不动作,-1表示出错。

由于使用了sprintf,需要在LessonA04.cpp的头部附近增加一行。

 
#include <stdio.h>
 


第五步,在WM_CREATE的处理例程中增加一行。

 
chartWnd.GetChart()->SetPluginMenu(AddPluginMenu, IntPluginMenu, chartWnd.GetChart());
 

注意了,SetPluginMenu有三个参数,前两个参数就是前两步编写的那两个函数,分别建立菜单和处理菜单。特别要注意第三个参数了。看到了吧,这里传进去就是一个CChart*指针。

大家要小心,如果那两个函数定义的方式(包括返回值和形参)不对,或者第三个参数传递不匹配,程序崩溃无商量。

OK,大功告成。

为了确认大家的代码和笨笨的一样,请检查WM_CREATE处理例程是不是下面这样的。

 
case WM_CREATE:
			chartWnd.Attach(hWnd, kTypeXY);

			chartWnd.GetChart()->SetPluginMenu(AddPluginMenu, IntPluginMenu, chartWnd.GetChart());
			
			chartWnd.GetChart()->AddPoint2D(-3.0, 9.0);
			chartWnd.GetChart()->AddPoint2D(-2.0, 4.0);
			chartWnd.GetChart()->AddPoint2D(-1.0, 1.0);
			chartWnd.GetChart()->AddPoint2D(0.0, 0.0);
			chartWnd.GetChart()->AddPoint2D(1.0, 1.0);
			chartWnd.GetChart()->AddPoint2D(2.0, 4.0);
			chartWnd.GetChart()->AddPoint2D(3.0, 9.0);
			
			chartWnd.GetChart()->SetTitle(_T("Hello World,我的第一个CChart程序!"));
			break;
 

这段代码主要就是从第一课拷贝过来的,呵呵。

下面看看劳动成果。

大家可以看看两个新菜单项的功能是不是如我们所愿。如果有所差别,肯定是上面的代码写得不一样了,呵呵。

如果我们只想显示新菜单,不想显示默认的菜单项,也就是完全替换右键菜单,可以实现吗?

完全可以!新版CChart贴心地提供了一个简单的接口。

在上面的代码中,SetPluginMenu的附近,增加下面一行:

        chartWnd.GetChart()->SetPluginMenuOnly(true);

这时结果如下:

可以看到,现在右键菜单只有我们添加的项了。

本节课笨笨给大家介绍了CChart的插件菜单功能,这个功能可能不见得能有多实用,但可以展示CChart的强大内核。

下一课笨笨将介绍一个非常实用的功能——客户区自绘,改变CChart的默认显示状态。这个功能应该在非常多的场合都能用到,敬请期待。

提请注意,请到www.cchart.net网站下载最新版本的CChart。旧版本不保证能实现本节课的功能。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值