我需要将ActiveX对象(使用带有ATL的Visual C ++)的数据(字节数组,即char *)传递给我的javascript代码(反之亦然)。我已经在网上挖掘了这样的问题并尝试了很多解决方案,但没有成功。我尝试了以下几点:
//in C++:
STDMETHODIMP CActiveXObj::f(BSTR* msg) // msg is the return value in ATL automation function
{
char *buffer; // byte data is stored in buffer
*msg = SysAllocStringByteLen((LPCSTR)buffer, bufferLen+1);
}
//////////////////////////////////////////////////////////////////////////
//in JavaScript:
var myobj= new ActiveXObject("IGCE.ActiveXObj");
var result = myobj.f(); // result = ""
有人能以最简单的形式向我提供工作代码吗?
非常感谢!
克里斯汀
答案 0 :(得分:3)
// In *.idl file
[propget, id(0)] HRESULT ArrayProperty([out, retval] SAFEARRAY(VARIANT) *pArray);
[propput, id(0)] HRESULT ArrayProperty([in] SAFEARRAY(VARIANT) Array);
// Somewhere in javascript
function ax2js(axArray) {
return new VBArray(array).toArray();
}
function js2ax(jsArray) {
var dict = new ActiveXObject("Scripting.Dictionary");
for (var i = 0; i < jsArray.length; i++) {
dict.add(i, jsArray[i]);
}
return dict.Items();
}
function fooHandler() {
var ax = new ActiveXObject("My.My");
var ar = ax2js(ax.ArrayProperty);
ax.ArrayProperty = js2ax(ar);
}
答案 1 :(得分:0)
您可能需要使用SAFEARRAY传递数据。这个名为CComSafeArray的ATL包装器。希望这对你来说已经足够了,如果没有的话 我会挖出一些代码。
答案 2 :(得分:0)
据我所知(根据我的经验),在与javascript交谈时,您只能使用以下基本数据类型:
其他任何东西似乎都不起作用。我从来没有尝试过使用SAFEARRAY,但我可以提出一个可能的选择。
如果您获得对DOM窗口的引用(我不会在此处介绍;如果您不知道如何,搜索和/或提交新问题,我可以在那里回答),您可以使用IDispatch在窗口上调用方法“Array”,它将返回一个空的javascript数组的IDispatch *。然后,您可以在Array IDispatch *上为要作为int发送到javascript的每个字节调用“push”,然后返回Array的IDispatch *作为相关方法或属性的返回值。您将获取javascript中的数据作为整数数组,但每个元素都是一个字节,您可以这样使用它。
如果您可以建议在javascript中使用二进制数据的另一种方法(暂时忘记activex控件),我可能会告诉您如何从控件中返回数据。
这实际上是FireBreath(IE和Firefox的开源插件框架; http://www.firebreath.org)在从JSAPI(javascript脚本对象)方法返回向量以将数据作为数组返回到javascript时使用的方法。您可以在兼容NPAPI的浏览器上使用类似(几乎相同)的方法。
答案 3 :(得分:0)
我知道这是一篇非常古老的帖子,但我自己偶然发现了将二进制数据从ActiveX传递到Javascript的同样问题,并决定提出一个基于taxilian提案的解决方案。
在此之前,我想指出也可以构建SAFEARRAY的二进制数据并将此对象发送回JS。唯一的问题是必须使用VBScript解压缩此对象,将其转换为仅由JScript(Microsoft的Javascript方言)识别的数据类型,而不是用于构建传统JS数组。
在没有理解这个解决方案的背后(对于那个检查taxilian的答案),这里有一个方法将在ActiveX控件中构建Javascript数组并将此数组返回给JS。
/** NOTE: you have to include MsHTML.h header in order to access IServiceProvider,
IHTMLWindow2 and related constants. **/
IDispatch* CActiveX_TutorialCtrl::GetJSArrayObject(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
LPOLECLIENTSITE site = this->GetClientSite();
IServiceProvider* serviceProvider = nullptr;
site->QueryInterface(IID_IServiceProvider, reinterpret_cast<void**>(&serviceProvider));
IHTMLWindow2* window_obj = nullptr;
serviceProvider->QueryService(SID_SHTMLWindow, IID_IHTMLWindow2, reinterpret_cast<void**>(&window_obj));
DISPPARAMS disparam = { nullptr, nullptr, 0, 0 };
VARIANT ret_val;
DISPID dispid;
LPOLESTR method_name = L"Array";
HRESULT hr = window_obj->GetIDsOfNames(IID_NULL, &method_name, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
hr = window_obj->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &disparam, &ret_val, nullptr, nullptr);
if (ret_val.vt != VT_DISPATCH)
return nullptr;
VARIANTARG push_arg;
method_name = L"push";
hr = ret_val.pdispVal->GetIDsOfNames(IID_NULL, &method_name, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
if (hr != S_OK)
return nullptr;
::VariantInit(&push_arg);
::VariantChangeType(&push_arg, &push_arg, 0, VT_I4);
for (int i = -10; i <= 10; ++i)
{
push_arg.intVal = i;
disparam.rgvarg = &push_arg;
disparam.rgdispidNamedArgs = nullptr;
disparam.cArgs = 1;
disparam.cNamedArgs = 0;
hr = ret_val.pdispVal->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &disparam, nullptr, nullptr, nullptr);
if (hr != S_OK)
return nullptr;
}
::VariantClear(&push_arg);
serviceProvider->Release();
window_obj->Release();
serviceProvider = nullptr;
window_obj = nullptr;
return ret_val.pdispVal;
}
您在此处看到的大多数代码都是典型的COM编程。首先,我们检索指向托管控件的客户端站点的指针。然后,我们为IServiceProvider提供QI(查询接口),这是一个实现许多支持服务的IE接口。其中一个是 IHTMLWindow2 ,它是Javascript中 window 对象的类型。现在我们有一个指向窗口对象的指针,我们可以创建一个Array对象。 Array只是IHTMLWindow2对象的一个方法,为了创建一个新的数组,我们必须调用这个函数。
为了在COM对象上调用方法(而IHTMLWindow2只是某个COM对象实现的接口),该对象必须实现IDispatch接口,允许用户使用调用方法。 GetIDsOfNames 方法用于检索Array方法的DISPID(dispatch id),然后我们最终通过在 window_obj 对象上调用Array方法创建一个新数组。在 ret_val 参数(VARIANT类型)中,我们将获得一个表示我们的JS数组的IDispatch *指针。
显然下一步该做什么:使用此指针获取 push 方法的DISPID,然后通过&#34; Invoking&#34;填充数组。这种方法一遍又一遍。示例函数还显示了如何构建IDispatch :: Invoke方法所需的DISPPARAMS和VARIANTARG对象。
最后,我们从方法返回IDispatch *指针。 JS会将此对象识别为本机JS数组,因为这实际上是它的内部实现。