JavaScriptとActiveXの間にデータを転送する-連載二

8949 ワード

本論文では、JSなどのスクリプト言語とActiveXコントロールとの間でどのように通信し、各種パラメータやCOMのIDispatchインターフェースを伝達するかを検討します.同様の方法を使用すると、LUA、AutoCadなど、他のすべてのシナリオ言語に拡張できます.
本稿では以下のいくつかの側面を検討する.
型配列の調整文字列パラメータ、文字列戻り値着信文字列の内容を変更する配列パラメータIDisliatchインターフェース紹介入力配列の内容を変更する配列内容を追加する配列参照で、JSはS 4 Execute()を呼び出します.
この文章は長いので、連載で発表します.連載は主に1~3点、連載は4~6点、連載は7~8時までです.
(四)配列パラメータ
1.使用時には、S 4 Execute()のinBuff/outBuffなどの行列参が必要となる場合があります.
2.JSにおける整体データはByte/Shot/Intなどを区別しないので、配列要素の種類はすべてint(COMにおけるVT I 4であり、Iは整体、4は4バイトを示す)である.
3.JSのArayはCOMでIDispatchを実現したオブジェクトであり、IDispatchインターフェースアプリで操作できます.IDispatchについては、次のセクションをご覧ください.
4.COM中C++定義
以下のコードには、2つの関数GetArayNumber OfIndexとGetArayLengthという関数が定義されています.機能は、配列長をそれぞれ取得し、指定された番号要素を取得します.
以下のコードの意味は、次のセクション「IDispatchインターフェース紹介」を参照してください.
JS配列はCOMにおいてIDispatchオブジェクトであり、長さを取得し、実際にはlengthという属性値を取得する.
最後の配列を取得すると、実際には「4」と名付けられた属性値(5つの要素を仮定する)が得られます.
STDMETHODIMP CJsAtl::GetLastElement(VARIANT vArray, LONG* retVal)
{
         int len = 0;
         HRESULT hr = GetArrayLength(vArray.pdispVal, &len);
         if (FAILED(hr))
                  return hr;
 
         hr = GetArrayNumberOfIndex(vArray.pdispVal, len - 1, retVal);
         return S_OK;
}
// ***
//   Javascript    
//       Javascript    length              
// ***
HRESULT GetArrayLength(IDispatch* pDisp, int* pLength)
{
         BSTR varName = L"length";
         VARIANT varValue;
         DISPPARAMS noArgs = {NULL, NULL, 0, 0};
         DISPID dispId;
         HRESULT hr = 0;

         hr = pDisp->GetIDsOfNames(IID_NULL, &varName, 1, LOCALE_USER_DEFAULT, &dispId);
         if (FAILED(hr))
                  return hr;
         hr = pDisp->Invoke(dispId, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &noArgs, &varValue, NULL, NULL);
         if (SUCCEEDED(hr))
         {
                  *pLength = varValue.intVal;
                  return hr;
         }
         else
         {
                  return hr;
         }
}
// ***
//   Javascript             
// ***
HRESULT GetArrayNumberOfIndex(IDispatch* pDisp, int index, int * pValue)
{
         CComVariant varName(index, VT_I4); //     
         DISPPARAMS noArgs = {NULL, NULL, 0, 0};
         DISPID dispId;
         VARIANT varValue;
         HRESULT hr = 0;       
         varName.ChangeType(VT_BSTR); //           ,   GetIDsOfNames
         //
         //              ,       dispId 
         //
         hr = pDisp->GetIDsOfNames(IID_NULL, &varName.bstrVal, 1, LOCALE_USER_DEFAULT, &dispId);
         if (FAILED(hr))
                  return hr;
         //
         //   COM  ,          ,  dispId        varValue 
         //
         hr = pDisp->Invoke(dispId, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTY GET , &noArgs, &varValue, NULL, NULL);
         if (SUCCEEDED(hr))
         {
                  *pValue = varValue.intVal;    //       int    
                  return hr;
         }
         else
         {
                  return hr;
         }
}

5.JSで呼び出し
function test_get_last()
{
       var array = new Array(0, 1, 2, 3); //     
       try {
              var obj = document.getElementByIdx_xx_x("obj");
              var lastElement = obj.GetLastElement(array); //           
              alert("lastElement: " + lastElement);
       } catch (e) {
              alert("JS ERROR: " + e.message);
       }
}

6.試験実行
配列定義:{0,1,2,3}
最後の要素:3
(五)IDispatchインターフェース紹介
1.Cプログラムの呼び出し時には、調整者は、インターフェース仕様(例えば、パラメータタイプ、パラメータバイト長、パラメータ順序など)を事前に知っておく必要があります.これらの仕様は言語によって異なりますので、COMは異なる言語間の呼び出しを解決していません.IDispatchインターフェースを提供しています.
2.IDispatchは、事前に明確にすることなく、オブジェクトを取得した後、オブジェクトから直接呼び出し方式を取得することができる例を自己説明しなければならないことを要求する.
3.IDispatchでVT_を通すTYPEはVT_のような関連タイプを指定します.I 4は4バイトの整数、VT_です.BSTRはunicode文字列でVT_です.DISPATCHはIDispatchオブジェクトを表しています.
4.オブジェクトの各属性または関数に、Id全体と文字列nameを割り当てます.使用者はname文字列でどうやって呼び出しますか?例えば、nameが「length」の属性であれば、使用者は長さと理解する.ここでは通常nameに従って対応する属性を理解するので、name記述は十分正確であるべきである.例えば、「length()」という名前の関数で整数加算機能を実現するのは不適切です.
5.IDispatchオブジェクトを使用する場合、首相はIDispatchを呼び出す:GetIDsOfNames()属性、関数名をパラメータとして、対応する属性、関数IDを取得する.
6.IDispatchを再起動:Invoke()はidをパラメータとして、実際に機能を呼び出します.
7.属性値を取得するとInvoke()が呼び出した時にDispactch_に着信します.ProptyGetフラグ.
8.属性値を設定するとInvoke()が呼び出した時にDispactch_に入るProptyPtマーク.また、DispParaamsパラメータでは、この属性を修正するとどのような値に変更するかを指定します.DispParaams構造説明を参照してください.
9.呼び出し関数であれば、Invoke()の呼び出し時に、Dispactch_に着信します.Methodマーク.このMethodにパラメータが必要なら、IDispatch:Invoke()のDispParaamsパラメータで指定します.
10.DispParaams構造使用例:
DISPPARAMS dispparams;
         dispparams.rgdispidNamedArgs = &dispidOfNamedArgs;
         dispparams.cArgs = 1;
         dispparams.cNamedArgs = 1;
         dispparams.rgvarg = new VARIANTARG[1];
         dispparams.rgvarg[0].vt = VT_I4;
         dispparams.rgvarg[0].intVal = 123;

a.上記のコードはMethodへの参照のための簡単な例です.まずDispParaamsオブジェクトを作成します.
b.cArgsはMethodのパラメータ個数を指定します.
c.cNamedArgsはMethodに名前が付いているパラメータの個数を指定します.(ネーミングパラメータは、名前がないパラメータに対応する概念です.いくつかの言語で定義可能な引数があります.このときIDispatchの記述では、パラメータに名前を割り当てることなく、呼び出し時には名前がないパラメータで存在します.JSでは、Arayオブジェクトのpsh()のように、不定個数のパラメータをサポートします.
d.rgvargは実際のパラメータ配列であり、各要素は一つのパラメータを表しています.vtはこの要素のデータタイプを示しています.intVal項は一つのC++結合構造で、vt==VT_I 4の場合、intVal=xxx方式で値を付けます.vt==VT_BSTRは、bstraVal=xxx方式で値を付けます.
11.例を挙げます.二つのパラメータはいずれも名前のないパラメータです.一つ目は整体型で、二つ目はBSTR型です.
DISPPARAMS dispparams;
         dispparams.rgdispidNamedArgs = NULL;
         dispparams.cArgs = 2;
         dispparams.cNamedArgs = 0;
         dispparams.rgvarg = new VARIANTARG[2]; // 2   ,  2   
         dispparams.rgvarg[0].vt = VT_I4;  //   
         dispparams.rgvarg[0].intVal = 123;
         dispparams.rgvarg[1].vt = VT_BSTR; //     
         dispparams.rgvarg[1].bstrVal = L"abcd";

(六)入力配列の内容を変更する
1.第5節では、JSからCOMに配列パラメータを伝達する方法と、COMからパラメータを取得する方法を紹介します.このセクションでは、COMでJSが導入した配列を変更する方法を紹介します.
2.JS配列値を変更する場合は、まずGetIDs OfNamesを通じて指定された番号要素のdispidを取得する.Invoke()を呼び出し、Dispactch_に入る.PropertyPutフラグは書き込み動作を示し、DispParaams構造においてこの元素の種類と元素の値を指定します.
3.COM中C++定義
STDMETHODIMP CJsAtl::ArrayModiy(VARIANT vArray)
{
         SetArrayNumberOfIndex(vArray.pdispVal, 0, 123); //      [0]   ,  
         return S_OK;
}
 
// ***
//   Javascript             
// ***
HRESULT SetArrayNumberOfIndex(IDispatch* pDisp, int index, int value)
{
         CComVariant varName(index, VT_I4);
         DISPID dispId;
         CComVariant varValue;
         HRESULT hr = 0;
         varName.ChangeType(VT_BSTR); //           ,   GetIDsOfNames
         hr = pDisp->GetIDsOfNames
                  (IID_NULL, &varName.bstrVal, 1, LOCALE_USER_DEFAULT, &dispId);
         if (FAILED(hr)) 
                  return hr;
        
         DISPID dispidPut = DISPID_PROPERTYPUT; // put  
         DISPPARAMS dispparams;
         dispparams.rgvarg = new VARIANTARG[1]; //    rgvarg
         dispparams.rgvarg[0].vt = VT_I4; //     
         dispparams.rgvarg[0].intVal = value; //    
         dispparams.cArgs = 1; //     
         dispparams.cNamedArgs = 1; //     
         dispparams.rgdispidNamedArgs = &dispidPut; //   DispId,        put  
 
         hr = pDisp->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTY PUT, &dispparams, NULL, NULL, NULL);
         return hr;
}
 

4.JS呼び出し
function test_set_first()
{
       var array = new Array(0, 1, 2, 3);
       try {
              var obj = document.getElementByIdx_xx_x("obj");
              obj.ArrayModiy(array);
              alert("first element: " + array[0]);
       } catch (e) {
              alert("JS ERROR: " + e.message);
       }
}

5.試験実行
元配列:{0,1,2,3}
修正後:{123,1,2,3}