2009-08-19 17 views
4

Мое приложение имеет несколько модулей, каждый на одной вкладке на основной форме. При использовании диалога удобно вызвать ShowModal, потому что вы знаете, когда диалог завершен. Но для пользователя это не хорошо, поскольку он блокирует всю программу, пока диалог не закрывается.Поддельный модальный диалог с помощью Show?

Я хочу иметь локально модальный диалог. Таким образом, один модуль может открыть диалог, и он блокирует только текущий модуль. Пользователь все еще может переключиться на другой модуль и продолжить работу. Если пользователь вернется к первому модулю, диалог там ждет закрытия, прежде чем пользователь сможет продолжить работу в этом модуле.

Я должен создать для этого рамки, которые могут использовать все диалоги в приложении. У меня есть базовый знак для всех диалогов TAttracsForm, и я думаю, что здесь есть место, где можно добавить мой метод Show().

Это должно блокировать доступ ко всем wincontrols только в текущем модуле. Он должен имитировать вызов ShowModal(). Как я могу это достичь?

С уважением

ответ

1

Я фактически практически реализовал локальные модальные диалоги. Он построен вокруг этого, когда свойство TForms Enabled установлено в False, вся форма заблокирована от ввода. И мои модули - только потомок от 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 - базовое поле всех диалогов.I Переопределить 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

Я понимаю, что есть некоторые свойства, которые необходимо добавить в диалоговом окне и модуле. Давайте забудем об этом на мгновение. Но основная проблема заключается в том, как я могу локально отключить все компоненты модуля, пока отображается диалог. Это плохое решение - просто перебирать их, потому что их так много. –

+1

В зависимости от типа элемента управления, в котором содержатся элементы управления, вы должны просто отключить родителя. Например, если ваши компоненты все находятся на TTabSheet, отключение TTabSheet предотвращает доступ ко всем этим элементам управления. –

+1

Просто появилась другая идея. Могу ли я просто установить для свойства Enabled значение False модуля (который наследуется от TForm), чтобы заблокировать все компоненты на нем? Быстрый тест кажется многообещающим :) –

2

Вы все еще хотите реализовать это с помощью «знаешь, когда диалог закончен» метафорой? Так как

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

если ответ да, то вы бы попытаться осуществить это с помощью нитей, как Google 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; 

И вы даже ниже код ...

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; 

называемые умножают раз из вкладок, но проблема заключается в их «диалоги» должны быть закрыты в «порядке стека», т.е. наоборот, в порядке, в котором они были показаны. Я думаю, что невозможно заставить пользователей закрывать формы в порядке предпочтений разработчиков :)

Смежные вопросы