سؤال

أحاول تلقي وقيم معقدة محتملة من خلال TwebBrowser (باستخدام tembeddedwb) مع الكائن الخارجي المقدم. علي سبيل المثال؛ في 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;

أنا لست على دراية كوم ولست متأكدا من كيفية العمل مع هذا.

سيكون موضع تقدير أي مساعدة.

هل كانت مفيدة؟

المحلول

يمكنك التعامل مع كائن JScript تماما مثل أي كائن OleVariant COM آخر. هناك عدد قليل من gotchas من حيث المصفوفات (وعن أي كائن 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;

نصائح أخرى

على الرغم من أنني لم أفعل مباشرة ما تحاوله مباشرة.

مع وجود متغير يمكنك بالفعل الوصول إلى الأساليب والممتلكات بشكل حيوي.

يشك في أنه يجب أن تكون قادرا على الوصول إلى كل شيء مباشرة.

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

لن تحصل على أخطاء تجميع الوقت إذا حصلت على أشياء خاطئة حتى تكون حذرا.

على سبيل المثال، يجمع التعليمات البرمجية التالية، ولكن سيعطي خطأ وقت التشغيل لعملية متغير غير صالحة حيث لا يوجد شيء معين ديناميكيا لهذا المتغير.

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

هل فكرت في تسلسل بياناتك المعقدة باستخدام تدوين كائن JavaScript (JSON)؟ سيسمح لك ذلك بتسلسل كائنات JavaScript التعسفي، وتمريرها كسلسلة بسيطة من الشخصيات وإعادة تشكيلها في رمز دلفي.

يحتوي Delphi 2009 على دعم JSON كجزء من DataSnap الجديد (غير متأكد من مدى سهولة استخدام المستقل). هناك أيضا عدد من تطبيقات دلفي JSON هناك قد تكون مفيدة:

الدفع lkjson. و json - superobject.

أنا لا خبير في JSON، لكن يبدو أنه حل بسيط وفعال نسبي لتبادل البيانات عبر اللغة.

ديفيد

كائنات في جافا سكريبت هي صفائف النظامية, مع أسماء الممتلكات كونها مفاتيح: obj.prop أي ما يعادل obj['prop'].

الصفائف العادية هي ببساطة كائنات تخزين الفهارس كخصائص، لذلك يتصرفون مثل صفيفات متفرقة.

السماح olevariants delphi بالوصول المباشر إلى العقارات، ولكن فقط عندما تكون أسمائهم صالحة معرفات دلفي, ، لذلك لا يحب استخدام مؤشر رقمي كاسم خاصية (أي obj.0 لا يترجم).

يمكن قراءة خصائص مع أسماء المعرف غير الصالحة الاحتجاج DISPATCH_PROPERTYGET كما في استجابة ريان.

ومع ذلك، تشمل دلفي الروتينات المناسبة في ComObjوحدة لتحويل هذا مباشرة:

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;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top