【转】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_ 
/*使用__declspec,一个Microsoft定义的关键字,实现函数的对外调用。也可以创建一个模块定义文件(Module-Definition File即.DEF),其效果都一样。前者简单些。*/ 
#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);  

/* 
简单说明: 
一个HINSTANCE是一个Windows数据类型:是一个实例的句柄;在此情况下,这个实例将是这个DLL。你可以通过使用函数LoadLibrary()获得DLL的实例,它获得一个名称作为参数。在调用LoadLibrary函数后,你必需查看一下函数返回是否成功。你可以通过检查HINSTANCE是否等于NULL(在Windows.h中定义为0或Windows.h包含的一个头文件)来查看其是否成功。如果其等于NULL,该句柄将是无效的,并且你必需释放这个库。换句话说,你必需释放DLL获得的内存。如果函数返回成功,你的HINSTANCE就包含了指向DLL的句柄。 
一旦你获得了指向DLL的句柄,你现在可以从DLL中重新获得函数。为了这样作,你必须使用函数GetProcAddress(),它将DLL的句柄(你可以使用HINSTANCE)和函数的名称作为参数。你可以让函数指针获得由GetProcAddress()返回的值,同时你必需将GetProcAddress()转换为那个函数定义的函数指针。举个例子,对于Add()函数,你必需将GetProcAddress()转换为AddFunc;这就是它知道参数及返回值的原因。现在,最好先确定函数指针是否等于NULL以及它们拥有DLL的函数。这只是一个简单的if语句;如果其中一个等于NULL,你必需如前所述释放库。 
*/ 
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, /*wMajor =*/ 1, /*wMinor =*/ 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" οnclick="doTest();"></input> 
</BODY> 
</HTML> 
  
说明:  codeBase="test.CAB#version=9,0,0,1"  codeBase表示文件相对或者绝对路径;version表示版本号,如果这个号和INF文件的版本号一样,那么第二次访问页面就不会下载,否则每次都下载。CLSID 是 ActiveX 项目生成的序号,具体可以在项目的*.rgs 文件中找到。   
  
好了。所有的步骤都完成了,这时你运行test.htm,提示ActiveX控件,你选择允许,然后就可以调用加法运算了。 
这只是一个简单的例子,在其中的DLL中,你可以实现自己的应用了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值