3

Создал сочетание клавиш Ctrl+O и Ctrl+А. При нажатии все работает, как я хотел, но проигрывается стандартный звук «Восклицание». Откуда он берется и как его устранить?

Я заметил что при запуске формы у меня в фокусе текстбокс. И если сделать его неактивным звук пропадает.

rdorn
  • 16,323
  • Вы бы привели воспроизводящий пример, а то получается какой-то подземный стук. – VladD Apr 30 '17 at 16:58
  • 1
    @VladD Воспроизводиться системный звук "Восклицание" – kovdryavlad Apr 30 '17 at 17:04
  • @VladD я заметил что при запуске формы у меня в фокусе текстбокс. И если сделать его неактивным звук пропадает. Как убрать фокус с тестбокса при запуске? – kovdryavlad Apr 30 '17 at 17:05
  • Ну, поставьте фокус на что-нибудь ещё? – VladD Apr 30 '17 at 17:17
  • Не, это не воспроизводящий пример. Нужно что-то такое, чтобы другие участники смогли запустить и увидеть ту же проблему на своей машине. [mcve] – VladD Apr 30 '17 at 17:18
  • 2
    @VladD не, все нормально, это известный баг со звуком в текстбоксе. Там еще с горячими клавишами проблема. – rdorn May 01 '17 at 00:23
  • У вас какая версия фреймворка в проекте выставлена? TextBox.MultyLine = true ? Посмотрите тут https://ru.stackoverflow.com/a/479523/198316 – rdorn May 01 '17 at 00:23
  • @rdorn: Ох, не знал. Тогда имеет смысл опубликовать ответ? – VladD May 01 '17 at 10:25

1 Answers1

8

TextBox - наиболее часто используемый элемент WinForms, прямую конкуренцию может составить только Label. И именно в нем есть досадный баг, который исправили только в .NET 4.6.1

Почти все контролы, когда они находятся в фокусе, перехватывают на себя обработку нажатий на клавиши и передают событие родительскому контейнеру, только если это явно указать в обработчике. В TextBox по-умолчанию определено много горячих клавиш для работы именно с ним, но если он находится в режиме MultyLine, то большинство сочетаний клавиш Ctrl+some key работают некорректно. Если быть точным, то единственное что отрабатывает для этих сочетаний - это проигрывание системного звука "Восклицание" (не помню как он называется в английской версии), который обычно сигнализирует об ошибочном действии пользователя (например при клике в основное окно приложения, при открытом модальном диалоге).

Решений два, радикальное и "костыль".
Решений три:

Мягкое решение - добавить на форму MenuStrip и настроить горячие клавиши в MenuStripItem-ах. Меню перехватит все заданные сочетания, они не попадут в TextBox, следовательно не будет проигрываться звук. Хорошо, но подходит не всегда.

Радикальное решение - пересобрать проект на платформе .NET 4.6.1. В этой редакции исправили работу некоторых сочетаний клавиш, например Ctrl+A (выделить всё), но поведение по-умолчанию для не используемых сочетаний клавиш не изменилось. Для нас это означает, что звуки отдельных сочетаний клавиш придется экранировать отдельно. Либо с помощью меню (см. выше), либо как описано ниже.

Исправляем баг руками - когда ни добавление меню, ни повышение версии платформы не допустимо, придется исправлять баг своими силами. Для этого вешаем обработчик на событие TextBox.KeyDown, в котором прописываем необходимые нам сочетания клавиш следующим образом (для примера Ctrl+A):

private void textBox1_KeyDown(object sender, KeyEventArgs e) 
{
    if (e.KeyData == (Keys.Control | Keys.A)) 
    {
        textBox1.SelectAll();
        //убираем звуковое сопровождение при нажатии клавиш
        e.Handled = e.SuppressKeyPress = true;
    }
}

Отдельно замечу, что нельзя использовать для отключения звуков вариант:

private void textBox1_KeyDown(object sender, KeyEventArgs e) 
{
    e.Handled = e.SuppressKeyPress = true;
}

Так как это не только заглушит звуки, но и превратит TextBox в тыкву, отключив обработку клавиш полностью.

rdorn
  • 16,323