2023年11月30日发(作者:)
b
n
c
.
w
w
Visual C++的ActiveX控件
w
t
e
n
.
t
k
e
o
n
o
.
b
k
n
o
c
.
w
w
w
t
e
n
.
t
k
e
o
n
o
.
b
k
n
o
c
o
.
b
w
n
w
c
w
.
t
e
n
.
t
k
e
o
n
o
.
b
k
n
o
c
o
.
b
w
n
w
c
w
.
w
w
w
t
k
e
o
n
o
.
b
k
n
o
c
o
.
b
w
n
w
c
w
.
w
w
w
t
e
n
.
k
o
c
o
.
b
w
n
w
c
w
.
w
w
w
t
e
n
.
k
o
o
内容提要:本文详细介绍了ActiveX控件的基本概念和ActiveX控件的创建方法,同时介绍了
ActiveX控件的属性、方法和事件的添加和使用方法。通过本文的学习,读者应了解ActiveX控件
的原理;能够用Visual C++创建ActiveX控件;会使用ActiveX控件;会向ActiveX控件添加属性、
方法和事件。
关键字:ActiveX控件、OLE、ActiveX自动化
引言:ActiveX是Microsoft公司的一项注册技术,它使用COM实现Windows程序之间的通信。
ActiveX封装包括了OLE、Internet和多媒体在内的各种技术,是Internet/Intranet的一个开放式平台。
ActiveX控件是OLE控件的升级版,大大简化了用户的操作,用户可以像使用Windows标准控件那
样使用它。ActiveX控件可以插入到Web页或者ActiveX包容器中。
正文:
k
o
o
1 ActiveX控件介绍
ActiveX控件是为Windows编写的可重复使用的定制控件,它是作为进程中的服务器而实现的。
本节将介绍ActiveX控件的相关知识。
1.1 ActiveX控件的相关技术
与ActiveX控件相关的技术有OLE、容器与服务器、ActiveX自动化等,下面分别加以介绍。
1. OLE介绍
OLE(Object Linking and Embedding,对象的嵌入与链接)是以COM为基础的。COM(Component
Object Model,组件对象模型)是OLE的基础。COM是一种能够使软部件作为对象进行相互作用的
二进制标准。COM不是一种编程语言,但可以为支持COM对象二进制形式的语言一起工作。可以
认为,COM提供了二进制对象的规范。
OLE使应用程序能够通过数据链接或嵌入的方式共享数据。当数据集合被链接到文档中,文档
将与此数据集合作为文档的一部分,并保持其与文档的链接。数据集合仍然作为一个分离对象保存
在自己的文件内,可以使用指针用其编辑程序单独打开。修改对象后,文档也发生相应的变化。如
果数据被嵌入文档,文档将不保留与最初含有此数据集合的文件的链接关系。也就是文档不会随数
据集合的原文件的修改而修改。无论是链接还是嵌入,都提供在文档中打开相应应用程序处理其中
特定数据集合的能力。
2. 容器与服务器
嵌入和链接的实现都需要容器和服务器(Container and Server)的支持。含有链接或嵌入数据
的应用程序称为容器应用程序,而为这些数据提供编辑功能的应用程序称为服务程序。
其中,服务器分为三种类型:小型服务器、全服务器和自动化服务器。小型服务器是指不能独
立运行,只能使用其包含到容器的服务器。全服务器是指可作为独立的应用程序运行,又可由容器
启动的服务器。自动化服务器是为自动化提供服务的程序。
3. ActiveX自动化
OLE自动化(ActiveX Automation)允许通过使用高级的宏语言或脚本语言(如JavaScript)在
一个应用程序的内部操作另一个应用程序的属性和方法。用于驱动的应用程序称为自动化客户
(Automation Client),而被驱动的应用程序称为自动化服务器(Automation Server)或自动化部件。
自动化客户是指使用OLE自动化提供服务的控制程序,它通过IDispatch接口工作。
自动化部件是一项由一个应用程序提供,而被另一个应用程序使用的服务,它是用对象描述语
言定义的。
对象描述语言所生成的文件扩展名为ODL,ODL文件经编译后存储到类型库(Type Library)
※ 1 ※
o
t
e
n
k
.
中,类型库是以TLB为扩展名的二进制文件。可以使用Visual C++中的OLE/COM Object Viewer实
用程序来读取类型库,并以图形形式来浏览自动化部件的信息,如常量、接口、方法和属性等(图
1)。
b
n
c
.
w
w
w
k
o
o
k
o
o
t
e
.
n
.
c
o
o
b
n
t
e
n
k
.
w
w
w
b
n
c
.
c
.
w
w
w
1.2 ActiveX控件的接口
ActiveX控件是OLE控件在Internet上的扩展。一个ActiveX控件必须支持IUnknown接口,而
且必须要注册,它是一个一般的COM对象。
ActiveX控件(ActiveX Controls)是运行中的小型自动化服务器,可以放入对话框、网页或者
任何容器应用程序。微软已经使用ActiveX控件取代了OLE控件。
ActiveX控件由两部分组成:控件本身,作为已经编译的库函数(实际是一个扩充的DLL);应
用程序的OLE载体,提供了嵌入式ActiveX控件之间的接口。ActiveX提供了三种接口类型:
(1)属性(Property):ActiveX控件内用于定义颜色、大小、范围和状态标志符等的数值。属
性可以是库存属性(Stock)或者自定义属性(Custom)。
(2)方法(Method):ActiveX控件内供容器程序外部调用的函数。ActiveX控件的方法包括库
存方法和自定义方法。
(3)事件(Event):ActiveX控件对诸如鼠标消息和键盘输入等消息的反映。ActiveX控件把
这些消息翻译成事件通知容器程序来产生相应的动作。ActiveX控件的事件包括库存事件和自定义
事件。
o
o
b
n
n
k
.
e
t
b
n
c
.
w
w
w
k
o
o
t
e
.
n
t
e
.
n
图1 OLE/COM Object Viewer实用程序
w
w
w
o
o
b
n
c
.
t
e
n
k
.
b
n
c
.
w
w
w
w
w
k
o
o
n
c
w
.
k
o
o
b
2 ActiveX控件的使用
本节用实例介绍ActiveX控件的使用,包括ActiveX控件属性的添加和修改、ActiveX控件方法
的添加和ActiveX事件的添加。
首先,利用ActiveX ControlWizard生成一个控件。然后为该控件添加标识控件内图形填充图案
的用户自定义属性和控件背景色标准属性。接着定制属性控制对话框来控制这两个属性。最后为控
件添加方法和事件。
w
w
c
.
w
o
o
b
n
e
n
k
.
t
※ 2 ※
o
o
e
n
k
.
t
w
w
c
w
.
2.1 使用ActiveX ControlWizard控件框架
使用ActiveX ControlWizard控件框架的方法如下:
(1)单击“文件”→“新建”,弹出“新建”对话框。切换到“工程”标签页,在对话框左侧
选择MFC ActiveX ControlWizard工程类型,在对话框右侧输入工程的名字,如ActiveXSample。输
入或者选择工程保存的位置。单击“确定”按钮新建一个ActiveX工程,如图2所示。
o
t
e
n
k
.
b
n
c
.
w
w
w
k
o
o
k
o
o
t
e
.
n
n
c
.
o
o
b
t
e
n
k
.
w
w
w
b
n
c
.
图2 新建控件工程
(2)在弹出的MFC ActiveX ControlWizard-Step 1 of 2对话框中,可以选择项目包含多少个控
件(最多99个);是否让项目文件中的控件有运行时的许可;是否产生上下文敏感的帮助文件(图
3)。在本例中,采用默认选项,单击“下一个”按钮。
c
.
w
w
w
o
o
b
n
n
k
.
e
t
b
n
c
.
w
w
w
k
o
o
t
e
.
n
t
e
.
n
图3 MFC ActiveX ControlWizard-Step 1 of 2对话框
(3)在MFC ActiveX ControlWizard-Step 2 of 2对话框中,采用默认选项,如图4所示,单击
“完成”按钮,向导将生成新项目代码。
w
w
w
o
o
b
n
c
.
t
e
n
k
.
b
n
c
.
w
w
w
k
o
o
图4 MFC ActiveX ControlWizard-Step 2 of 2对话框
MFC ActiveX ControlWizard的第(2)个步骤决定了控件如何与包容器进行交互(图3),下面
对步骤(3)的各个选项进行解释。
① Activates when visible(可见时激活)。
※ 3 ※
w
w
c
.
w
o
o
b
n
e
n
k
.
t
w
w
n
c
w
.
k
o
o
b
o
o
e
n
k
.
t
w
w
c
w
.
o
t
e
n
k
.
.
c
o
o
b
n
决定当控件可见时,包容器是否应自动激活它。对于ActiveX控件,通常需要立即激活。尽管
选中Activates when Visible选项,但它仅仅作为包容器应用程序的线索,它可能忽略申请。
② Invisible at runtime(在运行时不可见)。
如果选中了该选项,ControlWizard将不把OnDraw()函数添加到控件类中。可以为那些不需要
与用户进行交互的控件使用该选项。
③ Available in “Insert Object” dialog(在插入对象对话框中可用)。
这与从Test Container工具到Microsoft Offfice应用程序的许多应用程序提供的Insert Object对
话框(或等价物)相关。若没有选中该选项,将通知包容器,它不应该在包容器的Insert Object对
话框中包括这个新的控件。
④ Has an “About” box(有一个About框)。
ControlWizard将为About方法生成源程序代码,为常用About框生成资源。
⑤ Acts as a simple frame control(作为一个简单的框架控件)。
它为IsimpleFrame-Site接口提供支持。该选项将设置控件,来充当框架,用来包围包容器窗口
中其他ActiveX控件,将控件分组,并允许它们一起移动。并不是所有的包容器都支持简单的框架。
另外,单击“Edit Names”按钮可以对控件的名字进行修改,单击“Advanced”按钮可以对创
建ActiveX控件的高级选项进行设置。
b
n
c
.
w
w
w
k
o
o
k
o
o
t
e
.
n
t
e
n
k
.
w
w
w
b
n
c
.
2.2 分析ActiveX ControlWizard生成的代码
c
.
w
w
w
MFC ActiveX ControlWizard为ActiveXSample控件生成了三个类:CActiveXSampleApp、
CActiveXSampleCtrl和CActiveXSamplePropPage。
1. CActiveXSampleApp类
该类由COleControlModule类派生。
在该类的头文件中,声明了几个作为标识的外部变量。
const GUID CDECL _tlid;
const WORD _wVerMajor;
const WORD _wVerMinor;
并且,在该类的实现文件中,对这些外部变量进行了赋值。
const GUID CDECL BASED_CODE _tlid ={ 0xbe7ae7e5, 0xe87b, 0x4de4,
{ 0xac, 0x77, 0xb9, 0xa9, 0x64, 0xce, 0x50, 0xad } };
const WORD _wVerMajor = 1;
const WORD _wVerMinor = 0;
其中,_tlid是一个用于标识用户控件的全局的独特ID,_wVerMajor和_wVerMinor则提供了版
本的一些信息。
2. CActiveXSampleCtrl类
CActiveXSampleCtrl类是从COleControl类派生的。
CActiveXSampleCtrl类是控件类,值得注意的是该类的映射和OnDraw()函数。
CActiveXSampleCtrl类的映射一共有三种,分别是消息映射(Message Map)、分发映射(Dispatch
Map)和事件映射(Event Map)。一般情况下不提倡用户自己修改映射的入口,ClassWizard会处理
映射。
OnDraw()函数的程序代码如1所示。
【程序代码1】
void CActiveXSampleCtrl::OnDraw(CDC* pdc, const CRect& rcBounds,
const CRect& rcInvalid)
{
// TODO: Replace the following code with your own drawing code.
pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
o
o
b
n
n
k
.
e
t
b
n
c
.
w
w
w
k
o
o
t
e
.
n
w
w
w
o
o
b
n
c
.
t
e
n
k
.
b
n
c
.
w
w
w
w
w
k
o
o
t
e
.
n
n
c
w
.
k
o
o
b
w
w
c
.
w
o
o
b
n
e
n
k
.
t
※ 4 ※
o
o
e
n
k
.
t
w
w
c
w
.
o
t
e
n
k
.
pdc->Ellipse(rcBounds);
}
传给OnDraw()函数的参数有3个。pdc是指向设备环境对象的指针,rcBounds指定了控件边框
矩形,rcInvalid则指定了控件无效需要重绘的区域。
在ControlWizard生成的默认代码中,使用系统定义的白色画刷填充了整个控件区域,并沿着边
框矩形画了一个椭圆。
3. CActiveXSamplePropPage类
CActiveXSamplePropPage类是从COlePropertyPage类派生的。
CActiveXSamplePropPage类是属性页类,与对话框类相似。该类的构造函数用来对属性页的数
据进行初始化,而DoDataExchange()函数负责数据的交换,也就是属性的更新工作。这两个函数的
代码都由ClassWizard管理,用户无需管理。
b
n
c
.
w
w
w
k
o
o
k
o
o
t
e
.
n
2.3 添加属性
.
c
o
o
b
n
c
.
w
w
w
属性是控件的特征,ActiveX控件将其暴露给容器作为控制控件的参数。ActiveX控件的属性有
两种:
(1)库存属性(Stock):是每个控件都必须支持的,如背景颜色的实现由MFC在ActiveX控
件运行中用DLL提供,可被自定义属性覆盖。
(2)自定义属性(Custom):由控件开发人员定制的属性,管理ActiveX控件的内部性能。
本例主要介绍添加标准属性和用户自定义属性。
1. 添加用户定制属性
本例要添加的用户自定义属性是图形的填充图案属性brush,它确定图形内部的填充图案。
添加brush属性的步骤如下:
(1)单击“查看”→“建立类向导”打开MFC ClassWizard对话框,切换到Automation选项
卡。选中要添加属性的类名为CActiveXSampleCtrl类,单击Add Property按钮,如图5所示。
(2)在弹出的Add Property对话框中,输入External name为brush,这是控件属性的外部名称。
选择Type为short,选择行为为Member variable,如图6所示。
t
e
n
k
.
w
w
w
b
n
c
.
o
o
b
n
n
k
.
e
t
b
n
c
.
w
w
w
k
o
o
t
e
.
n
其中,Variable name为对应的变量的名称,这里使用默认值。Notification框中是用来处理属性
发生变化时的函数,也使用默认生成的函数名。Implementation用来选择更改属性的方法,Stock是
标准属性,由标准的方法来处理;Member variable用成员变量的方法来处理,可以直接更改属性的
取值;Get/Set methods不能直接改变属性的取值,必须提供专门的函数来实现。
(3)初始化属性的成员变量m_brush, 如程序代码2所示。
【程序代码2】
CActiveXSampleCtrl::CActiveXSampleCtrl()
{
InitializeIIDs(&IID_DActiveXSample, &IID_DActiveXSampleEvents);
w
w
w
o
o
b
n
c
.
t
e
n
k
.
b
n
c
.
w
w
w
w
w
k
o
o
t
e
.
n
n
c
w
.
k
o
o
b
图5 MFC ClassWizard对话框 图6 添加brush属性
w
w
c
.
w
o
o
b
n
e
n
k
.
t
※ 5 ※
o
o
e
n
k
.
t
w
w
c
w
.
o
t
e
n
k
.
.
c
o
o
b
n
c
.
w
w
w
// TODO: Initialize your control's instance data here
m_brush=0;
}
(4)在CActiveXSampleCtrl类的DoPropExchange()函数中添加代码,如程序代码3所示。
【程序代码3】
void CActiveXSampleCtrl::DoPropExchange(CPropExchange* pPX)
{
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
COleControl::DoPropExchange(pPX);
// TODO: Call PX_ functions for each persistent custom property
PX_Short(pPX, "brush", m_brush, 0);
}
其中的PX_Short()函数将控件类的属性与控件类的成员变量联系在一起,它的参数分别是:
① 指向属性交换对象的指针。
② 控件属性的外部名称。
③ 控件属性对应的控件类的成员变量。
④ 控件属性的默认值。
类似于PX_Short()的函数还有很多,都是针对某一类型的属性的,常用的有PX_Bool、PX_Color、
PX_Float、PX_Font、PX_String、PX_UShort、PX_ULong和PX_Double等。实际上,PX_函数不仅
仅完成了控件的属性的初始化工作,它还完成了属性的序列化。
(5)如果控件的属性发生了变化,那么就会调用OnBrushChanged()函数。修改后的
OnBrushChanged(),如程序代码4所示。
【程序代码4】
void CActiveXSampleCtrl::OnBrushChanged()
{
// TODO: Add notification handler code
InvalidateControl();
SetModifiedFlag();
}
该函数使控件无效并重画,这样就完成了控件的更新显示。
(6)CActiveXSampleCtrl类的OnDraw()函数也要进行修改,如程序代码5所示。
【程序代码5
】
void CActiveXSampleCtrl::OnDraw(CDC* pdc, const CRect& rcBounds,
const CRect& rcInvalid)
{
// TODO: Replace the following code with your own drawing code
pdc->FillRect(rcBounds,
CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
int style;
switch(m_brush)
{
case 0:
style=HS_BDIAGONAL;
break;
case 1:
style=HS_CROSS;
b
n
c
.
w
w
w
k
o
o
k
o
o
t
e
.
n
t
e
n
k
.
w
w
w
b
n
c
.
o
o
b
n
n
k
.
e
t
b
n
c
.
w
w
w
k
o
o
t
e
.
n
w
w
w
o
o
b
n
c
.
t
e
n
k
.
b
n
c
.
w
w
w
w
w
k
o
o
t
e
.
n
n
c
w
.
k
o
o
b
w
w
c
.
w
o
o
b
n
e
n
k
.
t
※ 6 ※
o
o
e
n
k
.
t
w
w
c
w
.
o
t
e
n
k
.
.
c
o
o
b
n
break;
case 2:
style=HS_FDIAGONAL;
break;
case 3:
style=HS_VERTICAL;
break;
default:
style=HS_CROSS;
}
CBrush *pBrush=new CBrush();
pBrush->CreateHatchBrush(style, RGB(20,1,2));
CBrush *pOldBrush=(CBrush *)pdc->SelectObject(pBrush);
pdc->Ellipse(rcBounds);
pdc->SelectObject(pOldBrush);
}
修改后,OnDraw()函数根据m_brush的值来确定填充椭圆所用到的图案。
2. 添加标准属性
本例要添加的标准属性是BackColor属性,它标识控件的背景颜色。添加BackColor属性的方
法与添加brush属性的方法类似,在External name右侧的下拉列表框中选择BackColor,行为选择
为Stock单选框(图7)。
b
n
c
.
w
w
w
k
o
o
k
o
o
t
e
.
n
t
e
n
k
.
w
w
w
b
n
c
.
c
.
w
w
w
o
o
b
n
n
k
.
e
t
b
n
c
.
w
w
w
k
o
o
t
e
.
n
2.4 使用属性表
1. 修改属性页
为控件添加了brush属性后,还没有为该属性提供可视化的界面供用户修改。在这里,定制了
对话框来修改属性。
(1)首先打开ID为IDD_PROPPAGE_ACTIVEXSAMPLE的对话框资源,把原来的静态文本控
件的标题做修改,接着在该对话框中插入一个组合框(图8)。
(2)打开组合框属性对话框,切换到Styles选项卡,设置组合框的风格为Drop List下拉列表
框,取消Sort复选框(图9)。
w
w
w
o
o
b
n
c
.
t
e
n
k
.
b
n
c
.
w
w
w
k
o
o
t
e
.
n
图7 添加BackColor属性
图8 对话框资源的修改 图9 设置组合框的风格
w
w
c
.
w
o
o
b
n
e
n
k
.
t
w
w
n
c
w
.
k
o
o
b
※ 7 ※
o
o
e
n
k
.
t
w
w
c
w
.
(3)切换到Data选项卡,输入数据(图10)。其中,数据输入中,换行用Ctrl+Enter组合键。
o
t
e
n
k
.
b
n
c
.
w
w
w
k
o
o
k
o
o
t
e
.
n
图10 组合框的数据
.
c
o
o
b
n
(4)用ClassWizard为组合框在CActiveXSamplePropPage类中添加一个int类型的变量
m_brush_selection和一个ComboBox类型的变量m_combox_brush。其中,m_brush_selection用于记
录组合框中选中的项,是大于等于0的整数;m_combox_brush用于确定当选择改变后,选中的是哪
一项。
(5)双击组合框,映射组合框的选中项改变时的处理函数,如程序代码6所示。
【程序代码6】
void CActiveXSamplePropPage::OnBrushSelectChanged()
{
// TODO: Add your control notification handler code here
m_brush_selection=m_combox_Sel();
}
该函数把改变后的选项保存在成员变量m_brush_selection中。
(6)编译运行控件程序,在弹出的“可执行调试对话”对话框中选择ActiveX Control Test
Container作为容器。在容器中插入ActiveX Sample Control类型的对象,单击Edit→Property。在弹
出的属性对话框中可以选择不同的填充图案,单击“应用”按钮即可看到效果(图11)。
t
e
n
k
.
w
w
w
b
n
c
.
c
.
w
w
w
o
o
b
n
n
k
.
e
t
b
n
c
.
w
w
w
k
o
o
t
e
.
n
2. 增加属性页
为了能在对话框中修改控件的BackColor属性,需要增加一个属性页。方法如下:
(1)修改文件“”中的代码,如程序代码7所示。
【程序代码7】
// Property pages
BEGIN_PROPPAGEIDS(CActiveXSampleCtrl, 2)
PROPPAGEID(CActiveXSamplePropPage::guid)
PROPPAGEID(CLSID_CColorPropPage)
END_PROPPAGEIDS(CActiveXSampleCtrl)
其中,CLSID_CColorPropPage是已经定义好的属性页。
(2)修改CActiveXSampleCtrl类的OnDraw()函数,以便按对话框中的背景颜色绘制控件,如
程序代码8所示。
【程序代码8】
void CActiveXSampleCtrl::OnDraw(CDC* pdc, const CRect& rcBounds,
w
w
w
o
o
b
n
c
.
图11 设置控件图形的填充图案
t
e
n
k
.
b
n
c
.
w
w
w
k
o
o
t
e
.
n
w
w
c
.
w
o
o
b
n
e
n
k
.
t
w
w
n
c
w
.
k
o
o
b
※ 8 ※
o
o
e
n
k
.
t
w
w
c
w
.
o
t
e
n
k
.
const CRect& rcInvalid)
{
// TODO: Replace the following code with your own drawing code.
CBrush backBrush;
COLORREF backColor=TranslateColor(GetBackColor());
SolidBrush(backColor);
pdc->FillRect(rcBounds, &backBrush);
……
}
(3)编译运行控件程序。第一次运行该ActiveX控件时,Visual C++会自动注册控件,并提示
运行该控件的容器,选择在ActiveX Control Test Container中运行控件,如图12所示。
b
n
c
.
w
w
w
k
o
o
k
o
o
t
e
.
n
n
c
.
o
o
b
t
e
n
k
.
w
w
w
b
n
c
.
图12 选择在ActiveX Control Test Container中运行控件
打开ActiveX Control Test Container程序后,单击Edit→Insert New Control,把该ActiveX控件
(ActiveXSample Control)加载进容器中,如图13所示。
c
.
w
w
w
o
o
b
n
n
k
.
e
t
b
n
c
.
w
w
w
k
o
o
t
e
.
n
图13 加载ActiveX控件
(4)选中ActiveX控件后,单击Edit→Properties会弹出控件的属性设置对话框,通过对话框
可以改变控件的背景颜色(图14)。
w
w
w
2.5 添加方法
o
o
b
n
c
.
t
e
n
k
.
b
n
c
.
w
w
w
w
w
k
o
o
t
e
.
n
n
c
w
.
k
o
o
b
图14 在属性设置对话框中修改控件的背景颜色
控件的方法(Method)类似于C++类中的成员函数。容器应用程序可以直接更改属性的取值,
这些属性是“共有”的;对于某些需要保护的属性,方法可以称为沟通容器和控件的桥梁。本例是
向控件添加一组Get/Set方法。该组方法的功能是返回和设置当前画的图形是椭圆,或者饼图。由
于只有两种可能,所以为控件设置了一个布尔型的变量m_bShape来记录控件当前画的形状。添加
w
w
c
.
w
o
o
b
n
e
n
k
.
t
※ 9 ※
o
o
e
n
k
.
t
w
w
c
w
.
o
t
e
n
k
.
Get/Set方法的步骤如下:
(1)单击“查看”→“建立类向导”打开MFC ClassWizard对话框,切换到Automation选项
卡。选中要添加属性的类名为CActiveXSampleCtrl类,单击Add Property按钮,如图15所示。弹
出Add Property对话框。在该对话框中输入External name为shape,这是控件属性的外部名称。选
择Type为BOOL,选择行为为Get/Set methods,如图16所示。
b
n
c
.
w
w
w
k
o
o
k
o
o
t
e
.
n
n
c
.
o
o
b
(2)修改DoPropExchange()函数,以便将属性名称与类的成员变量联系起来,如程序代码9
所示。
【程序代码9】
void CActiveXSampleCtrl::DoPropExchange(CPropExchange* pPX)
{
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
COleControl::DoPropExchange(pPX);
// TODO: Call PX_ functions for each persistent custom property
PX_Short(pPX, "brush", m_brush, 0);
PX_Bool(pPX, "shape", m_bShape, TRUE);
}
(3)修改GetShape()函数,如程序代码10所示。
【程序代码10】
BOOL CActiveXSampleCtrl::GetShape()
{
// TODO: Add your property handler here
return m_bShape;
}
(4)修改SetShape()函数,如程序代码11所示。
【程序代码11】
void CActiveXSampleCtrl::SetShape(BOOL bNewValue)
{
// TODO: Add your property handler here
m_bShape=bNewValue;
SetModifiedFlag();
}
(5)修改OnDraw()函数,如程序代码12所示。
【程序代码12】
void CActiveXSampleCtrl::OnDraw(CDC* pdc, const CRect& rcBounds,
const CRect& rcInvalid)
{
……
t
e
n
k
.
w
w
w
b
n
c
.
图15 打开MFC ClassWizard对话框添加方法 图16 添加Get/Set方法
c
.
w
w
w
o
o
b
n
n
k
.
e
t
b
n
c
.
w
w
w
k
o
o
t
e
.
n
w
w
w
o
o
b
n
c
.
t
e
n
k
.
b
n
c
.
w
w
w
w
w
k
o
o
t
e
.
n
n
c
w
.
k
o
o
b
w
w
c
.
w
o
o
b
n
e
n
k
.
t
※ 10 ※
o
o
e
n
k
.
t
w
w
c
w
.
o
t
e
n
k
.
CBrush *pBrush=new CBrush();
pBrush->CreateHatchBrush(style, RGB(20,1,2));
CBrush *pOldBrush=(CBrush *)pdc->SelectObject(pBrush);
if(m_bShape==TRUE)
pdc->Ellipse(rcBounds);
else
pdc->Pie(rcBounds, t(), Right());
pdc->SelectObject(pOldBrush);
}
(6)在ActiveX Control Test Container中运行控件,选中控件后单击Control→Invoke Methods,
弹出“Invoke Methods”对话框。在Method Name中选择shape(PropGet)就可调用GetShape()方
法(图17)。
b
n
c
.
w
w
w
k
o
o
k
o
o
t
e
.
n
.
c
o
o
b
n
t
e
n
k
.
w
w
w
b
n
c
.
2.6 添加事件
c
.
w
w
w
事件是控件在相应外部作用时由控件触发的通知。例如,单击控件、用键盘输入数据或改变控
件的状态等。当这些动作发生时,控件点火一个事件并通知容器。
控件利用事件与控件的容器进行通信。控件可以向容器发送通知,反过来容器也可以向控件发
出通知。
MFC支持两种事件:库存事件(stock event)和自定义事件(custom event)。库存事件是
COleControl自动处理的事件。自定义则用于标识某一确定的动作,由用户定义。用点火函数可以触
发事件。
本例向控件添加一个自定义事件,当双击控件,并且控件所画的图形为椭圆时触发该事件。添
加事件的步骤如下。
(1)单击“查看”→“建立类向导”,打开MFC ClassWizard对话框,切换到ActiveX Events
选项卡。选中要添加事件的类名为CActiveXSampleCtrl类,单击Add Event按钮,如图18所示。
o
o
b
n
n
k
.
e
t
b
n
c
.
w
w
w
k
o
o
t
e
.
n
图17 使用Get/Set方法
w
w
w
o
o
b
n
c
.
t
e
n
k
.
b
n
c
.
w
w
w
w
w
k
o
o
t
e
.
n
n
c
w
.
k
o
o
b
w
w
c
.
w
o
o
b
n
e
n
k
.
t
图18 打开MFC ClassWizard对话框添加事件
※ 11 ※
o
o
e
n
k
.
t
w
w
c
w
.
o
t
e
n
k
.
(2)在弹出的Add Event对话框中,输入External name为DblClickTrans,这是控件属性的外
部名称。默认的点火函数为FireDblClickTrans()(图19)。
(3)用ClassWizard为CActiveXSampleCtrl类映射鼠标双击消息,如图20所示。
b
n
c
.
w
w
w
k
o
o
k
o
o
t
e
.
n
.
b
c
n
.
k
o
o
图19 添加DblClickTrans事件 图20 映射鼠标双击消息
c
.
w
w
w
(4)修改OnLButtonDblClk()函数的代码,如程序代码13所示。
【程序代码13】
void CActiveXSampleCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if(m_bShape==TRUE)
FireDblClickTrans();
COleControl::OnLButtonDblClk(nFlags, point);
}
(5)在ActiveX Control Test Container中运行控件。当控件中画的图形为椭圆时,双击控件可
以看到ActiveX Control Test Container下窗口显示事件的名字DblClickTrans,说明触发了
DblClickTrans事件(图21);而当控件中画的图形为饼图时,双击控件则没有触发事件(图22)。
t
e
n
w
w
w
b
n
c
.
o
o
b
n
n
k
.
e
t
b
n
c
.
w
w
w
k
o
o
t
e
.
n
图21 双击椭圆触发了DblClickTrans事件 图22 双击饼图没有触发DblClickTrans事件
w
w
w
o
o
b
n
c
.
t
e
n
k
.
b
n
c
.
w
w
w
w
w
k
o
o
t
e
.
n
n
c
w
.
k
o
o
b
w
w
c
.
w
o
o
b
n
e
n
k
.
t
※ 12 ※
o
o
e
n
k
.
t
w
w
c
w
.


发布评论