Frage

Ich versuche, möglicherweise zu empfangen und komplexe Werte durch TWebBrowser (mit TEmbeddedWB) mit dem mitgelieferten externen Objekt. Zum Beispiel; in javascript würde ich versuchen, die freigelegte Methode mit einem Array als Parameter zu verwenden:

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);

Überprüfen der VarType von diesen beiden Beispielen sagt mir, es ist ein IDispatch.

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

Ich bin nicht ganz vertraut mit COM und ich bin nicht sicher, wie man damit arbeiten.

Jede mögliche Hilfe würde geschätzt.

War es hilfreich?

Lösung

Sie können die JScript-Objekt wie jedes andere OleVariant COM-Objekt behandeln. Es gibt ein paar Fallstricke in Bezug auf Arrays (und fast jedes JScript-Objekt ist im Wesentlichen eine spärliche Array).

Nach dem JScript-Objekt in einen OleVariant bekommen, können Sie einfach nennen es wie jeder normaler Code (ohne Kompilierung natürlich Prüfung).

Hier ist ein Code für Arrays zu tun:

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;

Andere Tipps

Obwohl ich nicht direkt getan, was Sie Sie versuchen.

mit einer Variante Sie können Sie tatsächlich Zugang Methoden und Eigenschaften dynamisch.

Im Grunde nehme ich an Sie sollte alles der Lage sein, direkt zugreifen zu können.

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

Sie werden keine Zeit bekommen Fehler kompilieren, wenn Sie die Dinge falsch so vorsichtig sein.

Zum Beispiel der folgende Code kompiliert, wird aber einen Laufzeitfehler ungültiger Variante Betrieb geben, da es nichts zu dieser Variablen dynamisch zugewiesen ist.

var
 vo : OleVariant;
 v  : Variant;
begin
  v.DoThis;
  vo.DoThat;
end;

Haben Sie darüber nachgedacht Ihre komplexen Daten Serialisierung JavaScript Object Notation (JSON)? Dies würde erlauben Sie beliebige JavaScript-Objekte serialisiert werden, so dass sie als einfache Zeichenfolge übergeben und sie in Delphi Code wiederherzustellen.

Delphi 2009 hat die Unterstützung für JSON als Teil des neuen DataSnap (nicht sicher, wie einfach es ist, Standalone zu verwenden). Darüber hinaus gibt es eine Reihe von Delphi JSON-Implementierungen gibt, die nützlich sein könnten:

lkjson und JSON - SuperObject

Ich bin kein Experte in JSON, aber es scheint eine relativ einfache und effiziente Lösung für die sprachübergreifende Datenaustausch zu sein.

David

Objekte in Javascript sind assoziative Arrays , mit Eigenschaftsnamen Schlüssel sein: entspricht obj.prop obj['prop'] ist

.

Regelmäßige Arrays sind einfach Objekte Indizes als Eigenschaften zu speichern, so verhalten sie sich wie spärlich Arrays.

Delphi OleVariants ermöglichen den direkten Zugriff auf die Eigenschaften, aber nur dann, wenn ihre Namen gültig sind Delphi-Bezeichner , so dass es nicht wie einen numerischen Index als Eigenschaftsnamen verwenden (dh obj.0 nicht kompilieren).

Eigenschaften mit ungültigen Bezeichnernamen können Aufruf DISPATCH_PROPERTYGET wie in Ryans Antwort .

Allerdings Delphi gehört richtige Routinen in ComObjunit dazu direkt zu tun:

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;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top