2009-08-26 7 views
0

私はまだローカルモーダルダイアログ(LMD)で作業しています。詳細については、this questionを参照してください。単純なケースではうまく動作しますが、ダイアログに結果が表示され、発信者に通知したい場合があります。コールはShow()と非同期であるため、コール後に結果を得ることはできません。イベントメソッドに1つまたは複数の値を返すにはどうすればよいですか?

私の質問は、メソッドTModule.myEventにTLMD_Dialog.btnOkClickメソッドから1つまたはいくつかの値を返す方法です。

私はこれに関与し3台持っている:それは実際にはかなり簡単です (TLMD_DialogがTAttracsFormから継承することに注意してください)

// Module.pas 
procedure myEvent(Sender: TObject); 

procedure TModule.btnCallDlg(Sender: TObject); 
begin 
    if Supports(lhaHandle.CurrentBoldObject, IObject, vMyObject) then 
    TModalDialog.Execute(param1, param2, myEvent); 
end; 

procedure TModule.myEvent(Sender: TObject); 
begin 
    // Some code that react on result of the LMD dialog 
end; 

// AttracsForm.pas 
type 
    TAttracsForm = class(TForm) 
    procedure FormClose(Sender: TObject; var Action: TCloseAction); 
    private 
    fCallerForm: TForm;  // May be replaced by check PopupParent but a separate variable may be safer 
    fOnAfterDestruction: TNotifyEvent; 
    published 
    procedure ShowLocalModal(aNotifyAfterClose: TNotifyEvent=nil); 
    end; 

procedure TAttracsForm.FormClose(Sender: TObject; var Action: TCloseAction); 
begin 
    if Assigned(fCallerForm) then  // fCallerForm not assinged means that ShowLocalModal is not called. The old way to show dialog is used 
    begin 
    ClientMainForm.ViewManager.UnLockCurrentView(fCallerForm as TChildTemplate); 

    if Assigned(OnAfterDestruction) then 
     OnAfterDestruction(Self); 

    Action := caFree; 
    end; 
end; 

{ Call to make a dialog modal per module. 
    Limitation is that the creator of the module must be a TChildtemplate. 
    Several modal dialogs cannot be stacked with this method.} 
procedure TAttracsForm.ShowLocalModal(aNotifyAfterClose: TNotifyEvent); 
begin 
    fCallerForm := ClientMainForm.ViewManager.LockCurrentView; // Lock current module and return it 
    PopupParent := fCallerForm; 
    OnAfterDestruction := aNotifyAfterClose; 
    Show; 
end; 

// LMD_Dialog.pas (inherit from TAttracsForm) 
class procedure Execute(aParam: IBoldObject; aNotifyEvent: TNotifyEvent); 
class procedure TLMD_Dialog.Execute(aParam: IBoldObject; aNotifyEvent: TNotifyEvent); 
begin 
    with Self.Create(nil) do 
    begin 
    // Do preparation 
    ShowLocalModal(aNotifyEvent); 
    end; 
end; 

procedure TLMD_Dialog.btnOkClick(Sender: TObject); 
begin 
    // Do something before close down 
    // Set Result of the dialog 
    Close; 
end; 
+1

ローカルモーダルダイアログではなく、モーダルモーダルまたはフォームモーダルダイアログ(システムモーダルまたはタスクモーダルダイアログ)を呼び出します。 – mghie

+0

私はいくつかの語彙を発明していますが、私にとってモーダルダイアログは、ShowModalを呼び出すことによって基礎となるGUIをロックします。私たちの考えは、アプリケーションのローカル部分、この場合はモジュールだけをロックすることです。次に、ローカルモーダルの式。 –

答えて

1

は私がたまにやる、のように、(あなたのケースの形で)基底クラスにイベントを追加している:今、あなたはコンストラクタがTEventDataまたはGiveSomeDataClass.Createを呼び出す子孫BIJをインスタンス化してみましょうことができ

//untested code, no doubt there are errors in it, it's the idea I want to pass 

type 
    TEventData = class(TObject) 
    public 
    property SomeCommonFieldForAncestorAndDescendants: String; 
    end; 

    TSomeBaseEvent = procedure (ASender: TObject; AEventData: TEventData) of object; 

    TSomeBaseClassOrForm = class(TForm) 
    protected 
    FSomeEventData: TEventData; 

    function GiveSomeDataClass: TClass; virtual; 
    procedure DoOnSomeThing; virtual; 
    public 
    constructor Create; override; 

    property OnSomething: TSomeBaseEvent; 
    end; 

。あなたの子孫は、GiveSomeDataClassをオーバーライドして、使用したいTEventDataの子孫を返すだけです。これで、祖先で宣言された1つのイベントが送信者とデータオブジェクトを返し、後者は含まれるデータの種類が異なる可能性があります。ハンドラーはif(AEventDataがTEventSpecialData)を使用し、それに応じて動作するようになりました。 DoOnSomethingを呼び出す前に、子孫のDoOnSomeThingオーバーライドであっても、FSomeEventDataの値を設定できます。 ;-)

代替:イベントデータをパブリックプロパティにし、通常のイベントから送信者を使用して、ハンドラからこのプロパティにステップインできます。

2

を、あなたは情報の追加パラメータをTNotifyEventが、カスタムイベントタイプを使用していませんあなたは帰りたい。

ファイル名と他のパラメータ(例えばZIPファイルの名前とその圧縮レベル取得するための簡単な例:

type 
    TReturnSaveZipFileDataEvent = procedure(Sender: TObject; 
    const AFileName: string; ACompressionLevel: Cardinal) of object; 

今の代わりのように、あなたのExecute()メソッドの最後のパラメータを宣言しTNotifyEventあなたの特別なイベントタイプを持っていると宣言してください

このような機能を実装するもっと良い方法は、インターフェイスを使用することです。カスタムインターフェイスはダイアログに渡されます。結果を返すだけで済みます。たとえば、インターフェイスにはanothダイアログで入力されたデータの有効性をチェックして、OnCloseQueryハンドラで呼び出します。

+0

素早くお返事ありがとうございます! しかし、私はFormCloseメソッドをTAttracsFormで再利用できないのですか? TLMD_Dialogでこれを上書きし、説明したカスタムイベントを使用する必要があります。 インターフェイスについて私はそれを使用する方法を経験していません。私はそれらを使う方法を研究しなければならない。 –

+0

さて、TAttracsFormでは、現在のハンドラが行う処理と、子孫クラスのイベントハンドラから呼び出す処理を行うメソッドを保護することができます。その後、追加するのは1行だけです。基本クラスは、ハンドラ自体の実装を持つ必要はありません。 – mghie

関連する問題