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


Posted in Javascript onAugust 07, 2010

一、 概述
因项目需要,开始学习并研究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中,你可以实现自己的应用了。
Javascript 相关文章推荐
使用Javascript和DOM Interfaces来处理HTML
Oct 09 Javascript
Prototype最新版(1.5 rc2)使用指南(1)
Jan 10 Javascript
javascript Keycode对照表
Oct 24 Javascript
jquery实现在页面加载完毕后获取图片高度或宽度
Jun 16 Javascript
基于zepto.js实现仿手机QQ空间的大图查看组件ImageView.js详解
Mar 05 Javascript
jQuery根据用户电脑是mac还是pc加载对应样式的方法
Jun 26 Javascript
javascript获取select值的方法分析
Jul 02 Javascript
AngularJS ng-mousedown 指令
Aug 02 Javascript
vux uploader 图片上传组件的安装使用方法
May 15 Javascript
在vue中使用echarts图表实例代码详解
Oct 22 Javascript
javaScript把其它类型转换为Number类型
Oct 13 Javascript
vue实现登录、注册、退出、跳转等功能
Dec 23 Vue.js
JavaScript中继承的一些示例方法与属性参考
Aug 07 #Javascript
javascript 防止刷新,后退,关闭
Aug 07 #Javascript
纯CSS打造的导航菜单(附jquery版)
Aug 07 #Javascript
基于jquery的商品展示放大镜
Aug 07 #Javascript
jquery autocomplete自动完成插件的的使用方法
Aug 07 #Javascript
jQuery的实现原理的模拟代码 -5 Ajax
Aug 07 #Javascript
javascript new fun的执行过程
Aug 05 #Javascript
You might like
用PHP代码给图片加水印
2015/07/01 PHP
php获取图片信息的方法详解
2015/12/10 PHP
JavaScript数组函数unshift、shift、pop、push使用实例
2014/08/27 Javascript
JS动态修改图片的URL(src)的方法
2015/04/01 Javascript
简介JavaScript中的sub()方法的使用
2015/06/08 Javascript
jQuery插件datepicker 日期连续选择
2015/06/12 Javascript
详解JavaScript中的异常处理方法
2015/06/16 Javascript
JQuery+Ajax实现数据查询、排序和分页功能
2015/09/27 Javascript
小心!AngularJS结合RequireJS做文件合并压缩的那些坑
2016/01/09 Javascript
Ionic实现页面下拉刷新(ion-refresher)功能代码
2016/06/03 Javascript
JavaScript事件学习小结(三)js事件对象
2016/06/09 Javascript
jQuery实现的自动加载页面功能示例
2016/09/04 Javascript
jQuery Form表单取值的方法
2017/01/11 Javascript
jquery mobile移动端幻灯片滑动切换效果
2020/04/15 Javascript
AngularJS读取JSON及XML文件的方法示例
2017/05/25 Javascript
微信小程序 蓝牙的实现实例代码
2017/06/27 Javascript
浅谈angular.js跨域post解决方案
2017/08/30 Javascript
JS实现的数组去除重复数据算法小结
2017/11/17 Javascript
解决vue+element 键盘回车事件导致页面刷新的问题
2018/08/25 Javascript
用图片替换checkbox原始样式并实现同样的功能
2018/11/15 Javascript
jQuery实现电梯导航模块
2020/12/22 jQuery
本地文件上传到七牛云服务器示例(七牛云存储)
2014/01/11 Python
浅析Python中的join()方法的使用
2015/05/19 Python
Python Series从0开始索引的方法
2018/11/06 Python
Python字符串的常见操作实例小结
2019/04/08 Python
python禁用键鼠与提权代码实例
2019/08/16 Python
Tensorflow 使用pb文件保存(恢复)模型计算图和参数实例详解
2020/02/11 Python
Jmeter HTTPS接口测试证书导入过程图解
2020/07/22 Python
英国轻奢珠宝品牌:Astley Clarke
2016/12/18 全球购物
俄罗斯在线购买飞机票、火车票、巴士票网站:Tutu.ru
2020/03/16 全球购物
规范化管理年活动总结
2014/08/29 职场文书
员工工作及收入证明
2014/10/28 职场文书
刮痧观后感
2015/06/05 职场文书
Golang二维数组的使用方式
2021/05/28 Golang
MySQL 那些常见的错误设计规范,你都知道吗
2021/07/16 MySQL
vue使用watch监听属性变化
2022/04/30 Vue.js