基本概念:
容器和服务器程序
容器应用程序时可以嵌入或链接对象的应用程序。Word 就是容器应用程序。服务器应用程序是创建对象并且当对象被双击时,可以被启动的应用程序。Excel 就是服务器应用程序。ActiveX 控件不能独立运行,它必须被嵌入容器应用程序中,和容器应用程序一起运行。@H_301_5@ @H_301_5@ ---------------------------------------------------------------------------------@H_301_5@ 编写一个 ActiveX 时钟控件
1.利用 MFC ActiveX ContrlWizard 新建一个 Clock 工程
2.在新建的工程中有三个类,其中 CClockApp 从 COleControlModule 中派生出来的,
可以将其看作是应用程序类,它的一个实例表示控件程序本身。@H_301_5@ @H_301_5@ COleControl 从 CWnd 派生得到,也是一个窗口类,@H_301_5@ CClockCtrl 相当于单文档程序的主窗口类。@H_301_5@ 这个类包含重绘用的 On
3.在三个类之上,还有类似小勺的图标 Dclock,_DClockEvents,它们表示接口。
接口是外部程序和控件进行通信的协议,可以把接口看作是函数的集合,外部程序通过接口提供的方法,去访问控件的属性和方法。也可以将接口看作抽象基类,接口中所定义的所有函数都是纯虚函数, 这些函数的实现都是在 CClockCtrl 类中实现,MFC 通过底层的封装使 CClockCtrl 类继承 Dclock 接口。所以调用接口,事实上调用的是 CClockCtrl 类中的函数。由于封装,底层的通信细节我们看不到,如果对这个感兴趣,可以看一些 COM 编程的资料。@H_301_5@ @H_301_5@ 4.如果些时编译一下工程,会生成一个 Clock.ocx 文件,它就是 ActiveX 控件的文件。
要用控件的时候,只需要把这个文件传递给对方。注意:ActiveX 控件不能单独使用,必须嵌入到一个窗口当中一直运行。当我们用 VB 添加控件时,发现了我们刚才编译的控件,但是 VB 怎么知道我们新建的控件的位置呢? 我们发现编译时,输出窗口的最后一行 “Registering ActiveX Control...”说明编译时会注册控件。事实上编译之后,VC 会调用 regsvr32 注册控件,并将信息写入到注册表中,VB 在加载 ActiveX 控件时,会从注册表中搜寻相关的 ActiveX 控件信息。注意:ActiveX 控件在使用之前都需要注册。
如果想卸载控件,可以在“运行”中输入命令:@H_301_5@ “regsvr32 /u 控件文件完整路径名”,事实上是调用工程中全局函数 DllUnregisterServer 来完成卸载的。@H_301_5@ 如果想再次注册控件,可以在“运行”中输入下面命令:@H_301_5@ “regsvr32 控件文件完整路径名”事实上是调用工程中全局函数 DllRegisterServer 来完成注册的。@H_301_5@ @H_301_5@ 5.下面实现在控件上输出当时系统时间。
可以在 On
ActiveX 控件有四种属性:@H_301_5@ Stock:为每个控件提供的标准属性,如字体或颜色。@H_301_5@ Ambient:围绕控件的环境属性——已被置入容器的属性。@H_301_5@ 这些属性不能被修改,但控件可以使用它们调整自己的属性。@H_301_5@ Extended:这些是由容器处理的属性,一般包括大小和在屏幕上的位置。@H_301_5@ Custom:由控件开发者添加的属性。@H_301_5@ @H_301_5@ 7.这时在 VB 测试中,我们的控件也可以修改控件的背景色和前景色了,但是设置完以后没有效果,因为还要 On
1)下面增加设置时间间隔的属性,用这个属性来控件时间刷新频率:@H_301_5@ @H_301_5@ 属性添加成功以后,在_DClock 接口中增加了 Interval 属性,同时在 CClockCtrl 类中增加了一个@H_301_5@ 成员变量 m_interval 和 On
在对话框资源中添加一个编辑框,再为这个编辑框关联一个变量, 注意,我们在为编辑框关联一个变量 m_updateInterval 的同时也关联了一个属性是,这样我们不需要增加代码就能把控件和自定义属性相关联。在 void CClockPropPage::DoDataExchange(CDataExchange* pDX)中会生成下面代码:@H_301_5@ @H_301_5@ 这样,我们就可以在属性页里面设置时间间隔了。@H_301_5@ @H_301_5@ 11.为控件添加一个方法:
为控件增加函数,MFC ClassWizard-->Automation-->Add Method Class Name 要选择CClockCtrl 输入函数名,之后就可以在 CClockCtrl 类中找到了。方法添加成功以后,在_DClock 接口中增加了 Hello 方法,同时在 CClockCtrl 类中增加了 Hello 方法。接下来,我们可以在 CClockCtrl 类中增加了 Hello 方法添加自己的代码就可以了。
12.为控件添加一个标准事件
我们选择 MFC ClassWizard-->ActiveX Events--->Add Event。事件添加成功以后,会在_DClockEvents 中增加一个事件 Click,DClockEvents 接口是源接口,控件将用这个接口发送通知事件,它不是控件本身实现的接口,这个接口是通过容器来实现的@H_301_5@ @H_301_5@ 13.增加一个自定义事件:当秒数为0时,发出一个 NewMinute 事件。
1)增加一个自定义事件的过程与增加一个标准事件的步骤相同,也可以这样添加在事件接口_DClockEvents 上点击右键,选择增加事件,效果一样,都会弹出 Add Event 对话框。事件添加成功以后,会在_DClockEvents 中增加一个事件NewMinute事件,同时在在 CClockCtrl 类中增加了void FireNewMinute(),也就是在控件内部可以调用 FireNewMinute()向容器发送事件通知,而这个函数内部会调用接口的 void NewMinute()向容器发出事件通知。@H_301_5@ @H_301_5@ 2)在 On
14.将我们自定义的控件属性在修改之后永久保存下来,用户打开程序之后,控件的属性都是使用原先保存的值。需要在 void CClockCtrl::DoPropExchange(CPropExchange* pPX)加入如下代码 PX_Short(pPX,"Interval",m_interval,1000);之后再在程序中 On
17.编写完控件以后,我们可以选择 Win32 Release 方式进行编译,生成发行版 ActiveX 控件。在开发的时候通常是以 Win32 Debug 模式下编译的,这种模式下开发有助于我们开发过程的产生的错误,例如非法内存访问错误;还可以帮助我们调试程序,跟踪程序进而排查错误。但是在调试模式下生成的文件比较大,因为在文件中包含了调试的信息。
而当我们开发完成后,在 Release 模式下进行编译时,VC 编译器会在代码生成上、执行速度上做一些优化,同时生成的可执行程序或控件文件会比较小。@H_301_5@ -------------------------------------------------------------------
在 VC 中编写一个客户端调用 ActiveX 控件:
1.新建一个基于 MFC 对话框的 ClockTest 工程项目
2.点击右键,选择“插入 ActiveX 控件”,然后在弹出的对话框中选择刚才我们创建的控件。
也可以通过菜单的方式增加控件:@H_301_5@ “工程”->增加到工程->Componets and Controls@H_301_5@ 选择已注册控件"Registered ActiveX Contrlos",找到我们自己控件,再按下插入。@H_301_5@ @H_301_5@ 通过这种方式插入 ActiveX 控件时,会在工程中自动生成一个类 CCock,其基类为 CWnd。这个类是一个封装类,封装了对 ActiveX 控件进行访问的一些操作。同时在 VC 的工具箱上面也增加一个时钟控件,可以直接将一个时钟控件拖放到窗体上。
3.用第二种方法插入的控件,除了将控件手动插入到窗体以外,我们也可以通过代码动态生成一个控件。
1)CClockTestDlg 增加一个成员变量:CClock m_clock; 2)在 CClockTestDlg 的头文件中包含一个 clock.h 3)接下来就要以在一个按钮的单击事件中增加创建控件的代码: 4)在设计时,可以点击右键为控件添加事件响应。