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控件、OLEActiveX自动化

引言:ActiveXMicrosoft公司的一项注册技术,它使用COM实现Windows程序之间的通信。

ActiveX封装包括了OLEInternet和多媒体在内的各种技术,Internet/Intranet的一个开放式平台。

ActiveX控件是OLE控件的升级版,大大简化了用户的操作,用户可以像使用Windows标准控件那

样使用它。ActiveX控件可以插入到Web页或者ActiveX包容器中。

正文:

k

o

o

1 ActiveX控件介绍

ActiveX控件是为Windows编写的可重复使用的定制控件,它是作为进程中的服务器而实现的。

本节将介绍ActiveX控件的相关知识。

1.1 ActiveX控件的相关技术

ActiveX控件相关的技术有OLE、容器与服务器、ActiveX自动化等,下面分别加以介绍。

1. OLE介绍

OLEObject Linking and Embedding对象的嵌入与链接)是以COM为基础的。COMComponent

Object Model,组件对象模型)是OLE的基础。COM是一种能够使软部件作为对象进行相互作用的

二进制标准。COM不是一种编程语言,但可以为支持COM对象二进制形式的语言一起工作。可以

认为,COM提供了二进制对象的规范。

OLE使应用程序能够通过数据链接或嵌入的方式共享数据。当数据集合被链接到文档中,文档

将与此数据集合作为文档的一部分,并保持其与文档的链接。数据集合仍然作为一个分离对象保存

在自己的文件内,可以使用指针用其编辑程序单独打开。修改对象后,文档也发生相应的变化。如

果数据被嵌入文档,文档将不保留与最初含有此数据集合的文件的链接关系。也就是文档不会随数

据集合的原文件的修改而修改。无论是链接还是嵌入,都提供在文档中打开相应应用程序处理其中

特定数据集合的能力。

2. 容器与服务器

嵌入和链接的实现都需要容器和服务器(Container and Server)的支持。含有链接或嵌入数据

的应用程序称为容器应用程序,而为这些数据提供编辑功能的应用程序称为服务程序。

其中,服务器分为三种类型:小型服务器、全服务器和自动化服务器。小型服务器是指不能独

立运行,只能使用其包含到容器的服务器。全服务器是指可作为独立的应用程序运行,又可由容器

启动的服务器。自动化服务器是为自动化提供服务的程序。

3. ActiveX自动化

OLE自动化(ActiveX Automation)允许通过使用高级的宏语言或脚本语言(如JavaScript)在

应用序的内部操作另一个应用程序的属性和方法。用于驱动的应用程序称为自动化客户

Automation Client,而被驱动的应用程序称为自动化服务器(Automation Server)或自动化部件。

自动化客户是指使用OLE自动化提供服务的控制程序,它通过IDispatch接口工作。

自动化部件是一项由一个应用程序提供,而被另一个应用程序使用的服务,它是用对象描述语

言定义的。

对象描述语言所生成的文件扩展名为ODLODL文件经编译后存储到类型库(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)属性(PropertyActiveX控件内用于定义颜色、大小、范围和状态标志符等的数值。属

性可以是库存属性(Stock)或者自定义属性(Custom

2)方法(MethodActiveX控件内供容器程序外部调用的函数。ActiveX控件的方法包括库

存方法和自定义方法。

3)事件(EventActiveX控件对诸如鼠标消息和键盘输入等消息的反映。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 ControlWizardStep 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 ControlWizardStep 1 of 2对话框

3)在MFC ActiveX ControlWizardStep 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 ControlWizardStep 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 ControlWizardActiveXSampleCActiveXSampleApp

CActiveXSampleCtrlCActiveXSamplePropPage

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:是每个控件都必须支持的,如背景颜色的实现由MFCActiveX

件运行中用DLL提供,可被自定义属性覆盖。

2)自定义属性(Custom:由控件开发人员定制的属性,管理ActiveX控件的内部性能。

本例主要介绍添加标准属性和用户自定义属性。

1. 添加用户定制属性

本例要添加的用户自定义属性是图形的填充图案属性brush,它确定图形内部的填充图案。

添加brush属性的步骤如下:

1)单击“查看”→“建立类向导”打开MFC ClassWizard对话框,切换到Automation选项

卡。选中要添加属性的类名为CActiveXSampleCtrl类,单击Add Property按钮,如图5所示。

2在弹出的Add Property对话框中,输入External namebrush这是控件属性的外部名称。

选择Typeshort,选择行为为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_BoolPX_Color

PX_FloatPX_FontPX_StringPX_UShortPX_ULongPX_Double等。实际上,PX_函数不仅

仅完成了控件的属性的初始化工作,它还完成了属性的序列化。

5OnBrushChanged()

OnBrushChanged(),如程序代码4所示。

【程序代码4

void CActiveXSampleCtrl::OnBrushChanged()

{

// TODO: Add notification handler code

InvalidateControl();

SetModifiedFlag();

}

该函数使控件无效并重画,这样就完成了控件的更新显示。

6CActiveXSampleCtrl类的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首先打开IDIDD_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。其中,数据输入中,换行用CtrlEnter组合键。

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

4ClassWizardCActiveXSamplePropPageint

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类型的对象,单击EditProperty。在弹

出的属性对话框中可以选择不同的填充图案,单击“应用”按钮即可看到效果(图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程序后,单击EditInsert 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控件后,单击EditProperties会弹出控件的属性设置对话框,通过对话框

可以改变控件的背景颜色(图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 nameshape,这是控件属性的外部名称。选

TypeBOOL,选择行为为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中运行控件,选中控件后单击ControlInvoke Methods

弹出“Invoke Methods”对话框。在Method Name中选择shapePropGet)就可调用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 nameDblClickTrans,这是控件属性的外

部名称。默认的点火函数为FireDblClickTrans()(图19

3)用ClassWizardCActiveXSampleCtrl类映射鼠标双击消息,如图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 ContainerDblClickTrans

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

.