使用ATL开发COM组件时有几个问题,可能会经常遇到,并且如果不知道的话,还很难找到解决的方法。我看到有些人在CSDN上也问到了相同的问题,但很少有人给出满意的答案,所以我将这几个常见问题写在下面,以免其他人再重复劳动。
一、 问:做的一个控件,在网页里面调用时,IE浏览器总是提示:“在此页上的ActiveX控件和本页上其它部分的交互可能不安全.你想允许这种交互吗?” 请问如何将这个提示去掉。
答:在你的控件中加入如下处理即可。在你的控件的类定义部分再多继承一个父类
public IObjectSafetyImpl<CCommunicationsLink,INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA>
同时在接口映射中也多加一句:
BEGIN_COM_MAP(CXXX)
........
COM_INTERFACE_ENTRY(IObjectSafety)
END_COM_MAP()
进行如上处理,则IE就不会再提示了。
二、 问:我用VC的ATL库写的控件,用VB可以接收到事件,但是用IE网页却死活收不到事件?
答:一般有以下几种原因:
第一个是IE浏览器只能支持单套间的模式,你的控件只能是单套间的,不能是多套间。
第二个是IE浏览器不会主动调用Advise等注册事件的接口,所以你的控件的类定义必须再多继承以下的父类
public
IProvideClassInfo2Impl<&CLSID_Test, &DIID__ITestEvents, &LIBID_TESTLib,1,0>
同时接口映射中加入以下处理
BEGIN_COM_MAP(CTest)
//用来查询接口类信息
COM_INTERFACE_ENTRY(IProvideClassInfo)
COM_INTERFACE_ENTRY(IProvideClassInfo2)
END_COM_MAP()
这样IE才能够注册准备接收事件。
参考 http://support.microsoft.com/default.aspx?scid=kb;en-us;200839
第三是你在控件中激活事件的语句(象调用Fire_Event的地方)如果不在主线程里面,而是在另外开的线程里面激活,则要经过处理才行。具体的处理步骤在微软的知识库中提到了,网址是
http://support.microsoft.com/kb/q280512/
需要下载一个该网页上的文件ATLCPImplMT.h,在控件事件实现的文件中进行如下处理:包含该文件,加上一些小修改,示例代码如下
#include "ATLCPImplMT.h" // 包含此句
// 注意下面一句的继承类由IconnectionPointImpl变成了 IConnectionPointImplMT
template <class T>
class CProxy_ITestEvents : public IConnectionPointImplMT<T, &DIID__ITestEvents, CComDynamicUnkArray>
{
//Warning this class may be recreated by the wizard.
public:
HRESULT FireEvents(DISPID p_DispID, CComVariant* p_pvars, long p_lParNum)
{
CComVariant varResult;
T* pT = static_cast<T*>(this);
int nConnectionIndex;
int nConnections = m_vec.GetSize();
for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
{
// 屏蔽掉向导生成的这三句
// pT->Lock();
// CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
// pT->Unlock();
// 换成下面这两句
CComPtr<IUnknown> sp;
sp.Attach(GetInterfaceAt(nConnectionIndex));
IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
if (pDispatch != NULL)
{
VariantClear(&varResult);
DISPPARAMS disp = {p_pvars, NULL, p_lParNum, 0 };
pDispatch->Invoke(p_DispID, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
}
}
return varResult.scode;
}
当然,还有象通过给主线程发消息、线程间列集等方法,不过我觉得这种操作起来更简单些,进行以上的处理后IE网页就可以接收事件了。
在网页中接收事件的语法大致如下:
vbs 中
sub 控件ID_On事件函数名(参数)
............
end sub
js 中
<script for="控件ID" event="事件函数名(参数)">
............
</script>
三、 问:我在控件里面有SAFEARRAY类型的数据,怎样通过事件传给IE网页或VB程序?
答:比如你的IDL定义如下:
dispinterface _ITestEvents
{
properties:
methods:
[id(1), helpstring("DataReceived")]
HRESULT DataReceived([in] SAFEARRAY(unsigned char)* Data);
};
此时如果收到数据了,需要通过事件将数据传出去。在事件处理的函数中定义如下
HRESULT Fire_DataReceived(SAFEARRAY * * Data)
你会发现ATL向导生成的代码根本无法将SAFEARRAY类型的数据传出去,其实可以将向导生成的代码进行一下修改即可
// pvars[0] = Data;
pvars[0].vt = VT_ARRAY | VT_BYREF | VT_UI1;
pvars[0].pparray = Data;
将原来的pvars[0] = Data;屏蔽掉,换成下面两句即可。注意其中VT_UI1跟你发送事件前,组织SAFEARRAY数据时的类型相同,比如你用下面的函数组织数据
SafeArrayCreate(VT_UI1, 1, pSab);
则是VT_UI1,如果是其他类型要同时对应起来。
使用ATL开发COM组件时有几个问题,可能会经常遇到,并且如果不知道的话,还很难找到解决的方法。我看到有些人在CSDN上也问到了相同的问题,但很少有人给出满意的答案,所以我将这几个常见问题写在下面,以免其他人再重复劳动。
一、 问:做的一个控件,在网页里面调用时,IE浏览器总是提示:“在此页上的ActiveX控件和本页上其它部分的交互可能不安全.你想允许这种交互吗?” 请问如何将这个提示去掉。
答:在你的控件中加入如下处理即可。在你的控件的类定义部分再多继承一个父类
public IObjectSafetyImpl<CCommunicationsLink,INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA>
同时在接口映射中也多加一句:
BEGIN_COM_MAP(CXXX)
........
COM_INTERFACE_ENTRY(IObjectSafety)
END_COM_MAP()
进行如上处理,则IE就不会再提示了。
二、 问:我用VC的ATL库写的控件,用VB可以接收到事件,但是用IE网页却死活收不到事件?
答:一般有以下几种原因:
第一个是IE浏览器只能支持单套间的模式,你的控件只能是单套间的,不能是多套间。
第二个是IE浏览器不会主动调用Advise等注册事件的接口,所以你的控件的类定义必须再多继承以下的父类
public
IProvideClassInfo2Impl<&CLSID_Test, &DIID__ITestEvents, &LIBID_TESTLib,1,0>
同时接口映射中加入以下处理
BEGIN_COM_MAP(CTest)
//用来查询接口类信息
COM_INTERFACE_ENTRY(IProvideClassInfo)
COM_INTERFACE_ENTRY(IProvideClassInfo2)
END_COM_MAP()
这样IE才能够注册准备接收事件。
参考 http://support.microsoft.com/default.aspx?scid=kb;en-us;200839
第三是你在控件中激活事件的语句(象调用Fire_Event的地方)如果不在主线程里面,而是在另外开的线程里面激活,则要经过处理才行。具体的处理步骤在微软的知识库中提到了,网址是
http://support.microsoft.com/kb/q280512/
需要下载一个该网页上的文件ATLCPImplMT.h,在控件事件实现的文件中进行如下处理:包含该文件,加上一些小修改,示例代码如下
#include "ATLCPImplMT.h" // 包含此句
// 注意下面一句的继承类由IconnectionPointImpl变成了 IConnectionPointImplMT
template <class T>
class CProxy_ITestEvents : public IConnectionPointImplMT<T, &DIID__ITestEvents, CComDynamicUnkArray>
{
//Warning this class may be recreated by the wizard.
public:
HRESULT FireEvents(DISPID p_DispID, CComVariant* p_pvars, long p_lParNum)
{
CComVariant varResult;
T* pT = static_cast<T*>(this);
int nConnectionIndex;
int nConnections = m_vec.GetSize();
for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
{
// 屏蔽掉向导生成的这三句
// pT->Lock();
// CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
// pT->Unlock();
// 换成下面这两句
CComPtr<IUnknown> sp;
sp.Attach(GetInterfaceAt(nConnectionIndex));
IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
if (pDispatch != NULL)
{
VariantClear(&varResult);
DISPPARAMS disp = {p_pvars, NULL, p_lParNum, 0 };
pDispatch->Invoke(p_DispID, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
}
}
return varResult.scode;
}
当然,还有象通过给主线程发消息、线程间列集等方法,不过我觉得这种操作起来更简单些,进行以上的处理后IE网页就可以接收事件了。
在网页中接收事件的语法大致如下:
vbs 中
sub 控件ID_On事件函数名(参数)
............
end sub
js 中
<script for="控件ID" event="事件函数名(参数)">
............
</script>
三、 问:我在控件里面有SAFEARRAY类型的数据,怎样通过事件传给IE网页或VB程序?
答:比如你的IDL定义如下:
dispinterface _ITestEvents
{
properties:
methods:
[id(1), helpstring("DataReceived")]
HRESULT DataReceived([in] SAFEARRAY(unsigned char)* Data);
};
此时如果收到数据了,需要通过事件将数据传出去。在事件处理的函数中定义如下
HRESULT Fire_DataReceived(SAFEARRAY * * Data)
你会发现ATL向导生成的代码根本无法将SAFEARRAY类型的数据传出去,其实可以将向导生成的代码进行一下修改即可
// pvars[0] = Data;
pvars[0].vt = VT_ARRAY | VT_BYREF | VT_UI1;
pvars[0].pparray = Data;
将原来的pvars[0] = Data;屏蔽掉,换成下面两句即可。注意其中VT_UI1跟你发送事件前,组织SAFEARRAY数据时的类型相同,比如你用下面的函数组织数据
SafeArrayCreate(VT_UI1, 1, pSab);
则是VT_UI1,如果是其他类型要同时对应起来。
分享到:
相关推荐
使用ATL开发COM组件文档
ATL com 组件开发完整实例,需要的可做参考。ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。通过活动模板库,可以建立COM组件,然后通过ASP...
初学COM,使用ATL创建COM组件,并测试COM组件的小例子
mfc visual c++ Atl开发集合组件实例
1、使用ATL建立一个包含2个接口的COM组件,并在其中一个自动化接口中实现字符串的小写转换(如:将HELLO转换成hello);在另一个普通的接口中实现2个方法:通过三角形的3条边长求面积和两数之间的除法()(如:a/b...
ATL开发的ACTIVEX控件的一个IE控件例子程序,源码。想学IE控件开发的试试看吧。
ATL创建进程外COM组件服务,包含COM组建客户端测试程序,使用时,需要先通过批处理文件将COM组建服务注册到Windows系统中(win10测试通过),具体可参考我的文章《ATL创建进程外COM组件服务(C++图解说明)》
atl开发指南 atl开发指南 atl开发指南 atl开发指南 atl开发指南
基于VS2010开发的COM组件接口的ATL编程,适合初学者编程。
第三章介绍了活动模板库(ATL)的概念和使用方法;第四章涉及接口的实现和线程之间的参数调度等细节问题;第五章探讨了代码复用的两种方法――包容和集合;第六章讨论了关于自动化的问题;第七章说明了事件和连接点...
使用ATL工具设计COM组件实现对串口的操作
基于ATL的COM组件开发
ATL SHELL EXTENSION编写的IE浏览器Cookie小偷程序.zip
如何用VS2005 ATL 创建 COM 组件
ATL COM组建的创建和调用示例, 采用VS进行开发,可参考
《ATL开发指南》第七部分 共11份 atl 开发指南 com 组件
ATL开发指南 ATL开发指南 ATL开发指南
《ATL开发指南》第一部分 共11份 atl 开发指南 com 组件
ATL,Active Template Library活动模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。通过活动模板库,可以建立COM组件,然后通过ASP页面中的脚本对COM对象进行调用。这种COM组件可以包含...
利用ATL编写COM组件,利用ATL编写COM组件,利用ATL编写COM组件,利用ATL编写COM组件