2009-12-18 72 views
4

我需要從ActiveX對象(使用Visual C++和ATL)將數據(字節數組,即char *)傳遞到我的JavaScript代碼(反之亦然)。我已經針對這個問題挖掘了Web,並嘗試了很多解決方案,但都沒有成功。我試過如下:從ActiveX傳遞字節數組到JavaScript,反之亦然

  • 將char *轉換爲BSTR並將其傳遞給javascript(JS),但由於我的數據的性質不是字符串,因此我的結果是JS。從C++

字節數據的

//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

您可能需要使用SAFEARRAY傳遞數據。這個叫做CComSafeArray的ATL包裝器。希望這將足以讓你開始,如果不是那麼 我會挖出一些代碼。

0

據我所知(在我的經驗)交談的JavaScript時,你只能使用以下基本數據類型:

  • 字符串
  • 詮釋
  • 布爾
  • IDispatch *

其他都沒有似乎工作。我從來沒有嘗試過使用SAFEARRAY,但我可以提出一個可能的選擇。

如果您獲得對DOM窗口的引用(如果您不知道如何搜索和/或提交新問題,並且我可以在那裏回答),那麼您可以使用IDispatch在窗口上調用方法「Array」,並且它將爲一個空的javascript數組返回一個IDispatch *。然後,您可以在Array IDispatch *上爲每個要發送給javascript的字節調用「推送」爲int,然後從該方法或屬性返回Array的IDispatch *作爲返回值。您將以javascript形式獲取數據作爲整數數組,但每個元素都是一個字節,您可以這樣使用它。

如果您可以建議另一種在JavaScript中使用二進制數據的方法(暫時忘記activex控件),我可能會告訴您如何以這種方式從控件中返回數據。

這實質上是FireBreath(用於IE和Firefox的開源插件框架; http://www.firebreath.org)在您從JSAPI(JavaScript腳本對象)方法返回一個向量以將數據作爲數組返回給JavaScript時使用的方法。您可以在NPAPI兼容的瀏覽器上使用類似(幾乎相同)的方法。

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); 
} 
+0

你不能使用VBArray。它不存在於JScript中,至少對於IE8而言。 – 2012-02-22 19:33:06

+0

[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

+0

我可以證實這個作品。作爲一個小改進,如果你需要一個字節數組,你可以用* .idl文件中的SAFEARRAY(BYTE)替換SAFEARRAY(VARIANT)。 – 2015-07-01 08:16:22

0

我理解,這是一個非常古老的職位,但我自己偶然發現了來自的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數組,因爲這實際上是它的內部實現。

相關問題