2009-08-19 74 views
4

我的應用程序有幾個模塊,每個模塊都位於mainform的一個選項卡中。 使用對話框時,可以方便地調用ShowModal,因爲您知道對話框何時完成。但對於用戶來說,它並不好,因爲它會鎖定整個程序,直到對話框關閉。使用Show僞造模態對話框?

我想有一個本地模式對話框。所以一個模塊可以打開一個對話框,它只鎖定當前模塊。用戶仍然可以切換到另一個模塊並繼續工作。如果用戶返回到第一個模塊,那麼在用戶可以繼續在該模塊中工作之前,對話框在那裏等待關閉。

我必須做出某種框架爲此,在應用程序中所有的對話框可以使用。 我有一個所有對話框TAttracsForm的基類,我想這裏是添加我的Show()方法的地方。

這應該只在當前模塊鎖定訪問所有WinControls的。 它應該模擬對ShowModal()的調用。我怎樣才能做到這一點?

問候

回答

1

我其實現在幾乎實現本地模式對話框。 它是在TForms Enabled屬性設置爲False的情況下構建的,整個Form從輸入被鎖定。而我的模塊只是TForm的後代。

是決定哪些模塊我ViewManager類是目前的加/關閉模塊等了2種新的方法。 LockCurrentView和UnLOckCurrentView。

function TViewManager.LockCurrentView: TChildTemplate; 
begin 
    Result := CurrentView; 
    Result.Enabled := False; 
    Result.VMDeactivate;   // DeActivate menus and toolbas for this module 
end; 

procedure TViewManager.UnLockCurrentView(aCallerForm: TChildTemplate); 
begin 
    aCallerForm.VMActivate;   // Activate menus and toolbas for this module 
    aCallerForm.Enabled := True; 
end; 

TAttracsForm是所有對話框的基類。我重寫FormClose並添加一個新方法ShowLocalModal來調用,而不是ShowModal。我還必須添加一個TNotifyEvent OnAfterDestruction,以在對話框關閉時調用。

procedure TAttracsForm.FormClose(Sender: TObject; var Action: TCloseAction); 
begin 
    if Assigned(fCallerForm) then  
    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; 

一些簡單的對話框測試看起來很有希望。所以模塊只需要調用ShowLocalModal(myMethod),它有一個TNotifyEvent作爲參數。該對話框關閉時調用此方法。

2

你必須做到以下幾點:

  1. 有一個標識爲每個模塊
  2. 有一個標誌,是否活動爲每個模塊
  3. 有一個標誌存儲附加對話框的模式。如果它是模態的並且模塊處於活動狀態,則在相應的事件處理程序中調用show方法。請記住在每個對話框的onshow和onclose事件中更新這些值。

您可能需要對此建議進行微調,直到您達到所需的確切功能。

+0

我意識到在對話框和模塊中必須添加一些屬性。讓我們暫時忘記這一點。 但主要問題是如何在顯示對話框時在本地禁用模塊中的所有組件。循環瀏覽它們是一個糟糕的解決方案,因爲它們太多了。 – 2009-08-19 12:35:45

+1

根據您的控件所包含的控件的類型,您應該能夠禁用父控件。例如,如果您的組件都在TTabSheet中,禁用TTabSheet將阻止訪問所有這些控件。 – 2009-08-19 13:03:37

+1

剛剛有另一個想法。我可以簡單地將模塊(從TForm繼承)的Enabled屬性設置爲False來鎖定它上面的所有組件? 一個快速測試似乎很有前途:) – 2009-08-19 13:08:52

2

你還是想用「你知道什麼時候該對話框完成」的比喻來實現這一點? 所以像

DoSomethingBeforeDialog(); 
Form:=TFakeFormDialog.Create(Nil); 
try 
    Form.FakeShowModal(); 
finally 
    Form.Free; 
end; 
DoSomethingAfterDialog(); 

如果答案是肯定的,你會嘗試用線程來實現這一點,像谷歌Chrome瀏覽器執行此與標籤頁。但是,如果沒有線程只有你能趕上消息處理,像這樣

function TFakeModalDlg.FakeShowModal(FormParent: TWinControl): boolean; 
begin 
    Parent:=FormParent; 
    SetBounds((FormParent.Width - Width) div 2, (FormParent.Height - Height) div 2, 
    Width, Height); 
    Show; 
    while NoButtonIsPressed() do 
    begin 
    Application.HandleMessage; 
    end; 
    Hide; 
end; 

A碼和你甚至有下面的代碼...

Form:=TFakeModalDlg.Create(Nil); 
try 
    (Sender as TButton).Caption:='Going modal...'; 
    Form.FakeShowModal(TabSheet1); 
    (Sender as TButton).Caption:='Returned from modal'; 
finally 
    Form.Free; 
end; 

稱爲從標籤乘次,但問題是這些的「對話框」應按「堆棧順序」關閉,即與其顯示的順序相反。我認爲這是不可能強迫用戶關閉形式開發的優先順序:)