首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > Web前端 >

DLL+ ActiveX控件+WEB页面调用事例

2012-08-02 
DLL+ ActiveX控件+WEB页面调用例子一、 概述?因项目需要,开始学习并研究VC、DLL及ActiveX控件,网上资料找了

DLL+ ActiveX控件+WEB页面调用例子

一、 概述?
因项目需要,开始学习并研究VC、DLL及ActiveX控件,网上资料找了很多,但没一个可用的或者说没一个例子可理解并运行的。没办法,自己研究吧。功夫不负有心人,终有小成了,呵呵,现在把自己学习总结了一下,献给需要的人。?
DLL(动态链接库): 分WIN32 DLL和MFC DLL?
ActiveX:分ATL控件和MFC控件两类(也是一个DLL)?
WEB:JAVASCRIPT 调用-> ActiveX调用-> DLL 完成加法运算并返回值,在页面上显示。?
二、开发(VS2008)?
1、DLL 库编写:?
文件-》新建-》WIN32控制台->填写项目名称-》选择DLL-》空项目-》完成。?
(1)在解决方案面板中,加入一个头文件testdll.h,内容:?
复制代码代码如下:
#ifndef _DLLTUT_DLL_H_?
#define _DLLTUT_DLL_H_?
#if defined DLL_EXPORT?
#define DECLDIR __declspec(dllexport)?
#else?
#define DECLDIR __declspec(dllimport)?
#endif?
//extern "C"告诉编译器该部分可以在C/C++中使用。?
extern "C"?
{?
DECLDIR int Add( int a, int b );?
DECLDIR void Function( void );?
}?
#endif?

(2)在解决方案面板中,加入一个实现文件testdll.cpp,内容:?
复制代码代码如下:
#include <iostream>?
#define DLL_EXPORT?
#include "testdll.h"?
extern "C"?
{?
// 这里主要用到 ADD 方法。?
DECLDIR int Add( int a, int b )?
{?
return( a + b );?
}?
DECLDIR void Function( void )?
{?
std::cout << "DLL Called!" << std::endl;?
}?
}?

(3)可选。新建一个WIN32控制台类,测试这个DLL。?
文件-》新建-》WIN32控制台->填写项目名称-》选择控制台程序-》空项目-》完成。?
在解决方案面板中,加入一个实现文件loaddll.cpp 内容:?
复制代码代码如下:
#include <iostream>?
#include <windows.h>?
using namespace std;?
typedef int (*AddFunc)(int,int); //定义指针函数、接口。?
typedef void (*FunctionFunc)();?
int main()?
{?
AddFunc _AddFunc;?
FunctionFunc _FunctionFunc;?
cout <<"---获取DLL---."<< endl;?
// L 表示使用UNICODE 字符集,要和项目的字符集保持一致。?
HINSTANCE hInstLibrary = LoadLibrary(L"E:\\Project\\VS\\LoadDll\\Release\\TestDll.dll");?
if (hInstLibrary == NULL)?
{?
cout <<"Dll 加载【失败】."<< endl;?
FreeLibrary(hInstLibrary);?
}else{?
cout <<"Dll 加载【成功】."<< endl;?
}?
_AddFunc = (AddFunc)GetProcAddress(hInstLibrary, "Add");?
_FunctionFunc = (FunctionFunc)GetProcAddress(hInstLibrary, "Function");?
if ((_AddFunc == NULL) || (_FunctionFunc == NULL))?
{?
FreeLibrary(hInstLibrary);//释放?
}else{?
cout <<"---获取DLL函数【OK】---."<< endl;?
}?
cout << _AddFunc(1, 1) << endl; // 开始调用?
_FunctionFunc(); //?
cin.get(); // 获得焦点,这样就不会程序就不会一闪而过了。?
FreeLibrary(hInstLibrary);//调用完后,要释放内存。?
return(1);?
}?

2、ActiveX 控件实现:?
这里我们选择ATL控件实现,而非MFC ActiveX。?
文件-》新建-》ATL项目->填写项目名称(“FROMYANTAI”)-》选择动态链接库(DLL)-》完成。?
完成后,会在右边“解决方案资源管理器”生成很多头H文件和CPP实现文件,这些都是默认的不要修改。?
(1)、添加一个ALT简单对象:鼠标邮件点击项目名称(刚才起的名字)选择-》添加类-》选择ATL简单对象。?
下一步起一个名字:“ytiicrj”—》下一步:其他不变,在支持中,选择“连接点”和“IE对象支持”—》完成。?
下一步给“ytiicrj”添加一个方法,以便WEB页面调用。在“类视图”选择“iytiicrj”(有个灰色的钥匙图标)鼠标右键添加-》添加方法。方法起名为“GetContent”-》参数属性选择IN,参数类型选择LONG 参数名 A –》添加;继续;参数属性选择IN,参数类型选择LONG 参数名 B –》添加;继续;参数属性选择OUT和RETVAL ,参数类型选择LONG* 参数名 out –》添加---》 点击完成。?
这样就在ytiicrj.H头文件中添加了一个(在最后一行):?
STDMETHOD(GetContent)(LONG a, LONG b, LONG* out);?
并在ytiicrj.CPP文件中添加了一个实现类:?
复制代码代码如下:
STDMETHODIMP CCaluNumCtrl::GetContent(LONG a, LONG b, LONG* out)?
{?
// TODO: 在此添加实现代码?
return S_OK;?
}?

(2)、在ytiicrj.H 文件中,调用DLL类库。代码如下:?
// CaluNumCtrl.h : ytiicrj 的声明 黑体(粗体)部分是具体的实现,其他未动。?
复制代码代码如下:
#pragma once?
#include "resource.h" // 主符号?
#include <windows.h> //添加?
#include "AtlActiveX_i.h"?
#include "_ICaluNumCtrlEvents_CP.h"?
#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)?
#error "Windows CE 平台(如不提供完全DCOM 支持的Windows Mobile 平台)上无法正确支持单线程COM 对象。定义_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA 可强制ATL 支持创建单线程COM 对象实现并允许使用其单线程COM 对象实现。rgs 文件中的线程模型已被设置为“Free”,原因是该模型是非DCOM Windows CE 平台支持的唯一线程模型。"?
#endif?
// ytiicrj?
class ATL_NO_VTABLE Cytiicrj :?
//增加一下一行:安全提示解除,--当运行浏览器调用时,不会提示安全问题。?
public IObjectSafetyImpl<Cytiicrj, INTERFACESAFE_FOR_UNTRUSTED_CALLER| INTERFACESAFE_FOR_UNTRUSTED_DATA>,?
public CComObjectRootEx<CComSingleThreadModel>,?
public CComCoClass<Cytiicrj, &CLSID_CaluNumCtrl>,?
public IConnectionPointContainerImpl<Cytiicrj>,?
public CProxy_ICaluNumCtrlEvents<Cytiicrj>,?
public IObjectWithSiteImpl<Cytiicrj>,?
public IDispatchImpl<ICaluNumCtrl, &IID_ICaluNumCtrl, &LIBID_AtlActiveXLib, 1, 0>?
{?
public:?
//以下三行实现定义。?
typedef int (*AddFunc)(int,int); //类型定义,对应DLL ADD方法。Func自定义,随便写。?
HINSTANCE hInstLibrary;?
AddFunc _AddFunc; //类映射?
Cytiicrj()?
{?
//开始调用DLL,进行计算。?
hInstLibrary = LoadLibrary(L"TestDll.dll");//把写好的DLL文件放在此项目生成的目录下?
if (hInstLibrary == NULL)?
{?
FreeLibrary(hInstLibrary);//资源释放?
}else{?
}?
//调用方法,返回方法句柄。?
_AddFunc = (AddFunc)GetProcAddress(hInstLibrary, "Add");?
}?
DECLARE_REGISTRY_RESOURCEID(IDR_CALUNUMCTRL)?
BEGIN_COM_MAP(Cytiicrj)?
COM_INTERFACE_ENTRY(ICaluNumCtrl)?
COM_INTERFACE_ENTRY(IDispatch)?
COM_INTERFACE_ENTRY(IConnectionPointContainer)?
COM_INTERFACE_ENTRY(IObjectWithSite)?
//增加一下一行:安全提示解除,--当运行浏览器调用时,不会提示安全问题。?
COM_INTERFACE_ENTRY(IObjectSafety)?
END_COM_MAP()?
BEGIN_CONNECTION_POINT_MAP(Cytiicrj)?
CONNECTION_POINT_ENTRY(__uuidof(_ICaluNumCtrlEvents))?
END_CONNECTION_POINT_MAP()?
DECLARE_PROTECT_FINAL_CONSTRUCT()?
HRESULT FinalConstruct()?
{?
return S_OK;?
}?
void FinalRelease()?
{?
FreeLibrary(hInstLibrary);?
}?
public:?
STDMETHOD(GetContent)(LONG a, LONG b, LONG* out);?
};?
OBJECT_ENTRY_AUTO(__uuidof(CaluNumCtrl), Cytiicrj)?

(3)、回到在ytiicrj.PP 文件中,添加实现代码如下:?
复制代码代码如下:
STDMETHODIMP CCaluNumCtrl::GetContent(LONG a, LONG b, LONG* out)?
{?
// TODO: 在此添加实现代码?
int sum = this->_AddFunc(static_cast<int>(a),static_cast<int>(b));?
*out = static_cast<LONG>(sum);?
this->_AtlFinalRelease();?
return S_OK;?
}?

(4)、生成DLL:?
这步很简单,选择 Release模式,点击项目进行生成(会提示选择REG32注册,那就选择被)。这样就在Release目录下生成了很多文件,我们要的就是一个DLL文件。?
3、DLL和 ATL ActiveX 控件DLL 打包为CAB文件:?
例如:生成test.CAB后,WEB页面就会提示下载安装。?
(1)首先定义setup.inf文件:它描述了下载的内容和目标目录还有版本号及相应的DLL文件。这个要手动编写的,我的内容如下(对应名称自行修改吧):?
复制代码代码如下:
[version]?
; version signature (same for both NT and Win95) do not remove?
signature="$CHICAGO$"?
AdvancedINF=2.0?
[Add.Code]?
AtlActiveX.dll=AtlActiveX.dll?
TestDll.dll=TestDll.dll?
setup.inf=setup.inf?
[install.files]?
AtlActiveX.dll=AtlActiveX.dll?
TestDll.dll=TestDll.dll?
setup.inf=setup.inf?
[AtlActiveX.dll]?
clsid={4AE870B5-C7FB-4171-A47E-7F57AFD86F67}?
file-win32-x86=thiscab?
FileVersion=1,0,0,1?
DestDir=11?
RegisterServer=yes?
[TestDll.dll]?
file-win32-x86=thiscab?
DestDir=11?
FileVersion=1,0,0,1?
RegisterServer=yes?
[setup.inf]?
file=thiscab?
[RegisterFiles]?
%11%\AtlActiveX.dll?
; end of INF file?

(2)整合资源:?
将所用到的DLL全部放到一个目录下包括setup.inf文件,然后在开始运行:IExpress 命令去生成CAB包。?
运行后,选择第一个,下一步,选择第三个,下一步,添加文件(选择你的DLL和INF文件),下一步,选择一个输出目录并创建一个CAB文件名,再选择第二个选项,下一步,选择第二个选项,然后OK。这样就生成了一个CAB文件。?
(3)WEB页面调用 ActiveX 控件 进行加法运算 :?
写一个test.htm网页和CAB文件放在一个目录,test.htm内容如下:?
复制代码代码如下:
<HTML>?
<HEAD>?
<TITLE>New Page</TITLE>?
<OBJECT id=CaluNumCtrl align="CENTER" WIDTH=0 HEIGHT=0 codeBase="test.CAB#version=9,0,0,1" classid="CLSID:B6D4B406-9CC4-4C80-B7A2-248BBB07F682"></OBJECT>?
<script language="javascript">?
function doTest()?
{?
var sum = CaluNumCtrl.GetContent(1,1);?
alert(sum);?
}?
</script>?
</HEAD>?
<BODY>?
<input type="button" value="renjie" id="btnOK" onclick="doTest();"></input>?
</BODY>?
</HTML>?

说明: codeBase="test.CAB#version=9,0,0,1" codeBase表示文件相对或者绝对路径;version表示版本号,如果这个号和INF文件的版本号一样,那么第二次访问页面就不会下载,否则每次都下载。CLSID 是 ActiveX 项目生成的序号,具体可以在项目的*.rgs 文件中找到。?
好了。所有的步骤都完成了,这时你运行test.htm,提示ActiveX控件,你选择允许,然后就可以调用加法运算了。?
这只是一个简单的例子,在其中的DLL中,你可以实现自己的应用了。

热点排行