VS2005 C++ 开发ActiveX控件

来源:互联网 发布:淘宝多少个好评一个钻 编辑:程序博客网 时间:2024/06/13 05:58

 

VS2005 C++ 开发ActiveX控件

simpleboy 2013/8/20整理 simpleboy2008@163.com

ActiveX在网页开发中经常得到应用,基本的开发步骤为:

第一步:开发ActiveX控件

第二步:在网页中通过JavaScript调用ActiveX控件

第三步:通过浏览器使用ActiveX控件

下面给出具体的例子

一、开发ActiveX控件

在VS2005中,使用编程向导,选择MFC ActiveX控件,如下图所示。

缺省完成即可。

然后类视图中的TaxLib类中添加控件的处理函数,添加的函数返回类型是LONG,一个输入参数num的类型是LONG,添加过程以及添加效果如下图所示。

 

其中的AddOne是刚才添加的控件处理方法,AboutBox方法是缺省条件下开发工具自动生成的。后面的使用就可以使用这两个方法来实验了。

双击AddOne函数就可以看到函数定义了,代码如下(对应的文件名为Tax.idl):

// Tax.idl : ActiveX 控件项目的类型库源。

 

// 此文件将由MIDL编译器工具处理以

// 产生类型库(Tax.tlb),该类型库将成为

// Tax.ocx 中的资源。

 

#include <olectl.h>

#include <idispids.h>

 

[ uuid(DC2A37EC-649B-42E9-8243-4EA232ED1C77),version(1.0),

  helpfile("Tax.hlp"),

  helpstring("Tax ActiveX控件模块"),

  control ]

library TaxLib

{

     importlib(STDOLE_TLB);

 

     //  CTaxCtrl 的主调度接口

 

     [ uuid(CC389683-C147-490B-88DA-BF57022A615D),

       helpstring("Tax Control的调度接口")]

     dispinterface _DTax

     {

         properties:

         methods:

 

              [id(DISPID_ABOUTBOX)]void AboutBox();

              [id(1), helpstring("方法AddOne")] LONG AddOne(LONG num);

     };

 

     //  CTaxCtrl 的事件调度接口

 

     [ uuid(10F7C381-1316-439D-BAE6-8C3D2221185D),

       helpstring("Tax Control的事件接口") ]

     dispinterface _DTaxEvents

     {

         properties:

              //  事件接口没有任何属性

 

         methods:

     };

 

     //  CTaxCtrl 的类信息

 

     [ uuid(D3C5CECF-26AA-46FD-945A-1D73C1DA06CC),

       helpstring("Tax Control"),control ]

     coclass Tax

     {

         [default] dispinterface _DTax;

         [default, source] dispinterface _DTaxEvents;

     };

 

};

 

这里要特别提醒一下,在控件使用的时候,需要一个控件编号,在TaxLib属性中看到的uuid号码对应的是Tax.idl文件中出现的第一个号码“DC2A37EC-649B-42E9-8243-4EA232ED1C77”,很多时候大家会使用这个号码作为控件编号,这是不对的,对的号码是类信息中的号码,即最后一个号码“D3C5CECF-26AA-46FD-945A-1D73C1DA06CC”。

控件处理函数在TaxCtrl.cpp文件中实现,代码如下:

// TaxCtrl.cpp : CTaxCtrl ActiveX控件类的实现。

 

#include"stdafx.h"

#include"Tax.h"

#include"TaxCtrl.h"

#include"TaxPropPage.h"

 

#ifdef _DEBUG

#definenew DEBUG_NEW

#endif

 

IMPLEMENT_DYNCREATE(CTaxCtrl, COleControl)

 

// 消息映射

 

BEGIN_MESSAGE_MAP(CTaxCtrl, COleControl)

    ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)

END_MESSAGE_MAP()

 

 

// 调度映射

 

BEGIN_DISPATCH_MAP(CTaxCtrl, COleControl)

    DISP_FUNCTION_ID(CTaxCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)

    DISP_FUNCTION_ID(CTaxCtrl, "AddOne", dispidAddOne, AddOne, VT_I4, VTS_I4)

END_DISPATCH_MAP()

 

// 事件映射

 

BEGIN_EVENT_MAP(CTaxCtrl, COleControl)

END_EVENT_MAP()

 

// 属性页

 

// TODO: 按需要添加更多属性页。请记住增加计数!

BEGIN_PROPPAGEIDS(CTaxCtrl, 1)

    PROPPAGEID(CTaxPropPage::guid)

END_PROPPAGEIDS(CTaxCtrl)

 

// 初始化类工厂和guid

 

IMPLEMENT_OLECREATE_EX(CTaxCtrl, "TAX.TaxCtrl.1",

    0xd3c5cecf, 0x26aa, 0x46fd, 0x94, 0x5a, 0x1d, 0x73, 0xc1, 0xda, 0x6, 0xcc)

 

// 键入库ID 和版本

 

IMPLEMENT_OLETYPELIB(CTaxCtrl, _tlid, _wVerMajor, _wVerMinor)

 

// 接口ID

 

const IID BASED_CODE IID_DTax =

        { 0xCC389683, 0xC147, 0x490B, { 0x88, 0xDA, 0xBF, 0x57, 0x2, 0x2A, 0x61, 0x5D } };

const IID BASED_CODE IID_DTaxEvents =

        { 0x10F7C381, 0x1316, 0x439D, { 0xBA, 0xE6, 0x8C, 0x3D, 0x22, 0x21, 0x18, 0x5D } };

 

// 控件类型信息

 

staticconst DWORD BASED_CODE _dwTaxOleMisc =

    OLEMISC_ACTIVATEWHENVISIBLE |

    OLEMISC_SETCLIENTSITEFIRST |

    OLEMISC_INSIDEOUT |

    OLEMISC_CANTLINKINSIDE |

    OLEMISC_RECOMPOSEONRESIZE;

 

IMPLEMENT_OLECTLTYPE(CTaxCtrl, IDS_TAX, _dwTaxOleMisc)

 

// CTaxCtrl::CTaxCtrlFactory::UpdateRegistry -

// 添加或移除CTaxCtrl 的系统注册表项

 

BOOL CTaxCtrl::CTaxCtrlFactory::UpdateRegistry(BOOL bRegister)

{

    // TODO:验证您的控件是否符合单元模型线程处理规则。

    // 有关更多信息,请参考MFC 技术说明64。

    // 如果您的控件不符合单元模型规则,则

    // 必须修改如下代码,将第六个参数从

    // afxRegApartmentThreading改为0

 

    if (bRegister)

        return AfxOleRegisterControlClass(

            AfxGetInstanceHandle(),

            m_clsid,

            m_lpszProgID,

            IDS_TAX,

            IDB_TAX,

            afxRegApartmentThreading,

            _dwTaxOleMisc,

            _tlid,

            _wVerMajor,

            _wVerMinor);

    else

        return AfxOleUnregisterClass(m_clsid, m_lpszProgID);

}

 

// CTaxCtrl::CTaxCtrl -构造函数

 

CTaxCtrl::CTaxCtrl()

{

    InitializeIIDs(&IID_DTax, &IID_DTaxEvents);

    // TODO:在此初始化控件的实例数据。

}

 

// CTaxCtrl::~CTaxCtrl -析构函数

 

CTaxCtrl::~CTaxCtrl()

{

    // TODO:在此清理控件的实例数据。

}

 

// CTaxCtrl::OnDraw -绘图函数

 

void CTaxCtrl::OnDraw(

            CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)

{

    if (!pdc)

        return;

 

    // TODO:用您自己的绘图代码替换下面的代码。

    pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));

    pdc->Ellipse(rcBounds);

}

 

// CTaxCtrl::DoPropExchange -持久性支持

 

void CTaxCtrl::DoPropExchange(CPropExchange* pPX)

{

    ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));

    COleControl::DoPropExchange(pPX);

 

    // TODO:为每个持久的自定义属性调用PX_ 函数。

}

 

// CTaxCtrl::OnResetState -将控件重置为默认状态

 

void CTaxCtrl::OnResetState()

{

    COleControl::OnResetState();  // 重置DoPropExchange 中找到的默认值

 

    // TODO:在此重置任意其他控件状态。

}

 

// CTaxCtrl::AboutBox -向用户显示关于

 

void CTaxCtrl::AboutBox()

{

    CDialog dlgAbout(IDD_ABOUTBOX_TAX);

    dlgAbout.DoModal();

}

 

// CTaxCtrl消息处理程序

 

LONG CTaxCtrl::AddOne(LONG num)

{

    AFX_MANAGE_STATE(AfxGetStaticModuleState());

 

    // TODO:在此添加调度处理程序代码

 

    return num+1;

}

 

从代码中可以看出AboutBox函数会弹出一个关于的对话框,而AddOne则返回输入整数加1,代码编译后,如果没有出错,则可以得到控件Tax.ocx了,如下图所示。

可以使用VS2005自带的工具测试控件的功能,如下图所示。

在测试容器中插入新控件,选择刚才编译好的控件(注意:编译好的控件自动会添加到测试容器中,开发人员不需要添加),如下图所示。

 

出现一个椭圆形,表示控件已经装载,可以进行测试了。我们这里只是测试控件的方法是否可以正常调用。如下图所示。

   

在方法名下拉列表中,就是控件的两个调用方法,先调用AboutBox方法,这个方法不需要输入参数,直接点调用即可,效果如下图所示。

AddOne方法调用需要输入参数num,在参数位置输入整数3并点设置值,然后点调用,可以看到返回值是整数4,即函数执行成功,输入参数以及执行效果如下图所示。

通过控件容器测试,说明控件没有任何问题,下面就是控件的使用问题。

二、使用JavaScript调用ActiveX控件

有很多方法可以调用ActiveX控件,这里选择在JavaScript中调用ActiveX控件。

编辑一个HTML文档,名字为t.html,编辑内容如下:

<html>

<head>

<title>ActiveX控件Demo</title>

<OBJECT id="L" classid="CLSID:D3C5CECF-26AA-46FD-945A-1D73C1DA06CC"></OBJECT>

</head>

<body>

<input id="Button1" type="button" value="执行函数" onclick="javascript:RunFunc();" />

<input id="Button3" type="button" value="关于" onclick="javascript:About();" />

<hr color="blue">

</body>

</html>

<script language="javascript">

 <!--

function RunFunc()

{

var lNum = L.AddOne(9);

alert("9+1 = "+lNum);

}

function About()

{

 L.AboutBox();

}

// -->

</script>

这里特别提醒一下,classid号码要输入对,否则调用会因为找不到控件而失败。其他的含义比较简单,这里就不啰嗦了。

这里是在本地调用ActiveX控件,其他形式的调用,还需要对控件进行安全方面的一些处理,否则浏览器会禁止执行。

三、浏览器使用ActiveX控件

双击刚才编辑的x.html文档,缺省情况下,启动IE浏览器打开页面,会有一个报警,效果如下图所示。

允许启动控件,则可以点击“执行函数”和“关于”按钮了。

 

点击“执行函数”按钮,效果如下图所示。

   

点击“关于”按钮,效果如下图所示。

 

原创粉丝点击