web上用Activex控件开发步骤(MFC)

首先要说明的是 web上用activex是门被抛弃的技术。为什么这么说,主要基于以下几个原因:

  1. 功能过于强大,强大到一旦安装,他所具有的权限可以做任何事,极易被人利用做坏事(相信大家都有浏览网页后莫名被安装流氓软件的经历,当然流氓软件利用的方式不止控件一种);
  2. 通过网页下载控件的中间过程受到操作系统、杀毒软件、浏览器等多方面因素限制,这使你的控件产品未必能在所有用户的电脑上正常使用;
  3. 最恶心的一点,未签名没有正规安全证书的控件,在最新的浏览器上(IE7等)默认安全策略是直接屏蔽掉的,而你如果想要获取这个信任,需要向微软等少数单位申请,花费有多少?据说是每年4千多……

看了以上如果你还是想要知道步骤,如下:

一、用Vc++6.0新建工程里的向导创建MFC activeX controlWizard

细节不说了,根据你控件需要了,略有不同,问题不会太大。

二、你控件代码的主xx.cpp(非xxCtr.cpp)文件中添加安全接口函数

否则每次运行控件时IE都会给出安全提示,很烦!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#include "comcat.h"
#include "Objsafe.h"

// 本控件的CLSID,注册表用
const GUID CDECL CLSID_SafeItem ={ 0x7AE7497B, 0xCAD8, 0x4E66, { 0xA5,0x8B,0xDD,0xE9,0xBC,0xAF,0x6B,0x61 } };
// 版本控制
const WORD _wVerMajor = 1;
// 次版本号
const WORD _wVerMinor = 0;

/////////////////////////////////////////////////////////////////////
// CICCardApp::InitInstance - DLL initialization

BOOL CICCardApp::InitInstance()
{
BOOL bInit = COleControlModule::InitInstance();

if (bInit)
{

}

return bInit;
}

//////////////////////////////////////////////////////////////////////
// CICCardApp::ExitInstance - DLL termination

int CICCardApp::ExitInstance()
{
return COleControlModule::ExitInstance();
}

//////////////////////////////////////////////////////////////////////

// 创建组件种类
HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription)
{
ICatRegister* pcr = NULL ;
HRESULT hr = S_OK ;

hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
if (FAILED(hr))
return hr;

// Make sure the HKCR\Component Categories\{..catid...}
// key is registered.
CATEGORYINFO catinfo;
catinfo.catid = catid;
catinfo.lcid = 0x0409 ; // english

// Make sure the provided description is not too long.
// Only copy the first 127 characters if it is.
int len = wcslen(catDescription);
if (len>127)
len = 127;
wcsncpy(catinfo.szDescription, catDescription, len);
// Make sure the description is null terminated.
catinfo.szDescription[len] = '\0';

hr = pcr->RegisterCategories(1, &catinfo);
pcr->Release();

return hr;
}

// 注册组件种类
HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
{
// Register your component categories information.
ICatRegister* pcr = NULL ;
HRESULT hr = S_OK ;
hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
if (SUCCEEDED(hr))
{
// Register this category as being "implemented" by the class.
CATID rgcatid[1] ;
rgcatid[0] = catid;
hr = pcr->RegisterClassImplCategories(clsid, 1, rgcatid);
}
if (pcr != NULL)
pcr->Release();
return hr;
}
// 卸载组件种类
HRESULT UnRegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
{
ICatRegister* pcr = NULL ;
HRESULT hr = S_OK ;

hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
if (SUCCEEDED(hr))
{
// Unregister this category as being "implemented" by the class.
CATID rgcatid[1] ;
rgcatid[0] = catid;
hr = pcr->UnRegisterClassImplCategories(clsid, 1, rgcatid);
}

if (pcr != NULL)
pcr->Release();

return hr;
}

// DllRegisterServer - Adds entries to the system registry
STDAPI DllRegisterServer(void)
{
HRESULT hr;

AFX_MANAGE_STATE(_afxModuleAddrThis);

if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid))
return ResultFromScode(SELFREG_E_TYPELIB);

if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
return ResultFromScode(SELFREG_E_CLASS);

// 标记控件初始化安全.
// 创建初始化安全组件种类
hr = CreateComponentCategory(CATID_SafeForInitializing,
L"Controls safely initializable from persistent data!");
if (FAILED(hr))
return hr;
// 注册初始化安全
hr = RegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForInitializing);
if (FAILED(hr))
return hr;

// 标记控件脚本安全
// 创建脚本安全组件种类
hr = CreateComponentCategory(CATID_SafeForScripting, L"Controls safely scriptable!");
if (FAILED(hr))
return hr;
// 注册脚本安全组件种类
hr = RegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting);
if (FAILED(hr))
return hr;

return NOERROR;
}

//////////////////////////////////////////////////////////////////
// DllUnregisterServer - Removes entries from the system registry

STDAPI DllUnregisterServer(void)
{
HRESULT hr;

AFX_MANAGE_STATE(_afxModuleAddrThis);

if (!AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor))
return ResultFromScode(SELFREG_E_TYPELIB);

if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE))
return ResultFromScode(SELFREG_E_CLASS);

// 删除控件初始化安全入口.
hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForInitializing);
if (FAILED(hr))
return hr;
// 删除控件脚本安全入口
hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting);
if (FAILED(hr))
return hr;

//////////////////////////
return NOERROR;
}

三、添加自己的代码到控件文件xxCtr.cpp中

这里最好通过向导添加 View->ClassWard->automation

四、编译生成你的xx.ocx控件文件

这个文件其实就是个DLL函数库,只是后缀不同而已。

五、制作xx.inf文件用于之后的空间打包压缩

1
[version]   signature="$CHICAGO$"   AdvancedINF=1.0   [Add.Code]   xx.ocx=xx.ocx   [xx.ocx]   file-win32-x86=thiscab   clsid={351FC603-D784-4B8D-BA2C-33C212EC5BAA}   FileVersion=1,0,0,1   RegisterServer=yes

六、打包压缩成xx.cab文件

你需要用到给控件签名的一些工具:cabarc.exe、signcode.exe,另外你可能需要用于制作自己试验证书的工具:makecert.exe、cert2spc.exe。
制作根证书MyCert.cer和私钥myKey.PVK:

1
2
makecert -r  -sv "myKey.PVK"  -n CN="xx Electric Industry Co. Ltd."   MyCert.cer
CERT2SPC MyOKIcert.cer MyOKIcert.spc打包压缩空间为xx.cab:
1
cabarc -s 6144 n xx.cab xx.ocx xx.inf

数字签名cab文件
双击signocode.exe文件,图形化签名,注意要通过自定义选择自己的证书和私钥而不是选择系统已有的。

七、在你要用空间的Web上添加代码:

1
<td colspan="2"><object id='t1' codeBase=/UserMode/xx.cab#version=1,0,0,1 classid='clsid:F3530445-A287-4A0B-AC3E-C4AF2B63EBA7' height=0 width=0 ></object></td>

八、调用控件内方法。

通过javascript直接调用控件对象的方法就行了,比如调用空间中存在的一个download()方法: document.getElementByID(“t1”).download();八。客户端使用,其他人从网上下载到你的控件后,如果是Window XP系统的话,需要先导入证书为可信任(详细到Google上搜索导入证书,很容易),再安装控件,之后才能用;而如果是Window2000用户则只要安装控件就可以使用了。

九、控件的删除

Internet选项-〉设定-〉显示对象,直接看到你的xx.cab文件,Del掉就行了,注册表中信息会自动消除掉,当然你也可以直接到注册表中删除对应xx.inf中列出的键值的项。

十、升级

只要在源代码中更改xx.rc文件中对应的那些1.0.0.1为你的新版本号,并同时更改你调用控件的web上的版本号就可以了,下一次客户访问这个页面时会自动提示安装新控件,新控件会覆盖就版本的控件。

以上仅供参考,本人也是新手,最近工作需要用控件才能完成一些功能,以上包含了我开发过程中碰到的诸多问题,希望对所有人能有所帮助