Сообщение Delphi CMExit не отправляется при закрытии модального диалога? - PullRequest
2 голосов
/ 06 апреля 2009

В одной части приложения, над которым я работаю, есть элемент управления формой, который выполняет проверку при получении сообщения CMExit, что в точности соответствует тому, как в документации Delphi говорится об этом (этот пример кода взят из справки Delphi). файлы):

procedure TDBCalendar.CMExit(var Message: TWMNoParams);
begin
 try
  FDataLink.UpdateRecord;                          { tell data link to update database }
 except
  on Exception do SetFocus;                      { if it failed, don't let focus leave }
 end;
 inherited;
end;

Целью этого является выполнение проверки, как только элемент управления теряет фокус. Так, например, если бы я нажал кнопку «ОК», элемент управления формы потерял бы фокус, этот метод запустился бы и, в случае исключения, вернул бы фокус к этому элементу управления формы. (Таким образом, событие «click» на кнопке OK никогда не будет проходить, и диалоговое окно никогда не закроется).

У меня проблема в том, что этот элемент управления формы находится внутри модального диалогового окна. Нажатие ОК действительно отправляет сообщение CMExit и приводит к обновлению записи (и проверке). Однако нажатие клавиши Enter в элементе управления формы приводит к закрытию модального диалогового окна без отправки сообщения CMExit . Как будто контроль формы никогда не «теряет фокус». Это означает, что диалоговое окно не только закрывается без формы, которая фактически проверяет данные, но и набор данных также не обновляется.

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

(Я предполагаю, что CMExit не запускается, потому что элемент управления никогда на самом деле не теряет фокус. Форма закрыта, но элемент управления формы все еще "фокусируется" на закрытой форме.)

1 Ответ

7 голосов
/ 06 апреля 2009

Закрытие формы не обязательно запускает событие TControl при выходе. Например, пользователь может нажать Alt-F4.

Я бы предложил перенести проверку в отдельный процесс и вызвать этот отдельный процесс как из событий при закрытии , так и при закрытии.

Приведенный ниже код должен работать без особых изменений:

function TDBCalendar.UpdateSuccessful: boolean;
begin
  { tell data link to update database }
  { if successful, return True, else return False }
  { this function must be Public if a form is gonna check this value }
  Result := True;
  try
    FDataLink.UpdateRecord;
  except on Exception do
    Result := False;
  end;
  inherited;
end;

procedure TDBCalendar.CMExit(var Message: TWMNoParams);
begin
  //if not valid, then don't let them leave
  if not(UpdateSuccessful) then begin
    SetFocus;
  end;
end;

///////////////////////////////////////////
//on the form that contains your control...
///////////////////////////////////////////

procedure TMyForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  //if not valid, then don't let them close the form
  if not(dbcal.ControlIsValid) then begin
    Action := caNone;
  end
  else begin
    inherited;
  end;
end;
...