2009-08-26 6 views
0

저는 여전히 로컬 모달 대화 상자 (LMD)로 작업하고 있습니다. 자세한 내용은 this question을 참조하십시오. 이제는 간단한 경우에 잘 작동하지만 때로는 호출자에게 알리고 싶은 대화 상자의 결과가 있습니다. 호출이 Show()와 비동기 적이기 때문에 호출 후에 결과를 얻을 수는 없습니다.이벤트 메서드에 하나 이상의 값을 반환하려면 어떻게해야합니까?

그럼 내 질문은 방법 TModule.myEvent 메서드 TLMD_Dialog.btnOkClick 메서드에서 하나 또는 여러 값을 반환 할 수 있습니다?

나는이에 관여하는 3 개 개의 유닛을 가지고 : 당신이 TNotifyEvent 사용하지 않는, 이

// 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의 하위 항목 만 반환해야합니다. 이제 조상에서 선언 된 단일 이벤트가 있고 보낸 사람과 데이터 개체가 반환되며 후자는 포함 된 데이터 형식이 다를 수 있습니다. 처리기는 이제 if (AEventData가 TEventSpecialData)를 사용하고 그에 따라 작동 할 수 있습니다. DoOnSomething을 호출하기 전에 자손의 DoOnSomeThing 재정의에서도 FSomEventData의 값을 설정할 수 있습니다. ;-)

대체 방법 : 이벤트 데이터를 공용 속성으로 만들고 일반 이벤트의 보낸 사람을 사용하여 처리기에서이 속성으로 이동할 수 있습니다.

2

은 정말 아주 간단합니다 (TLMD_Dialog이 TAttracsForm에서 상속합니다)하지만, 정보에 대한 추가 매개 변수를 사용하여 사용자 정의 이벤트 유형 너는 돌아 오기를 원해.

(예 : ZIP 파일의 이름과 압축 수준의 파일 이름과 다른 매개 변수를 얻기위한 간단한 예 : 이제

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

를 대신이 될 수있는 당신의 Execute() 방법의 마지막 매개 변수를 선언 TNotifyEvent을 입력하면 특별한 이벤트 유형으로 선언됩니다.

이러한 기능을 구현하는 훨씬 더 좋은 방법은 인터페이스를 사용하는 것입니다. 대화 상자에 사용자 인터페이스가 전달되므로이 인터페이스를 사용하여 둘 이상의 이벤트를 처리 할 수 ​​있습니다. 예를 들어, 인터페이스는 anoth를 가질 수 있습니다. 대화 상자가 OnCloseQuery 핸들러에서 호출 할 입력 된 데이터의 유효성을 검사합니다.

+0

빠른 답변 주셔서 감사합니다! 그렇다면 TAttracsForm에서 FormClose 메소드를 재사용 할 수 없다는 뜻입니까? TLMD_Dialog에서이를 덮어 쓰고 설명 된 사용자 지정 이벤트를 사용해야합니다. 인터페이스에 대해서는 사용 방법에 대해 경험하지 못했습니다. 나는 그들을 사용하는 방법을 연구해야합니다. –

+0

자, TAttracsForm에서 현재 처리자가 수행하는 작업과 하위 클래스의 이벤트 처리기에서 호출하는 보호 된 메서드를 만들 수 있습니다. 그런 다음 추가하는 것은 한 줄입니다. 기본 클래스에는 처리기 자체에 대한 구현이 필요하지 않습니다. – mghie

관련 문제