Выход из формы с использованием ModalResult - PullRequest
14 голосов
/ 17 мая 2011

У меня есть куча форм, и я хочу автоматизировать их, чтобы они сами открывались и закрывались.

Я знаю, как заставить их открываться (с помощью функции OnActivate), но у меня возникают проблемы с их закрытием.

Так, например, у меня есть

procedure TProgressForm.FormActivate(Sender: TObject);
begin
  inherited;
  if FModItem.IsInQueue then
    begin
      RunBtnClick(Self);
      ModalResult := mrOK;
    end;    
end;

, которая запускает функцию. Я хочу закрыть окно после запуска функции, что и делает ModalResult.

(я также пытался добавить строку ModalResult в самом конце процедуры RunBtnClick, но это тоже не сработало)

и я создаю форму следующим образом:

ProgForm := TProgressForm.Create(Self, FModItem);
Self.Visible := False;
try
 if ProgForm.ShowModal = mrOK then
  begin
    Left := ProgForm.Left;
    Top := ProgForm.Top;
  end;

Мне удалось создать кнопки для закрытия формы, просто добавив mrOK к Модальному результату в Инспекторе объектов, но я не могу сделать это явно

Кто-нибудь может понять, почему он не работает?

Спасибо

Ответы [ 4 ]

15 голосов
/ 18 мая 2011

Причина не работает в том, что VCL активно устанавливает ModalResult в 0 в TCustomForm. ShowModal после показа формы, но до начала проверки изменений в ModalResult. Так что в OnActivate и в OnShow, вы должны рано.

Решением является задержка уведомления. Это может быть сделано PostMessage следующим образом:

const
  UM_ACTIVATED = WM_USER + 1;

type
  TProgressForm = class(TForm)
    procedure FormActivate(Sender: TObject);
  private
    procedure UMActivated(var Message: TMessage); message UM_ACTIVATED;
  end;

...

procedure TProgressForm.FormActivate(Sender: TObject);
begin
  PostMessage(Handle, UM_ACTIVATED, 0, 0);
end;

procedure TProgressForm.UMActivated(var Message: TMessage);
begin
  { Your code here }
  ModalResult := mrOk;
end;

Источник: NLDelphi

6 голосов
/ 18 мая 2011

Я бы переопределил ShowModal и сделал бы тесты, которые вы сейчас делаете в OnActvate оттуда. Это имеет два больших преимущества:

  • Не показывает форму вообще , если ее не нужно показывать. Инициирование закрытия формы с OnActivate вызывает «мерцание» формы на экране: оно отображается и немедленно удаляется.
  • Не полагается на код, который не находится под вашим контролем. Вам больше не нужен порядок операций в предке ShowModal, потому что вы вызываете его только в том случае, если форма действительно должна быть показана.

Конечно, использование элемента GUI (формы) таким способом является небольшим запахом кода, потому что он в основном использует GUI без необходимости взаимодействия с пользователем. Это, несомненно, может быть реорганизовано для использования промежуточной функции, которая возвращает mrOk и делает то, что RunBtnClick() делает без необходимости в GUI, и создает Form только при необходимости. Я полагаю, это ситуация с выгодой для себя.

Код:

TMyForm = class(TForm)
....
public
  function ShowModal:Integer;override;
end;

function TMyForm.ShowModal:Integer;
begin
  if FModItem.IsInQueue then
    begin
      RunBtnClick(Self);
      Result := mrOK;
    end
  else
    Result := inherited ShowModal;
end;
3 голосов
/ 18 мая 2011

Событие OnActivate инициируется до сброса ModalResult в mrNone в TCustomForm.ShowModal. Это означает, что изменение ModalResult в вашем обработчике OnActivate игнорируется.

  function TCustomForm.ShowModal: Integer;
  Show;
  try
    SendMessage(Handle, CM_ACTIVATE, 0, 0);  << Your onActivate is called here
    ModalResult := 0; << ModalResult is reset
2 голосов
/ 18 мая 2011

Посмотрите на TCustomForm.ShowModal (внутри forms.pas): ModalResult сначала не проверяется до после сообщения CM_ACTIVATE (указанное сообщение вызывает ваш вызов OnActivate); фактически он устанавливается на 0 сразу после возврата вызова OnActivate, поэтому неудивительно, что ваше назначение не работает.

Я не хочу слишком много возиться с этим (ваш код определенно не проходит тест на запах), но вы можете попробовать добавить что-то вроде:

if ModalResult=0 then 
     SendMessage(Handle, CM_ACTIVATE, 0, 0);

в начало вашего обработчика событий.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...