2017-02-22 3 views
0

У меня есть приложение winforms, которое содержит 3 элемента управления в моей форме: GroupBox gb1 который содержит ComboBox cmb1 и TextBox tb1.Почему «ProcessCmdKey» дважды срабатывает для combobox, но один раз для текстового поля?

В Form1.cs У меня есть следующий код:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 
{ 
    if (comboBox1.Focused) 
     MessageBox.Show("Cmb Focus"); 
    else if (textBox1.Focused) 
     MessageBox.Show("Txtbox Focus"); 

    return base.ProcessCmdKey(ref msg, keyData); 
} 

Если я остановлюсь мое текстовое поле и нажмите клавишу я получаю дисплей 1 MessageBox. Сфокусировано, я получаю 2 всплывающих окна.

Первоначально я наткнулся this question года полтора назад, и человек, который отвечал на вопрос, принял мое решение, которое просто цитирует MSDN:

Метод ProcessCmdKey первый определяет, имеет ли элемент управления в ContextMenu, и если это так, позволяет ContextMenu обрабатывать командный ключ. Если командный ключ не является ярлыком меню, а элемент управления имеет родителя, ключ передается методу ProcessCmdKey родителя. Чистый эффект заключается в том, что командные ключи «пузырятся» по иерархии управления.

Я понимаю, что он говорит, но в то же время я не понимаю «фактическое» поведение моего приложения.

Ни один элемент управления не имеет контекстного меню. Оба элемента управления имеют 1 родительский объект (поле группы). Так почему же они ведут себя по-другому?

Я попробовал несколько вещей, чтобы помочь мне понять:

1) Если я изменить код return true;, оба элемента управления отображать только 1 окно сообщения. Если я изменю его на return false;, я получаю такое же поведение, как описано ранее.

2) Я подумал, что, может быть, это был «побочный эффект» тот факт, что Combobox object наследует от System.Windows.Forms.ListControl. Поэтому я попробовал просто добавить третий элемент управления, ListBox, который также наследует от System.Windows.Forms.ListControl. Но когда я фокусирую это ListBox, я все еще получаю только 1 сообщение.

3) Я добавил к моему comboBox1.Items.Add("1");Form1() конструктора, а затем нажать клавишу на моей клавиатуре. Я подумал: «Может быть, если я нажму клавишу« соответствует »элементу коллекции Items combobox, он отобразит только 1 всплывающее окно». Но нет, это все еще показывает дважды.

Это поведение было доведено до моего сведения вчера после того, как пользователь прокомментировал ответ, который я опубликовал в связанном выше вопросе, но я не смог найти , почему это происходит.

ответ

2

Это немного причуда, характерная для ComboBox. Это calls ProcessCmdKey as well в своем обработчике сообщений. Не 100% уверены, почему он это делает, но почти наверняка имеет какое-то отношение к нажатиям клавиш, полученным выпадающим списком, а не текстовым полем.

В противном случае побочный эффект, связанный с тем, как родной combobox обрабатывает сообщения, отправляет сообщения WM_KEYDOWN из раскрывающегося списка в текстовое поле, если они не использовались для выбора элемента в раскрывающемся списке. Описывается в разделе «По умолчанию Combo Box Behavior» в the SDK doc page.И нет никакого способа сказать, откуда это взялось, поэтому Winforms не может сделать его избирательным.

Да, вы, конечно, должны return true;, когда вы обрабатываете нажатие клавиши, всегда необходимо. Я не могу сказать, почему вы пропустили это, но это решает проблему. Возможно, IMessageFilter может решить вашу проблему (не пробовал), но вопрос не дает никакого намека на то, как выглядит настоящая проблема.

+0

Что касается вашего последнего абзаца, я в основном просто удалял код в вопросе, который я связал, там оригинальный плакат вызывает метод 'base' в конце его' override'. Я не был уверен, было ли это «хорошей идеей», чтобы просто «вернуть истину», независимо от того, какой был вход, в случае, если это может изменить предполагаемое поведение элемента управления/приложения. – sab669

+0

Вызов base.ProcessCmdKey() является сложным требованием или вы разрываете комбинацию клавиш в базовом классе. Но нет, если вы использовали нажатие клавиши, точка добавления 'return true;' –

Смежные вопросы