我理解,這是一個非常古老的職位,但我自己偶然發現了來自的ActiveX二進制數據傳遞到的JavaScript同樣的問題,並決定提出了基於taxilian的建議的解決方案。
在此之前,我想指出的是也可以構建二進制數據的SAFEARRAY並將該對象發送回JS。唯一的問題是必須使用VBScript來解壓縮這個對象,並將其轉換爲只能由JScript識別的數據類型(微軟的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中的對象。現在我們有一個指向窗口對象的指針,我們可以創建一個Array對象。數組只是IHTMLWindow2對象的一個方法,爲了創建一個新的數組我們必須調用這個函數。
爲了調用COM對象的方法(和IHTMLWindow2只是通過某些COM對象實現的接口),該對象必須實現IDispatch接口,其允許用戶通過使用調用方法調用此對象的方法。 GetIDsOfNames方法用於檢索Array方法的DISPID(dispatch id),然後通過在我們的window_obj對象上調用Array方法最終創建一個新數組。在ret_val參數(VARIANT類型)中,我們將得到一個代表我們JS數組的IDispatch *指針。
下一步做什麼很明顯:使用此指針獲取push方法的DISPID,然後通過反覆調用此方法填充數組。示例函數還顯示瞭如何構建IDispatch :: Invoke方法所需的DISPPARAMS和VARIANTARG對象。
最後,我們從方法返回IDispatch *指針。 JS將這個對象識別爲本地JS數組,因爲這實際上是它的內部實現。
你不能使用VBArray。它不存在於JScript中,至少對於IE8而言。 – 2012-02-22 19:33:06
[MSDN文檔VBArray](http://msdn.microsoft.com/en-us/library/ie/y39d47w8(v = vs.94).aspx)似乎表明否則:「在以下文檔模式中受支持:怪癖,Internet Explorer 6標準,Internet Explorer 7標準,Internet Explorer 8標準,Internet Explorer 9標準和Internet Explorer 10標準,在Windows應用商店應用中不受支持。 – 80x25 2014-11-05 01:40:21
我可以證實這個作品。作爲一個小改進,如果你需要一個字節數組,你可以用* .idl文件中的SAFEARRAY(BYTE)替換SAFEARRAY(VARIANT)。 – 2015-07-01 08:16:22