2

提供された外部オブジェクトを使用して、(TEmbeddedWB を使用して) TWebBrowser を介して複雑な値を受信し、場合によっては送信しようとしています。例えば; javascript では、配列をパラメーターとして公開されたメソッドを使用しようとします。

var test = [123, 'abc'];
external.someFunction(test);

//Or something more complex
var complexObject = {
  someMethod : function(){ return 1; },
  someProperty : 123,
  someArray : ['xyz', 3.14]
}
external.someFunction(complexObject);

これらの両方の例の VarType を確認すると、IDispatch であることがわかります。

function TSomeClass.someFunction(var Param : OleVariant) : OleVariant;
var
  vType : Integer;
begin
  vType := (VarType(Param) and VarTypeMask); //Says 9 (varDispatch)
  Result := true;
end;

私は COM に完全に精通しているわけではなく、これをどのように操作すればよいかわかりません。

どんな助けでも大歓迎です。

4

4 に答える 4

3

JScript オブジェクトは、他の OleVariant COM オブジェクトと同様に扱うことができます。配列に関しては、いくつかの落とし穴があります (ほぼすべての JScript オブジェクトは、基本的にスパース配列です)。

JScript オブジェクトを OleVariant に取得したら、通常のコードと同じように呼び出すことができます (もちろん、コンパイル時のチェックは必要ありません)。

配列を処理するためのコードを次に示します。

type
  TJScriptArray = class
  private
    FArray:   IDispatchEx;
    FCount:   Integer;
    function  GetProperty( const AName: String ): OleVariant;
    function  GetItem(Index: Integer): OleVariant;
  public
    constructor Create( AObj: OleVariant );
    destructor  Destroy; override;
  public
    property  Count: Integer read FCount;
    property  Item[Index: Integer]: OleVariant read GetItem; default;
  end;

function  VarToDispatchEx( const AObject: OleVariant ): IDispatchEx;
begin
  Result := nil;
  if VarType( AObject ) <> varDispatch then
    Exit;
  Supports( IDispatch(AObject), IDispatchEx, Result );
end;

function  IsJScriptArray( const AObject: OleVariant ): Boolean;
var
  temp: IDispatchEx;
begin
  temp := VarToDispatchEx( AObject );
  Result := temp <> nil;
end;


constructor TJScriptArray.Create(AObj: OleVariant);
begin
  inherited Create;
  FArray := VarToDispatchEx( AObj );
  if FArray = nil then
    raise Exception.Create( 'TJscriptArray called with invalid parameters.' );
  FCount := GetProperty( 'length' );
end;

destructor TJScriptArray.Destroy;
begin
  inherited Destroy;
end;

function TJScriptArray.GetItem(Index: Integer): OleVariant;
begin
  if Index > FCount then
    raise Exception.Create( 'Index out of bounds.' );
  Result := GetProperty( IntToStr( Index ) );
end;

function TJScriptArray.GetProperty(const AName: String): OleVariant;
var
  sz: WideString;
  id: Integer;
  res: Variant;
  ei: TExcepInfo;
  params: TDispParams;
  hr: HResult;
begin
  {
    ACTION: return the specified property from the jscript array
    NOTE:   since a jscript array is a sparse array there may be
            gaps. In that case a null variant is returned. This is
            signalled by the name (id) not existing.
  }
  sz := AName;
  hr := FArray.GetDispID( PWideChar(sz), 0, id );
  if hr = disp_e_UnknownName then begin
    Result := Null;
    Exit;
    end
  else
    OleCheck( hr );

  VarClear( res );
  FillChar( ei, sizeof(ei), 0 );
  FillChar( params, sizeof(params), 0 );
  OleCheck( FArray.InvokeEx( id, 0, dispatch_PropertyGet, @params, @res, @ei, nil ) );
  Result := res;
end;
于 2009-06-01T13:15:27.123 に答える
2

私はあなたがしようとしていることを直接していませんが。

Variantを使用すると、実際にメソッドとプロパティに動的にアクセスできます。

基本的に、すべてに直接アクセスできるはずだと思います。

Param.Someproperty
Param.SomeArray[1]
Param.SomeMethod();

間違えてもコンパイル時のエラーは発生しませんのでご注意ください。

たとえば、次のコードはコンパイルされますが、その変数に動的に割り当てられるものがないため、無効なバリアント操作の実行時エラーが発生します。

var
 vo : OleVariant;
 v  : Variant;
begin
  v.DoThis;
  vo.DoThat;
end;
于 2009-05-29T04:10:25.783 に答える
1

JavaScript Object Notation (JSON) を使用して複雑なデータをシリアル化することを検討したことがありますか? これにより、任意の JavaScript オブジェクトをシリアル化し、単純な文字列として渡し、Delphi コードで再構成することができます。

Delphi 2009 は、新しい DataSnap の一部として JSON をサポートしています (スタンドアロンでの使用がどれほど簡単かはわかりません)。また、役立つ可能性がある Delphi JSON の実装もいくつかあります。

lkjsonJSON をチェックアウト - SuperObject

私は JSON の専門家ではありませんが、JSON は言語間のデータ交換のための比較的単純で効率的なソリューションのようです。

デビッド

于 2009-05-29T05:28:44.987 に答える
0

Javascript のオブジェクトは連想配列であり、プロパティ名がキーです:obj.propは と同等obj['prop']です。

通常の配列は、インデックスをプロパティとして格納する単なるオブジェクトであるため、スパース配列のように動作します。

Delphi の OleVariants は、プロパティへの直接アクセスを許可しますが、その名前が有効なDelphi 識別子である場合に限られるため、数値インデックスをプロパティ名として使用することは好まれませobj.0ん (つまり、コンパイルされません)。

Ryan の response のDISPATCH_PROPERTYGETように、無効な識別子名を持つプロパティを呼び出して読み取ることができます。

ComObjただし、Delphi には、これを直接行うためのユニットに適切なルーチンが含まれています。

uses ComObj;

...

function TSomeClass.someFunction(var Param : OleVariant) : OleVariant;
begin
  ShowMessage(Param.someProperty); // 123
  ShowMessage(GetDispatchPropValue(Param, 'someProperty')); // 123

  ShowMessage(Param.someArray.length); // 2
  ShowMessage(GetDispatchPropValue(Param.someArray, '0')); // xyz

  Result := true;
end;
于 2013-07-24T20:05:47.673 に答える