VC ActiveX插件开发
全文参考:组件开发:http://www.cnblogs.com/phinecos/archive/2008/07/25/1251743.html
安全接口:http://www.cnblogs.com/phinecos/archive/2008/08/07/1263270.html
http://blog.csdn.net/isadream/archive/2008/05/14/2445493.aspx
签名:http://hi.baidu.com/ipeter/blog/item/5bfa75f08f878bc67831aa08.html
免费数字证书:http://blog.csdn.net/Mobidogs/archive/2008/01/23/2062040.aspx
CSDN打包:http://support.microsoft.com/kb/167158
CSDN安全接口:http://support.microsoft.com/kb/161873/en-us
一、
确定目标:
二、使用VS 2005 MFC ActiveX Ctronl进行开发。
三、
创建工程步骤:
1、打开VS2005,选择-》new project-》VC++->MFC ActiveX
Controll如下图:
图1
2、 选择OK-》NEXT出现:
图2
3、选中Run-time license项,再点击NEXT-》NEXT出现如下对话框:
图3
我们选择AcitveX when visible 和 fisker-free activeation,不需要选择:has an
about box
dialog,如果你想要该项则选中它。最后点击FINISH,我们在这里就完成了ActiveX插件的创建过程,该插件为空,使用VS自带工具ActiveX
Control test container里测试只显示一个空圆。
四、
创建对话框:
在创建完ActiveX后,我们可以看到工程里包含以下几个文件:
1)CTestActiveXApp:这是ActiveX应用程序类,从COleControlModule类继承下来的。它是OLE控件模块对象继承自的基类,包含了初始化(InitInstance)和清理(ExitInstance)的代码
2)CTestActiveXCtrl:从COleControl继承而来,这里是我们实现控件大部分功能的地方。
3)CTestActiveXPropPage:从COlePropertyPage继承而来,用于管理控件的属性页对话框。向导已经为我们创建了一个默认的对话框来作为控件的属性页对话框。
此处,我们不使用向导创建的对话框(也可使用,为了更好让各位了解方法,采用新建对话框方式 )。
1、 插入对话框:
选择Resource View右键单击Dialog项目选择-》insert
dialog
在属性页里我们更改对话ID为IDD_MAIN_DIALOG, 更改属性:Border—none,
Style – Child, System Menu – False, Visible –
True.这里我们就已经插入了一个对话。
2、 为对话框添加类
右键IDD_MAIN_DIALOG对话框空白处-》Add Class,我们为对话框添加类:CMainDlg,Base
Class选择:CDialog点击FINISH即完成了添加类过程。
3、 显示对话框:
在以上我们添加的对话框在我们测试时它不会显示出来,我们还需要以下过程 :
在CTestActiveXCtrl类中添加头文件#include”MainDlg.h”并添加变量CMainDlg
m_pMainDlg;
为CTestActiveXCtrl类添加WM_CREATE消息,并添加以下内容:
int
CMyActiveXCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (COleControl::OnCreate(lpCreateStruct) ==
-1)
return -1;
//
TODO: Add your specialized creation code
here
m_MainDlg.Create(IDD_MAIN_DIALOG, this);
return 0;
}
在OnDrawn函数中我们需移动对话位置以让它显示出来 :
void CMyActiveXCtrl::OnDraw(
CDC* pdc,
const CRect& rcBounds, const CRect&
rcInvalid)
{
DoSuperclassPaint(pdc, rcBounds);
m_MainDlg.MoveWindow(rcBounds, TRUE);
CBrush
brBackGnd(TranslateColor(AmbientBackColor()));
pdc->FillRect(rcBounds,
&brBackGnd);
}
编译:修改project属性:
我们将use of
mfc改为静态库连接,选择Release编译,我们就可得到TestActiveX.ocx文件。这就是我们开发的插件了。
到这里一个简单的ActiveX开发已经完毕,我们使用VS自带工具ActiveX Control test
container测试可发现可显示出一个对话框。
注:本机注册组件方法:
Regsvr32
桌面/TestActiveX\Release\TestAtiveX.ocx即可注册,在注册表里我们可以找到相应CLASSID
五、
在网页中使用此ActiveX:
开发至此,我们将学习在网页里使用ActiveX,可以使用微软的 ActiveX
Control
Pad(点击下载)。要利用它在Web页面中插入一个ActiveX控件,在<BODY>标记中右键,选择“Insert
ActiveX Control”,选择你需要的就可以了。
图4
图5
我们更改为<object>标签添加codebase属性
<object
id=”MyActiveX1”width=350 height=50
classid=”CLSID:36299202-09ef-4abf-adb9-47c599dbe778”
codebase=http://192.168.1.12/dd/ocx/TestActiveX.ocx#version=1,0,0,2>//客户端可根据//CODEBASE路径属性下载插件安装
……………..
</object>
至此网页容器开发完毕,我们在IIS或本地浏览将可看到对话显示出来 。
但至此ActiveX控件并末开发完毕,我们还需为其添加安全接口和数字签名。
六、
添加安全接口:
在客户端浏览器ActiveX容器时,我们可看到会弹出窗口:
下面我们介绍将其定义为安全接口 :
参考:MSDN帮助http://support.microsoft.com/kb/161873/en-us
在APP里参照以下进行更改即可。
CMyActiveXApp theApp;
#include "strsafe.h"
#include
<comcat.h>
#include
<objsafe.h>
//需要包含这三个头文件
//
本控件的CLSID,注册表用
const GUID CDECL BASED_CODE _tlid =
{ 0x6a7e4bf6, 0xc523, 0x479d, { 0xbe, 0xac, 0x98, 0xce, 0xc2, 0x1,
0x2, 0x33 } }; //带version(1.0)字段,在工程里ODL文件中获取[
uuid(6A7E4BF6-C523-479D-BEAC-98CEC2010233), version(1.0),
helpfile("MyActiveX.hlp"),helpstring("MyActiveX ActiveX Control
module"),control ]
// 版本控制
const WORD _wVerMajor =
1;
// 次版本号
const WORD _wVerMinor =
0;
const CATID
CATID_SafeForScripting
=
{0x7dd95801,0x9882,0x11cf,{0x9f,0xa9,0x00,0xaa,0x00,0x6c,0x42,0xc4}};//此段无需更改
const CATID CATID_SafeForInitializing =
{0x7dd95802,0x9882,0x11cf,{0x9f,0xa9,0x00,0xaa,0x00,0x6c,0x42,0xc4}};//此段无需更改
const CATID CLSID_SafeItem =
{0xABAD1B64,0xCD91,0x4839,{0xAB,0xE6,0xBA,0xE8,0x2C,0xC3,0xE6,0xF7}};//在工程里ODL文件中获取后带control字段,为本控件的注册CLASSID。[
uuid(ABAD1B64-CD91-4839-ABE6-BAE82CC3E6F7),helpstring("MyActiveX
Control"), control ]
////////////////////////////////////////////////////////////////////////////
// CMyActiveXApp::InitInstance - DLL
initialization
BOOL CMyActiveXApp::InitInstance()
{
BOOL bInit = COleControlModule::InitInstance();
if
(bInit)
{
}
return
bInit;
}
////////////////////////////////////////////////////////////////////////////
// CMyActiveXApp::ExitInstance - DLL
termination
int CMyActiveXApp::ExitInstance()
{
// TODO: Add your own module termination code here.
return COleControlModule::ExitInstance();
}
/////////////////////////////////////////////////////////////////////////////
// 创建组件种类
HRESULT CreateComponentCategory(CATID catid, CHAR
*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
size_t
len;
// Make sure
the provided description is not too long.
// Only copy
the first 127 characters if it is.
// The
second parameter of StringCchLength is the maximum
// number of
characters that may be read into catDescription.
// There
must be room for a NULL-terminator. The third parameter
// contains
the number of characters excluding the NULL-terminator.
hr =
StringCchLength(catDescription, STRSAFE_MAX_CCH,
&len);
if
(SUCCEEDED(hr))
{
if (len>127)
{
len = 127;
}
}
else
{
// TODO: Write an error handler;
}
// The
second parameter of StringCchCopy is 128 because you need
// room for
a NULL-terminator.
hr =
StringCchCopy(COLE2T(catinfo.szDescription), len + 1,
catDescription);
// Make sure
the description is null terminated.
catinfo.szDescription[len + 1] = '\0';
hr =
pcr->RegisterCategories(1,
&catinfo);
pcr->Release();
return
hr;
}
//
Register your component categories information
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 - Remove
entries from the registry
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);
// Mark the
control as safe for initializing.
hr =
CreateComponentCategory(CATID_SafeForInitializing,
_T("Controls safely initializable from persistent data!"));
if
(FAILED(hr))
return hr;
hr =
RegisterCLSIDInCategory(CLSID_SafeItem,
CATID_SafeForInitializing);
if
(FAILED(hr))
return hr;
// Mark the
control as safe for scripting.
hr =
CreateComponentCategory(CATID_SafeForScripting,
_T("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);
// Remove
entries from the registry.
hr=UnRegisterCLSIDInCategory(CLSID_SafeItem,
CATID_SafeForInitializing);
if
(FAILED(hr))
return hr;
hr=UnRegisterCLSIDInCategory(CLSID_SafeItem,
CATID_SafeForScripting);
if
(FAILED(hr))
return hr;
if
(!AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor))
return ResultFromScode(SELFREG_E_TYPELIB);
if
(!COleObjectFactoryEx::UpdateRegistryAll(FALSE))
return ResultFromScode(SELFREG_E_CLASS);
return
NOERROR;
}
至此,我们已对控件进行安全接口定义,WINDOWS系统将可识别其为安全脚本。
但在IE6以上版本对AcitveX进行了约束,我们需要对其添加数字签名才能被客户下载。
六、数字签名:
在VS里有附带makecert.exe工具可产生测试证书,并此证书并不能在互联使用,我们需要一个正版数字证书,不过大部分需要钱。
数字签名:
在VS里有个签名工具signtool(VC6里为signcode)在VS 命令行里我们输入 signtool
signwizard可弹出签名向导,我们只需按步骤即可完成签名。
有问题联系 QQ:574781136
email:johin.123@hotmail.com
|