Недостаток настройки Form.KeyPreview = true?

.net windows winforms

18320 просмотра

4 ответа

Интересно, для чего на самом деле хорошо свойство Form.KeyPreview? Почему он существует и чем я «рискую», устанавливая его в true? Я предполагаю, что это должно иметь какой-то негативный эффект - иначе он не должен существовать вообще (или, по крайней мере, быть истинным по умолчанию)?

РЕДАКТИРОВАТЬ : я прекрасно знаю, что он делает. Я спрашиваю почему . Почему я должен установить его в значение true, чтобы вызвать события клавиатуры? Почему события клавиатуры не всегда запускаются для формы. Что не только это стандартное поведение?

Конкретная причина, по которой я спрашиваю: я только что установил KeyPreview = true в базовой форме моего приложения, от которой наследуются все другие формы. Я готовлюсь к неприятному сюрпризу?

Автор: Dan Byström Источник Размещён: 13.11.2019 11:29

Ответы (4)


66 плюса

Решение

Form.KeyPreviewнемного анахронизма, унаследованного от объектной модели Visual Basic для проектирования форм. Еще в дни VB6 вы должны KeyPreviewбыли иметь возможность осуществлять сочетания клавиш. В Windows Forms это больше не нужно, поэтому ProcessCmdKey()лучше переопределить :

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
  if (keyData == (Keys.Control | Keys.F)) {
    DoSomething();   // Implement the Ctrl+F short-cut keystroke
    return true;     // This keystroke was handled, don't pass to the control with the focus
  }
  return base.ProcessCmdKey(ref msg, keyData);
}

Но KeyPreviewбыл поддержан, чтобы помочь легиону программистов VB6 перейти на .NET еще в начале 2000-х. Смысл KeyPreviewили ProcessCmdKey()заключается в том, чтобы ваш пользовательский интерфейс мог реагировать на быстрые нажатия клавиш. Сообщения с клавиатуры обычно отправляются на элемент управления, который имеет фокус. Цикл сообщений Windows Forms позволяет коду взглянуть на это сообщение до того, как его увидит элемент управления. Это важно для сочетаний клавиш, реализация KeyDownсобытия для каждого элемента управления, который может сфокусироваться на их обнаружении, очень непрактична.

Установка KeyPreviewв True не вызывает проблем. KeyDownСобытие формы будет запущено, оно будет иметь влияние, только если у него есть код, который делает что-то с нажатием клавиши. Но имейте в виду, что он внимательно следит за использованием VB6, вы не можете увидеть, какие нажатия клавиш используются для навигации. Как и клавиши курсора и Tab, Escapeи Enterдля диалога. Не проблема с ProcessCmdKey().

Автор: Hans Passant Размещён: 05.03.2010 01:22

4 плюса

Из MSDN

Если для этого свойства установлено значение true, форма будет получать все события KeyPress, KeyDown и KeyUp. После того, как обработчики событий формы завершили обработку нажатия клавиши, нажатие клавиши назначается элементу управления с фокусом. Например, если для свойства KeyPreview установлено значение true, а текущий выбранный элемент управления является TextBox, после того, как нажатие клавиши обработано обработчиками событий формы, элемент управления TextBox получит нажатую клавишу. Чтобы обрабатывать события клавиатуры только на уровне формы и не разрешать элементам управления получать события клавиатуры, установите для свойства KeyPressEventArgs.Handled в обработчике событий KeyPress формы значение true.

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

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

EG Пользователь нажимает клавишу K, вызывается обработчик событий формы (Key Down, Key Up, Key Pressed), а затем вызываются обработчики событий в текущем активном элементе управления.

РЕДАКТИРОВАТЬ : Нет, нет никаких недостатков или неприятных сюрпризов. Единственное, о чем я могу думать, это очень небольшое снижение производительности, так как нужно проверять дескрипторы событий в форме для каждого KeyDown, KeyUp, KeyPressed. Кроме того, если вы не добавляете обработчики событий в форму и делаете что-то, что может вызвать проблемы. ты в порядке Если вам не нужно глобально обрабатывать ключевые события, кроме элементов управления, я бы посоветовал вам оставить это значение false, чтобы предотвратить дополнительные проверки. На современных ПК это не будет иметь видимого различия.

Автор: Michal Ciechan Размещён: 05.03.2010 01:00

2 плюса

Стандартная модель событий Windows состоит в том, что окно с фокусом клавиатуры получает все события клавиатуры. Помните, что в Windows все является окном - «элемент управления» - это просто окно, являющееся дочерним элементом другого окна. Это до того окна, чтобы запускать сообщения своему родителю, если он решит сделать это, при нажатии определенных клавиш.

Для стандартизации навигации между элементами управления в диалоговом окне Windows также предоставляет «диспетчер диалогов». В нативном коде для модальных диалогов это обрабатывается модальным циклом сообщений внутри DialogBoxфункции. Для немодальных диалогов вы должны звонить IsDialogMessageв своем собственном цикле сообщений. Вот как он крадет клавиши Tab и курсора, чтобы перемещаться между элементами управления, и Enter, чтобы нажать кнопку по умолчанию. Это имеет противоположный эффект - не позволяет элементам управления обрабатывать Enter по умолчанию, что обычно обрабатывается многострочными элементами управления. Чтобы выяснить, хочет ли элемент управления обрабатывать ключ, код диспетчера диалогов посылает сфокусированному элементу управления WM_GETDLGCODEсообщение; если откликается управление соответствующим образом окна диспетчер возвращается FALSEпозволяяDispatchMessage фактически доставить его в оконную процедуру, в противном случае менеджер диалогов делает свое дело.

Windows Forms в основном просто оборачивает старые нативные элементы управления, поэтому он должен соответствовать модели событий Win32. Он реализует тот же подход диспетчера диалогов - следовательно, по умолчанию он не позволяет вам видеть Tab, Return и клавиши курсора.

Рекомендуемый подход, если вы хотите обработать один из этих ключей, это переопределить PreviewKeyDownи установить для PreviewKeyDownEventArgs IsInputKeyсвойства значение true.

Автор: Mike Dimmick Размещён: 23.03.2015 04:24

1 плюс

Простая и тривиальная, хотя и практическая причина:

В такой игре, как Space Invaders, https://www.mooict.com/c-tutorial-create-a-full-space-invaders-game-using-visual-studio/ пользователь неоднократно забивает пробел, чтобы испарить инопланетян. Когда последний захватчик ушел, всплывающее текстовое поле, чтобы сказать, «хорошая работа». Пользователь все еще дергается большим пальцем, нажимая пробел (или, может быть, только освобождение буфера клавиатуры?), И поздравляющий MessageBox исчезает, прежде чем его можно прочитать. Я не мог видеть обходной путь из-за того, как формы обрабатывают нажатия кнопок / пробела.

Мой пользовательский диалог использует предварительный просмотр клавиш для предварительной обработки нажатий клавиш, отправляемых GameOverDialog, чтобы игнорировать любые нажатия пробела. Пользователь должен закрыть с помощью мыши или Enter. Это просто FixedDialog с надписью «Вы выиграли» и кнопкой [OK].

public partial class GameOverDialog : Form
{
    public GameOverDialog()
    {
        InitializeComponent();
        this.MaximizeBox = false;
        this.MinimizeBox = false;
    }

    // keyhandler keypreview = true
    private void SpaceDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Space)
        {
            e.Handled = true;
            return;
        }
    }

    private void SpaceUp(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Space)
        {
            e.Handled = true;
            return;
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        this.Close();
    }
}

Кроме того, интересный вариант, который я не проверял: если вы подумаете об этом, это был бы отличный способ встроить читы, скрытые сообщения и т. Д. В безобидные диалоги [OK] или любую форму, которая позволяет предварительный просмотр ключа.

Автор: user11511276 Размещён: 16.05.2019 04:58
Вопросы из категории :
32x32