7

Delphi の部分:

イベントを持つクラスがあり、そのイベントから、インターフェイスされたオブジェクトを渡すプロシージャを呼び出す必要があります。Delphi では問題なく動作しますが、Pascal Script での宣言には問題があります。

背景に -IGPGraphicsインターフェイスは の一部であり、Delphi GDI+ libraryメソッドなしでは次のように定義されます。

type
  IGdiplusBase = interface
  ['{24A5D3F5-4A9B-42A2-9F60-20825E2740F5}']
  IGPGraphics = interface(IGdiPlusBase)
  ['{57F85BA4-CB01-4466-8441-948D03588F54}']

以下は、Pascal Script で行う必要があることを単純化した Delphi 疑似コードです。

type
  TRenderEvent = procedure(Sender: TObject; const GPGraphics: IGPGraphics) of object;
  TRenderClass = class(TGraphicControl)
  private
    FOnRender: TRenderEvent;
  public
    property OnRender: TRenderEvent read FOnRender write FOnRender;
  end;

// when the TRenderClass object instance fires its OnRender event I want to call 
// the RenderObject procedure passing the IGPGraphics interfaced object to it; I
// hope I'm doing it right, I'm just a newbie to this stuff - but it works so far
// in Delphi (since I didn't get it to work in Pascal Script)

procedure TForm1.RenderClass1Render(Sender: TObject; const GPGraphics: IGPGraphics);
begin
  RenderObject(GPGraphics, 10, 10);
end;

// what I need in Pascal Script is between these two lines; just pass the interface
// object from the event fired by component to the procedure called from inside it

procedure RenderObject(const GPGraphics: IGPGraphics; X, Y);
begin
  // and here to work with the interfaced object somehow
end;

Pascal スクリプトのコンパイル部分:

私の目的は、イベントを持つクラスを Pascal Script で使用できるようにすることであり、そのインターフェイス オブジェクトを上記のようにそのプロシージャに渡す必要があるため、最初にコンパイル時にこれを宣言しようとしました (ただし、これが正しい方法です):

// the interface
PS.AddInterface(Cl.FindInterface('IUnknown'), StringToGuid('{57F85BA4-CB01-4466-8441-948D03588F54}'), 'IGPGraphics');
// the type for the event
PS.AddTypeS('TRenderEvent', 'procedure(Sender: TObject; const GPGraphics: IGPGraphics)');
// and the class with the event itself
with PS.AddClassN(PS.FindClass('TGraphicControl'), 'TRenderClass') do
begin
  RegisterProperty('OnRender', 'TRenderEvent', iptrw);
end;

Pascal Script ランタイム部分:

私が間違いなく迷っているのは、ランタイム部分です。インターフェイス化されたオブジェクトをコール スタックから取得して、RenderObject プロシージャに渡す方法がわかりません。

function RenderClassProc(Caller: TPSExec; Proc: TPSExternalProcRec; Global, 
  Stack: TPSStack): Boolean;
var
  PStart: Cardinal;
begin
  PStart := Stack.Count-1;
  Result := True;
  if Proc.Name = 'RENDEROBJECT' then
  begin
    // how do I get the interfaced object from Stack (or whatever else) and pass 
    // it to the RenderObject proc here ? I can't find anything related about it
    // except functions that has no parameter index
    RenderObject(Stack.Get ?, Stack.GetInt(PStart-2), Stack.GetInt(PStart-3));
  end;
end;

質問は次のとおりです。

この場合のコンパイルとランタイム部分を正しく定義する方法を誰かに提案してもらえますか?

PSそのInno-Setupタグで申し訳ありませんが、おそらくそこの誰かがInnoSetupをこのようにカスタマイズしようとしました.

どうもありがとう!

4

2 に答える 2

1

あなたが何を求めているのか理解できれば、インターフェースをパラメーターとしてメソッドに渡したいと思うでしょう。残念ながら、それに対する正確な答えはありませんが、PascalScriptのグローバル変数にインターフェイスを割り当てる方法は知っています。カスタリアでのやり方は次のとおりです。

PSScript OnCompileイベントで、PS.Comp.AddInterfaceを使用してインターフェイスを追加してから、必要な各メソッドを追加します。その後、インターフェースタイプの変数を追加します。たとえば、次のようになります。

with PS.Comp.AddInterface(ARunner.Comp.FindInterface('IUnknown'),
  StringToGUID('{0346F7DF-CA7B-4B15-AEC9-2BDD680EE7AD}'),
  'ICastaliaMacroClipboardAccess') do
begin
  RegisterMethod('function GetText: string', cdRegister);
  RegisterMethod('procedure SetText(AText: string)', cdRegister);
end;
PS.AddRegisteredVariable('Clipboard', 'ICastaliaMacroClipboardAccess');

次に、OnExectuteイベントで、以前に作成した変数をインスタンスにバインドします。

P := PS.GetVariable('Clipboard'); //P is type PIFVariant
SetVariantToInterface(P, Implementing object as ICastaliaMacroClipboardAccess);    

これを行うと、スクリプトは変数を介してインターフェイスオブジェクトにアクセスできるため、この場合、スクリプトにClipboard.GetTextの呼び出しを含めることができ、期待どおりに機能します。

それはテストされ、動作します。

さて、TPSScript.ExecuteFunctionを使用して、上からPIFVariantを渡して、必要なものに近づけることができるかもしれないと推測します。しかし、それは私がテストしたものではありません。

幸運を!

于 2012-07-16T17:07:32.603 に答える