Я создаю программу, которая устанавливает хук клавиатуры для захвата всех клавиш и отображения текста, связанного с ними.
Однако я наткнулся на препятствие, и некоторые клавиши меняют поведение, когдахук установлен.
Я расскажу о публикации небольшой, но полной тестовой программы, но сейчас я просто опишу проблему.
Проблема проявляется в Windows 764-битная, в .NET 4.0, программа на C #.Я предполагаю, что ничего из этого не имеет значения.
Мой хук устанавливает себя через SetWindowsHookEx
, а затем обрабатывает все ключи, обработанные в системе.
Если метод хука просто возвращает или выполняет минимальную обработкуклавиша (я опубликую, что изменит поведение через секунду), клавиатура функционирует так, как ожидается в программах.
Однако, если я вызову эту функцию, ToAscii
из User32.dll, чтобы выяснить, какая клавишана моей клавиатуре OemTilde или подобный действительно есть, тогда любая клавиша, которая «перекрывает следующую клавишу», перестает функционировать.Я не знаю правильного имени для таких ключей, но два типа апострофа, `` и ´ , as well as
~ and
¨`, перестают функционировать.
Например, если я нажму ~
и затем N
, он отображается следующим образом:
- Без установленного крючка клавиатуры: -
- С установленным крюком клавиатуры: n (примечание № ~ выше)
Кто-нибудь знает, почему это происходит и как я могу решить эту проблему?
Пока я согласен на правильную обработку ключей в других программах, даже если это означает, что я не будуможет правильно определять правильные последовательности клавиш в моей собственной программе.
Дополнительная информация:
Если я вызываю функцию ToAscii
как часть метода ловушки, возникает другая проблема.Ключи типа ¨
обрабатываются дважды, т.е.если я нажму ¨
один раз, Блокнот получит два ¨¨
символа, а нажатие N
теперь просто добавляет N
.
Однако, если я использую BeginInvoke
для обработки ключа наВ отдельном потоке после возврата из метода перехвата клавиатуры возникает первая проблема.
Моя программа, вероятно, немного особенная в этом:
- Я не использую клавиатурусостояние (т. е. 256-байтовый массив «Состояние ключа», который я передаю, просто полон 0)
- Мне не нужны мертвые ключи (в том смысле, что моя программа не будет их обрабатывать, ядостаточно заботиться о них, чтобы я не хотел, чтобы моя программа делала их бесполезными для остальной системы)
Таким образом, мой код в итоге выглядел следующим образом:
private bool IsDeadKey(uint key)
{
return ((Hook.Interop.MapVirtualKey(key, 2) & 2147483648) == 2147483648);
}
void _Hook_KeyDown_Async(KeyDownEventArgs e)
{
var inBuffer = new byte[2];
char key = '\0';
if (!IsDeadKey((uint)e.KeyCode))
{
int ascii = Hook.Interop.ToAscii((int) e.KeyCode,
e.ScanCode,
_KeyState,
inBuffer,
e.Flags);
if (ascii == 1)
{
key = Char.ToUpper((char) inBuffer[0]);
}
}
BeginInvoke(
new Action<Keys, Boolean, Boolean, Boolean, Char>(ProcessKeyboardEvent),
e.KeyCode, e.Control, e.Shift, e.Alt, key);
}