Вопрос вроде бы простой, но стопорнулся на нём. В сети много примеров на эту тему, но перепробовав всё, я понял, что мне нужен свой вариант)))
Проблема заключается в том, что вызвав модальную форму, программа ждёт некоторого действия от пользователя, например нажатия на кнопку ok или Cancel. И если прогнать отладчиком, то какой бы код ни написать после ShowModal – всё это не исполняется, пока не нажмешь извне так сказать на одну из кнопок.
Меня такой вариант явно не устраивал, и тогда я объявил одно свойство ReadyToClose и при присвоении ему значения True – таймер закрывает эту модальную форму. Так сказать диверсионно подрывная работа изнутри))
Зачем? В моём конкретном случае нужно было показывать анимацию во время копирования файлов и закрывать её, когда соответствующий поток закончит свою работу. Закрывать программно.
Итак, пусть у нас есть некая модальная форма….
Вот код её юнита…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
unit uAnimateForm; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls,ShellAnimations, Vcl.StdCtrls, Vcl.ExtCtrls; type TfAnimateForm = class(TForm) AnimateCopyFiles: TAnimate; CloseTimer: TTimer; procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure CloseTimerTimer(Sender: TObject); procedure FormCreate(Sender: TObject); private FReadyToClose:Boolean; public property ReadyToClose:Boolean read FReadyToClose write FReadyToClose; end; //var // fAnimateForm: TfAnimateForm; implementation {$R *.dfm} procedure TfAnimateForm.CloseTimerTimer(Sender: TObject); begin if ReadyToClose then begin AnimateCopyFiles.Active:=False; Self.Close; end; end; procedure TfAnimateForm.FormClose(Sender: TObject; var Action: TCloseAction); begin Action:=caNone; end; procedure TfAnimateForm.FormCreate(Sender: TObject); begin //CloseTimer.Enabled:=true; end; end. |
Теперь в некоторой тестовой программе сделаем следующее
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
procedure TForm1.bTestClick(Sender: TObject); var AnimateForm:TfAnimateForm; begin AnimateForm:=TfAnimateForm.Create(Self); AnimateForm.AnimateCopyFiles.Active:=true; AnimateForm.ReadyToClose:=true; AnimateForm.CloseTimer.Enabled:=true; AnimateForm.ShowModal; end; |
И всё прекрасно закрывается… Думаю, что есть ещё с десяток способов как это сделать. Но на мой взгляд – просто и элегантно.
Способ №2
Но честно, сказать, способ этот срабатывал не всегда, поэтому пришлось уйти от вызова модального окна и воспользоваться обычным, а блокировку элементов делать таким образом
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
procedure TPasteThreadDBTreeGreedView.ShowCopyAnimate; begin (VisualFrame.AnimateForm.CloseTimer.Enabled:=true); (VisualFrame.AnimateForm.Show); //Деактивируем объект-владелец if Assigned(VisualFrame.ObjectToDisable) then if (VisualFrame.ObjectToDisable is TForm) then (VisualFrame.ObjectToDisable as TForm).Enabled:=false; end; |
Активация обратно
1 2 3 4 5 6 7 8 9 |
procedure TPasteThreadDBTreeGreedView.HideCopyAnimate; begin VisualFrame.AnimateForm.Close; if Assigned(VisualFrame.ObjectToDisable) then if (VisualFrame.ObjectToDisable is TForm) then (VisualFrame.ObjectToDisable as TForm).Enabled:=true; end; |