ActiveX 学习笔记
1.ActiveX的基本概念
ActiveX控件可以看作是一个极小的服务器应用程序,它不能独立运行,必须嵌入到某个容器程序中,与该容器一起运行。这个容器包括WEB网页,应用程序窗体等。
ActiveX控件的后缀名是OCX或者DLL。一般是以OCX和动态库共存的形式打包成cab或者exe的文件放在服务器上,客户端下载后运行安装cab或exe解压成OCX和动态库共存的文件,然后注册ocx文件。
ActiveX控件是基于COM标准,使得软件部件在网络环境中进行交互的技术集。它与具体的编程语言无关。作为针对Internet应用开发的技术,ActiveX被广泛应用于WEB服务器以及客户端的各个方面。同时,ActiveX技术也被用于方便地创建普通的桌面应用程序,此外ActiveX一般具有界面。
2.三个概念:ActiveX、OLE和COM
从时间的角度讲,OLE是最早出现的,然后是COM和 ActiveX;从体系结构角度讲,OLE和ActiveX是建立在COM之上的,所以COM是基础;单从名称角度讲,OLE、ActiveX是两个商标名称,而COM则是一个纯技术名词,这也是大家更多的听说ActiveX和OLE的原因。COM是应OLE的需求而诞生的,所以虽然COM是OLE的基础,但OLE的产生却在COM之前。COM的基本出发点是,让某个软件通过一个通用的机构为另一个软件提供服务。ActiveX最核心的技术还是COM。ActiveX和OLE的最大不同在于,OLE针对的是桌面上应用软件和文件之间的集成,而 ActiveX则以提供进一步的网络应用与用户交互为主。COM对象可以用C++、Java和VB等任意一种语言编写,并可以用DLL或作为不同过程工作的执行文件的形式来实现。使用COM对象的浏览器,无需关心对象是用什么语言写的,也无须关心它是以DLL还是以另外的过程来执行的。从浏览器端看,无任何区别。这样一个通用的处理技巧非常有用。
3.ActiveX控件工程的创建
使用VS2013有两种方式可以创建ActiveX工程:
第一种:创建“MFC ActiveX Control”工程;
第二种:创建“ATL 项目”。由于使用ATL开发ActiveX控件需要了解com技术,对程序员的要求也较高,开发时间也较长,所以如果ActiveX只在windows操作系统下运行,那么就使用“MFC ActiveX Control”工程来快速建立ActiveX控件。但是这里要注意了:使用“MFC ActiveX Control”工程来快速建立ActiveX控件,他不仅要建立在windows操作系统下,还必须在windows操作系统下安装c++依赖库安装包,因为MFC是建立在微软的c++动态库的基础上的。所以这两种方式各有优缺点,根据项目需求来选择适合的方式。
4.使用VS2013创建MFC ActiveX工程项目步骤
第一、新建项目-》选择MFC ActiveX Control工程,命名EasyStatusBar,点击确定弹出控件向导对话框。
第二、,向导对话框中全部选择默认即可,点击finish就完成了工程的创建。
5.分析“MFC ActiveX 控件”工程的三个重要的类以及对外接口定义文件idl
使用向导创建完工程可以看到自动生成了三个类:CEasyStatusBarApp,CEasyStatusBarCtrl,CEasyStatusBarPropPage
我们可以发现CEasyStatusBarApp派生于COleControlMoudle类,而COleControlMoudle派生于CWinApp,所以可以把该类看做是一个应用程序类,它的实例表示了控件程序本身。
CEasyStatusBarCtrl派生于COleControl类,而COleControl派生于CWnd,因此它是一个窗口类,那么对控件窗口的操作都在该类中完成。在该类中提供了一个OnDraw函数,当窗口控件发送重绘时候就会调用这个函数。如果控件需要输出图像,就可以在这个函数中编写相应的代码。当然,我们也可以通过GetDC()获取上下文设备进行图形绘制!
CEasyStatusBarPropPage派生于COlePropertyPage类,而COlePropertyPage派生于CDialog类,它以一种类似于对话框的图形界面显示自定义控件的属性。
打开EasyStatusBarCtrl.h文件,我们发现了如下所示的内容:
与之在EasyStatusBarCtrl.cpp中相对应的内容如下所示:
可以发现该头文件不仅仅定义了消息映射,还提供了一个调度映射和事件映射。其中调度映射是MFC提供的一种映射机制,主要是为了让外部应用程序可以方便的访问控件的属性和方法,而事件映射也是MFC提供的一种机制,让控件可以向包含它的容器发送事件通知,稍后我们在为控件添加方法和属性以及事件的时候就会用到这两个映射。
接下来我们来看最重要的部分:对外接口定义文件EasyStatusBar.idl,代码如下:
#include
#include
[ uuid(D7247DEF-2A87-4D2F-A656-8EE1574B3940), version(1.0),
control ]
library EasyStatusBarLib
{
importlib(STDOLE_TLB);
// Primary dispatch interface for CEasyStatusBarCtrl
[
uuid(6F64AC3A-9CB6-4F92-9696-6CC0BF11868E)
]
dispinterface _DEasyStatusBar
{
properties:
methods:
[id(DISPID_ABOUTBOX)] void AboutBox();
};
// Event dispatch interface for CEasyStatusBarCtrl
[
uuid(739548F0-7514-49CA-8505-4395F554E284)
]
dispinterface _DEasyStatusBarEvents
{
properties:
// Event interface has no properties
methods:
};
// Class information for CEasyStatusBarCtrl
[
uuid(835515A0-122B-46C3-903A-5B013C657FE6)
]
coclass EasyStatusBar
{
[default] dispinterface _DEasyStatusBar;
[default, source] dispinterface _DEasyStatusBarEvents;
};
};
这个就是对外接口定义文件,如果外部程序想要调用ActiveX的方法,属性以及在注册表注册的classid(WEB网页调用需要使用),就必须了解这个文件,这个文件可以分为四个部分来看:
首先是EasyStatusBar.Lib这个库信息:
第二部分是调度映射的接口信息,该接口信息包含了属性(如控件背景色)和对外方法
这里定义了一个AboutBox方法,用于弹出关于对话框。接口是控件和外部程序进行通信的协议。可以把接口看做是函数的集合,外部程序通过接口所暴露出来的方法去访问控件的属性和方法。实际上,可以把接口看做是一个抽象基类,在此接口中定义的所有函数都是纯虚函数,这些函数的实现是在CEasyStatusBar类中完成的。MFC通过底层的封装,让CEasyStatusBar继承这个接口,实现函数。
第三部分是事件映射的接口信息
第四部分是类的信息,其中uuid就是ActiveX控件注册到注册表的classid,它是ActiveX注册后在系统内的唯一标识,WEB网页就是使用这个ID加载ActiveX控件的
6.定义调度映射和事件映射方法,提供给外部调用者使用
那么怎么定义新的调度映射和事件映射方法呢,如果手动定义很不方便,当然使用编译器进行定义,步骤是打开类视图:
我们发现在EasyStatusBarLib下面存在_DEasyStatusBar和_DEasyStatusEvents这两个接口,分别对应调度映射和事件映射。在_DEasyStatusBar项中可以右键-》添加方法(或属性),该操作是完成调度映射的方法和属性的添加;在_DEasyStatusEvents项中可以右键-》添加方法(或属性),该操作是完成事件映射的方法和属性的添加。
举个例子,比如我们想为控件添加背景颜色和前景颜色(文本颜色)这个两个属性,如下所示:
在_DEasyStatusBar项中可以右键-》添加属性,弹出如下对话框:
在Property name这一栏下拉列表中有很多标准的属性,我们选择BackColor,然后我们发现在Implementation type这一项自动选择了Stock,代表标准颜色。如果我们想自定义属性,就需要在Property name输入属性名字比如Interval,然后在Implementation type有两个选择项,如果选择Member variable,就会为该属性生成一个成员变量和一个通知函数,如果选择Get/Set methods,就会生成一个GetInterval函数和一个SetInterval函数,具体我们需要根据自己的需求进行选择,这里选择Member variable选项,如下所示:
点击完成之后,将会在工程的三个地方增加对应的代码,分别如下所示:
1、在
2、在
3、在
以上是关于添加方法和属性,给控件添加事件的方法和属性的流程也是一样的,比如给控件添加点击事件,如下所示:
点击finish就完成了点击事件的添加,还是比较简单的。
现在我们的控件是什么也没显示,只有一个背景色的属性,下面我们来实现在按钮上显示当前时间,实现起来还是比较简单的,首先添加WM_CREATE消息的处理函数,在函数里面创建定时器,如下所示:
接下来添加WM_TIMER消息的处理函数,如下所示:
在上面的函数中调用了Invalidate()函数,调用该函数会马上引起控件的重绘,所以我们只需要在OnDraw函数中实现显示时间的代码即可,如下所示:
在以上函数中,首先是使背景色和前景色(文本颜色)生效,调用了响应的函数,然后就是显示当前时间的代码。
7.注册ActiveX控件
按照上面的步骤已经完成简单ActiveX控件的编写,重新生成后会在Debug下生成一个EasyStatusBar.ocx的文件,使用windows的dos窗口可以注册这个ActiveX控件,注册方法如下:
首先win+R键打开运行,然后输入注册命令:regsvr32 c:\.......\EasyStatusBar.ocx(反注册命令:regsvr32 c:\.......\EasyStatusBar.ocx -u)
有两种情况会导致控件注册失败:
第一种:使用非Administrator用户登入系统会由于权限不足而无法注册com组件,这时候就必须使用Administrator用户登入操作系统
第二种:ActiveX控件所依赖的dll库被程序给占用,就会导致注册失败,解决办法是将正在运行的程序关闭就可以
8.测试ActiveX控件的方法
第一种:使用html网页来测试
在TestMfcActiveX.htm的文件中编写代码如下:
注意上面的classid就是在idl文件中类的uuid,然后打开这个网页就会显示ActiveX控件。上面的classid在控件成功注册后也可以通过注册表查找,具体方法是win+R键,输入regedit命令,就会弹出“注册表编辑器”,位置在“HKET_CLASSES_ROOT”中,根据你控件的名称,快速按下前三个字母,然后就可以定位到比较好找的位置,如下图:
第二种:建立Mfc应用程序,在Mfc窗口右键-》插入“ActiveX”控件,然后就会在MFC的窗体上显示ActiveX控件
第三种:也是最方便的一种方法,就是使用vs自带的ActiveX Control Test Container来测试ActiveX控件,但是VS2013在“工具”中没有这一项,并且我也没有在安装目录下找到相关的,这一点比较坑爹!于是只能再装一个VS2010,把这个工具添加到VS2010,添加方法如下:
首先找到C:\Program Files\Microsoft Visual Studio 10.0\Samples\2052\C++\MFC\ole\TstCon\TstCon.sln(这个是安装目录,根据自己的实际情况来定),然后使用VS2010打开解决方案TstCon.sln,编译项目TCProps和TstCon,编译完成后会在C:\Program Files\Microsoft Visual Studio 10.0\Samples\2052\C++\MFC\ole\TstCon\Debug\中生成TstCon.exe执行程序,这个执行程序就是ActiveX Control Test Container,接下来我们就在VS2010中的工具中添加这个TstCon.exe,在VS2010中的“工具”菜单项中选择“外部工具”,在弹出的窗体中添加一个新的工具,标题为ActiveX Control Test Container,命令为C:\Program Files\Microsoft Visual Studio 10.0\Samples\2052\C++\MFC\ole\TstCon\Debug\TstCon.exe,然后点击确定就可以完成工具的添加了。
这样,在“工具”中就有了一个ActiveX Control Test Container,点击它就会弹出测试ActiveX的容器,如下图
点击Edit->Insert New Control->选择EasyStatusBar Control,点击OK
然后就会显示这个注册后的AcitveX控件,如果要测试这个控件的调度映射的方法About Box,就先选中控件,然后点击Control-》Invoke Methods,在Methods Name下拉框中选择AboutBox这个方法,点击Invoke按钮就可以测试这个方法了,如下图:
以上控件是我已经写好的一个控件,可以分别单独设置文本的颜色以及控件的背景色和前景色。
当然,我们还可以往控件里面加别的东西,比如对话框等等。以上差不多就是创建一个ActiveX控件的过程,还有很多细节没讲,比如属性的持久性,环境属性等等,后面慢慢补充。