2010-01-06 12 views
3

У меня возникает очень своеобразная проблема. Я заметил, что иногда во время ввода текста в TextBox я теряю несколько нажатий клавиш. Я добавил множество операторов трассировки в событиях, подключенных этим TextBox, и я обнаружил, что когда я потерял нажатие клавиш, события KeyUp, KeyDown и KeyPress были правильно запущены, но событие TextChanged никогда не запускалось..NET: событие TextChanged для TextBox не всегда срабатывает, даже если KeyUp и KeyDown стреляют

Есть ли у кого-нибудь идеи, почему это произойдет? Я мог бы написать это как «.NET-ошибка», но я бы предпочел выяснить, есть ли здесь решение.

Если есть предположение, что я использую события KeyUp/KeyDown, чтобы определить, был ли текст изменен, есть проблема и там. KeyUp/KeyDown вызывается несколько раз для каждого нажатия клавиши, поэтому было бы очень сложно определить, кто-то печатал одну и ту же букву несколько раз.

+0

Какие клавиши вы используете, чтобы испытать это? Textchanged является частью свойства Text для текстового поля, и любой вход (альфа и числовой вместе с символами, например $) срабатывает при событии TextChanged, клавиши со стрелками, вставка, перезапись не срабатывает, а попадают в событие KeyUp/KeyDown , – t0mm13b

+0

Очевидным примером может быть нажатие Backspace, когда текстовое поле пуст. Нет события TextChange, но все события клавиатуры. –

+0

Я определенно использую обычные буквенно-цифровые нажатия клавиш, когда это происходит. – dreadpirateryan

ответ

1

Я действительно не знаю, но у меня есть случайное предположение: вы работаете в виртуальной машине?

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

+0

Нет, не работает в виртуальной машине. Я подумаю об этой идее таймера - хорошее предложение. – dreadpirateryan

0

Вы имеете в виду, что нажатие клавиши действительно потеряно и никогда не появляется в поле? Или вы имеете в виду, что не получаете событие TextChanged для каждого нажатия клавиши?

Я считаю, что событие TextChanged управляется уведомлением EN_CHANGE операционной системы, которое отправляется через сообщение WM_COMMAND. Я знаю, что некоторые типы сообщений в Windows «объединены», чтобы избежать избыточных уведомлений. Например, это может случиться с сообщениями WM_MOUSEMOVE и поэтому вы не получаете события перемещения мыши для каждого пикселя, который мышь перемещает по экрану.

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

+0

Ключ фактически потерян и никогда не появляется в окне - и когда это произойдет, я заметил, что событие TextChanged также не срабатывает. Благодарим за информацию о сообщениях Windows. Может быть, я могу вручную запустить это событие во время событий KeyUp/KeyDown? – dreadpirateryan

+1

Кажется, что-то ел сообщение. Может быть, есть где-то в обходной обложке сообщения об устройстве? Или смею сказать, может быть, какой-то кейлоггер? Вы должны попробовать запустить Spy ++, если он установлен, и посмотреть, попадает ли сообщение в окно. – Josh

+0

В программе действительно есть крючок для клавиатуры - важная часть информации, которую я должен был включить. Крюк создается с помощью следующего кода: SetWindowsHookEx (WH_KEYBOARD, KeyFunction, dllInstance, AppDomain.GetCurrentThreadId()); Метод KeyFunction проверяет определенные нажатия клавиш, вызывает другие функции в зависимости от того, что это за клавиши, а затем вызывает функцию CallNextHookEx. Мои утверждения следа говорят мне, что в тех случаях, когда я теряю нажатие клавиш, крючок действительно видит ключ, а функция CallNextHookEx получает правильное название. – dreadpirateryan

2

Хммм ....

Это будет удар, но, ты сказал у вас есть KeyUp, KeyDown и обработчики событий KeyPress правильно? Вы установите флаг e.Handled истину в обработчиках событий, смотрите здесь:

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

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

     private void textBox1_KeyPress(object sender, KeyPressEventArgs e) 
     { 
      e.Handled = true; 
     } 

здесь смотрите в MSDN об этом Handled собственности. (Если у вас есть MSDN 2008 SP 1 установлен локально, ссылка ms-help://MS.MSDNQTR.v90.en/fxref_system.windows.forms/html/dfc80b44-1d79-6315-cbea-1388a048c018.htm)

Цитирую:

 
Handled is implemented differently by different controls within Windows Forms. 
For controls like TextBox which subclass native Win32 controls, it is 
interpreted to mean that the key message should not be passed to the underlying 
native control. 

If you set Handled to true on a TextBox, that control will not pass the key 
press events to the underlying Win32 text box control, but it will still 
display the characters that the user typed. 

Возможно, он не установлен, т.е. e.Handled = false; тем самым предотвращая TextChanged событие от стрельбы?

Вы можете проверить и подтвердить это?

Edit: После ответа dreadprivateryan, я могу подозревать, (из-за отсутствия кода публикуемую), основанный на его ответ, e.Handled верно, когда Enter клавиша нажата и ложь для всего остального, которое, на мой взгляд, считает, что именно по этой причине в результате этого не принимаются дальнейшие нажатия клавиш.

  • Вы пытаетесь установить фокус на другой элемент управления при нажатии клавиши Enter? Возможно, что и KeyUp, и KeyDown конфликтуют ...
  • Удалить крючок клавиатуры и отключить его ...
  • Мое предложение состоит в том, чтобы полностью изменить код, как показано на рисунке, вынуть либо KeyDown, либо KeyUp Event Обработчик, как они, упрощенно говоря, один и тот же, нормально, технически, он обозначается соответственно, когда нажата клавиша, а также при отпускании клавиши. Посмотрите на эту ссылку here. Был аналогичный вопрос, размещенный here на SO.

В приведенном ниже примере я использовал обработчик события keyUp для переключения фокуса на следующий доступный элемент управления при нажатии клавиши ввода. В обработчике событий KeyPress это просто фильтрует вход и допускает только номера 0-9, все остальное отбрасывается. Включено в обработчик этого события, является залогом для клавиши backspace для редактирования.

 
     private void textBox1_KeyUp(object sender, KeyEventArgs e) 
     { 
      if (e.KeyCode == Keys.Enter) SendKeys.Send("{TAB}"); 
     } 
     private const string VALID_KEYS = ""; 
     private void textBox1_KeyPress(object sender, KeyPressEventArgs e) 
     {     
      if (VALID_KEYS.IndexOf(char.ToUpper(e.KeyChar)) != -1 || e.KeyChar == (char)8) 
       e.Handled = false;                
      else                     
       e.Handled = true;                 
}                       

Надеется, что это помогает, С наилучшими пожеланиями, Том.

+0

Спасибо за предложение. Я устанавливаю e.Handled = true в том случае, если нажатие клавиши является клавишей ввода, и в противном случае я вообще не обрабатываю обработку. К сожалению, я не думаю, что это связано с моей проблемой - я теряю нажатия клавиш, нажимаю ли я клавишу Enter. – dreadpirateryan

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