Modaldialog не реагирует на ввод / esc

#delphi #modal-dialog

#delphi #модальный диалог

Вопрос:

У меня есть modaldialog с OK и Cancel кнопкой. Для OK я установил Default для свойства значение True, а для Cancel кнопки — Cancel свойство. ModalResult имеет значение mrOK и mrCancel соответственно.

Однако ни нажатие Enter, ни Esc клавиша на моей клавиатуре не закрывают диалоговое окно. Что я здесь пропустил?

Редактировать
Я разместил на своем сайте небольшое тестовое приложение, использующее подозрительный диалог. IDE — это RAD Studio XE3.

введите описание изображения здесь

Комментарии:

1. Вы установили для свойств ModalResult значение mrOk / mrCancel?

2. @lurd — Да, я сделал (иначе кнопки тоже не работали бы). Я добавлю информацию к своему вопросу. Спасибо за ответ.

3. Вызываете ли вы модальный диалог с помощью ShowModal метода? Просто чтобы убедиться. В противном случае я предлагаю вам создать небольшой компилируемый пример, чтобы продемонстрировать вашу проблему.

4. @lurd — Да, я вызываю ShowModal . Я разместил тестовое приложение на своем сайте .

5. Похоже, это как-то связано с TSpinEdit; Если вы добавляете TEdit в форму, то Enter и Esc работают правильно, когда TEdit сфокусирован, но не когда сфокусирован TSpinEdit.

Ответ №1:

Из вашего опубликованного примера вы можете видеть, что TSpinEdit элемент управления сфокусирован и фиксирует ключи.

Чтобы закрыть модальную форму во всех случаях, установите form KeyPreview в true и вставьте это в OnKeyPress событие:

 procedure TSelectDlg.FormKeyPress(Sender: TObject; var Key: Char);
begin
  if (Key = Char(vk_escape)) then  // #27
    CancelBtn.Click
  else
  if (Key = Char(vk_return)) then  // #13
    OkBtn.Click;    
end;
  

Комментарии:

1. Хотя я согласен, что это решает проблему (спасибо за это), остается новый вопрос: какая польза от свойств Cancel и Default , если нам приходится самим писать код для эмуляции нажатий клавиш? Кроме того, этот код также требуется, если у меня нет setfocus строки.

2. Если вы нажмете клавишу OK, чтобы сфокусироваться, вы можете выйти с помощью клавиши return без этого дополнительного кода. Это поведение Windows по умолчанию. Свойства cancel и default обрабатываются, когда нет другого сфокусированного элемента управления, захватывающего ключи.

3. Понял. Похоже, я ожидал слишком многого от свойств Cancel и Default :-). (Прошло некоторое время с тех пор, как я использовал Delphi в последний раз)

4. Это не проблема delphi, это стандартное поведение платформы

5. @DavidHeffernan Это isue Delphi. Перейдите и проверьте реализацию TSpinEdit, и вы увидите, почему. Методы, которые вы хотите проверить, — это TSpinEdit. Нажатие клавиши и запуск TSpinEdit. Является validchar.

Ответ №2:

Для справки, это должно сработать. Однако, похоже, что в TSpinEdit есть ошибка. Поскольку TSpinEdit является образцом (Vcl.Samples.Spin.pas, обратите внимание на «Образцы»), вы можете исправить это самостоятельно.

Для TSpinEdit добавьте следующее объявление метода сразу после WMCut:

    procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  

Завершите класс (Shift Ctrl C) и добавьте следующий код в WMGetDlgCode:

 procedure TSpinEdit.WMGetDlgCode(var Message: TWMGetDlgCode);
begin
  inherited;
  Message.Result := Message.Result and not DLGC_WANTALLKEYS;
end;
  

Это сообщит VCL, что элемент управления редактированием не хочет обрабатывать клавиши Enter и Escape (VK_ENTER, VK_ESCAPE). Поскольку он не обрабатывает клавиши, они будут перенаправлены на кнопки, которые затем будут вызваны на основе их настроек (по умолчанию и отмена).

Не стесняйтесь сообщать об этом в Центр качества

Комментарии:

1. Возможно, пришло время рассмотреть возможность замены этого «образца» на реальный up-down control .

2. Нравится компонент TUpDown? Существует уже некоторое время, например, с Delphi 2 или 3.

3. Сообщается как QC125891, TSpinEdit захватывает ключи vk_return и vk_escape .

4. @LURD Не могли бы вы отредактировать контроль качества, пожалуйста. Эта проблема существует со времен Delphi 7, если не даже более старых версий Delphi. В Delphi 7 установлена версия компилятора 15, но вы ввели 20, что равно для Delphi 2009.

5. @SilverWarior, 20 — это Delphi-XE6. Я не уверен, но я думаю, что предполагается добавить последнюю версию, в которой обнаруживается ошибка. В любом случае, я добавил примечание о том, что это присутствует, по крайней мере, с D7.