Qt中使用ActiveX(二)【方法调用和事件处理】

使用Qt作ActiveX开发ActiveX Server之后,最重要的一个应用是处理与客户端之间的交互,一般来说开发的ActiveX Server可以用在如下几个方面:

1. IE浏览器中嵌入ActiveX控件进行网页开发(由于ActiveX是微软推出的一项技术,浏览器只支持IE浏览器)

2. 客户使用COM的方式调用(可以使用C#、VB等语言引入COM组件进行开发)

一般来说这两者的使用方式差别不是很大,由于客户语言的限制还是略有不同,本文主要以IE浏览器中的情形来进行说明。

  • 使用ActiveX控件

在IE中使用ActiveX很简单,只需要将ActiveX控件引入到网页之中(使用OBJECT标签即可),网页代码如下所示:
<html xmlns="http://www.w3.org/1999/xhtml">
<html>

<head>
<title>Qt ActiveX Example</title>
</head>

<body>
<OBJECT id="myActiveX" WIDTH=640px" HEIGHT=480px" CLASSID="CLSID:68DEF798-54CF-4894-8B63-65862A7F995D"></OBJECT>
</body>

</html>
其中CLSSID中的值使用Qt中导出类的CLASSID,一般在下面的代码中找到
class MyActiveX : public QWidget, public QAxBindable
{
	Q_OBJECT

		Q_CLASSINFO("ClassID", "{AC72FE56-631D-4912-AB9E-B3230FCF2EA7}")             //将该项中的ClassID添加到网页中
		Q_CLASSINFO("InterfaceID", "{750E45AB-86A7-4D4A-A1D9-99A851E4881E}")
		Q_CLASSINFO("RegisterObject", "yes")
}
在添加完成之中,如果我们的ActiveX已经注册成功(在编译过程中会自行注册,但是Dll的依赖文件仍然需要拷贝到工程生成Dll的目录下),如果没有注册,可以使用Windows提供的regsvr32.exe进行注册,具体命令是
regsvr32 myActiveX.dll  //myActiveX.dll是我电脑上测试工程生成的ActiveX的名称,具体名称请参考读者自己生成的文件,后缀一般可以是dll或者ocx
在添加完成之后,当我们需要调用ActiveX中提供的函数时,直接使用ActiveX中OBJECT的id号调用即可,如下所示:
<html>

<head>
</head>

<body onload = "loadHtml">
<OBJECT id="myActiveX" WIDTH=640px" HEIGHT=480px" CLASSID="CLSID:68DEF798-54CF-4894-8B63-65862A7F995D"></OBJECT>
</body>

<script>
fucntion loadHtml()
{
  myActiveX.ChangeBoxColor();       //ChangeBoxColor是测试ActiveX导出的一个方法
}
</script>

</html>
以上就是调用ActiveX的方法,十分的简单。除此之外另外的需求包括,如何对ActiveX中的事件进行处理,也就是说当出现鼠标点击(或者其他事件),我们需要调用JavaScript函数来响应这一事件应该怎么写呢?可以有几种方式实现,其中最简单的方式是:直接明确写出事件:

  • ActiveX事件处理方式一

可以在网页中写如下的代码:
<html>

<head>
</head>

<body onload = "loadHtml">
<OBJECT id="myActiveX" WIDTH=640px" HEIGHT=480px" CLASSID="CLSID:68DEF798-54CF-4894-8B63-65862A7F995D"></OBJECT>
</body>

<script>
fucntion loadHtml()
{
  myActiveX.ChangeBoxColor();
}

function myActiveX::BoxClicked(boxName)  //BoxClicked是Qt中的一个Signal,在mousePressEvent中我们emit这个事件,这样就可以在单击鼠标的时候调用这个JS函数
{
  alert(boxName);
}

</script>

</html>

[更新备注:很多读者反映发送不了Qt的信号,我上传了一份测试的代码在我个人的资源中,供大家参考,下载地址:http://download.csdn.net/detail/csxiaoshui/9728972 ]

  • 事件处理方式二

第一种事件处理的方式需要客户端按上面的方式进行,但是在非网页开发的时候就比较麻烦,比如使用C#调用Qt开发的控件时,就不能用上面的事件处理方式了,这时候我们可以将事件的调用转到ActiveX内部,也就是说ActiveX在内部调用外部的回调函数,具体是实现方式如下:
1. 我们需要提供类似于AttachEvent(QString,FuctionPTR*)这样的函数,将函数指针传到ActiveX内部,第一个参数QString是一个标识符,可以自己随意使用,一般可能是用来表示是什么类型的事件。

2. 当我们这样设定之后,会发现一个问题,在Qt中根本就没有提供在方法中表示函数指针的参数类型(具体可以参考Qt中使用ActiveX(一)种的表格),经过一番搜索,发现可以使用IDispatch*这种类型来接受外部的函数指针,于是我们需要提供以下的方法:
void AttachEvent(const QString& eventName,	IDispatch* dispFunc);
3. 当我们得到这样一个指针之后,我们需要明确的有两点:
    (1) 我们的函数类型是怎么样的?也就是说这个函数的参数和返回值类型是什么样的,不同参数的函数需要不同的处理方式
    (2) 怎么调用这个外部的指针(IDispatch*)?
其实这两个问题是绑定在一起的,具体来说我们需要通过IDispatch提供的Invoke方法来调用函数,在调用的过程中我们需要明确函数的参数有几个,在调用过程中根据参数的不同写法有点差别,首先我们看一下Invoke的函数原型:
HRESULT Invoke(  
  [in]       DISPID dispIdMember,  
  [in]       REFIID riid,  
  [in]       LCID lcid,  
  [in]       WORD wFlags,  
  [in, out]  DISPPARAMS *pDispParams,  
  [out]      VARIANT *pVarResult,  
  [out]      EXCEPINFO *pExcepInfo,  
  [out]      UINT *puArgErr  
);
具体的解释可以参考MSDN中的描述,其中最后三个参数涉及到异常处理和返回值,最重要的是第5个参数 pDispParams,这个参数就是根据传入的函数参数个数来确定的,下面是我调用这个函数的方式:
	DISPPARAMS dispParams = { NULL, NULL, 0, 0 };
	m_dispatch->Invoke(
		DISPID_VALUE,
		IID_NULL,
		LOCALE_USER_DEFAULT,
		DISPATCH_METHOD,
		&dispParams,
		NULL,
		NULL,
		NULL);
其中dispParams根据参数的个数来设置,由于我传入的JavaScript函数没有参数,所以传入的参数如上所示,假设我们传入的参数包含以下参数:
		function OnLButtonClicked(flag, x, y)
		{
			alert("flag: "+ flag + " x: " + x + " y: " + y);
		}
这个JavaScript的函数包含了三个参数,当我们把它传入到ActiveX中的时候,我们怎么调用它呢,需要如下的设置:
	VARIANTARG avarParams[3];

	avarParams[2].vt = VT_I4;  
	avarParams[2].intVal = flag;  

	avarParams[1].vt = VT_I4;  
	avarParams[1].intVal = x;  
 
	avarParams[0].vt = VT_I4;  
	avarParams[0].intVal = y;  

	DISPPARAMS dispParams = { avarParams, NULL, 3, 0 };

	m_dispatch->Invoke(
		DISPID_VALUE,
		IID_NULL,
		LOCALE_USER_DEFAULT,
		DISPATCH_METHOD,
		&dispParams,
		NULL,
		NULL,
		NULL);
我们需要设置它的每一个参数的值和类型,关于VARIANTARG的定义,可以参考MSDN,它是一个比较大的结构体。另外在使用参数设置的时候需要注意一个问题:
这些参数的设置和JavaScript函数的形参列表是相反的

除此之外还有一个需要注意的地方:如果我们想把IDispatch这个参数存储起来,例如我想把外部传入的IDispatch存入到成员变量中:
void MyActiveX::AttachEvent(const QString& eventName, IDispatch* dispFunc) //这个AttachEvent函数是暴露出来供JavaScript调用的一个方法,用来将JS中的回调函数设置到ActiveX之中
{
	dispFunc->AddRef();
	m_dispatch = dispFunc
}
一定要AddRef,让引用技术加1,不然出了这个设置函数IDispatch的指针就被析构了。保存下来之后可以在合适的情况下调用。

  • 7
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 37
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 37
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值