Не отпускает CTRL, WinApi хуки

Здравствуйте. Делаю приложение по типу пунтосвитчера. Нужно при отлове нажатий кнопок менять текст на заданный в списке.

Поставил низкоуровневые хуки:

keybdhookHandler = new LowLevelHookHandler(KeybdHookCallback);
keybdhookID = SetHook(WinApi.WH_KEYBOARD_LL, keybdhookHandler);

Это блок нормально ловит и нажатия и отжатия.
Но бред получается при ctrl.
Логика такая:
При определенных условиях ввода текста появляется меню подстановки с вариантами от 1 до 20.
Далее если нажать цифрами от 1 до 9 то происходит события KeyDown в нем происходит удаление введенного слова и вставка новой фразы с помощью SendKeys. Этот блок работает как часы стабильно и хорошо.
Если нужно ввести выше 9 то при удерживании клавиши ctrl я блокирую перехват кнопок и запоминаю числа которые вводит пользователь.
При отпускании ctrl смотрю что было введено и пытаюсь повторить туже самую функцию замены. Но система думает что ctrl еще нажат и в программе где происходит ввод начинается бред. Как будто нажимаются кнопки в комбинации с ctrl.

Почему аткая хрень может быть то?? Уже сделал в отдельном таске замену с задержкой в 5 сек чтобы все события успевали проходит но все равно программа не понимает что ctrl уже отжали.

Даже вот такую дичь влепил:

WinApi.keybd_event((byte)WinApi.VKeys.CONTROL, 0x45, WinApi.KEYEVENTF_EXTENDEDKEY | WinApi.KEYEVENTF_KEYUP, UIntPtr.Zero);
WinApi.keybd_event((byte)WinApi.VKeys.LCONTROL, 0x45, WinApi.KEYEVENTF_EXTENDEDKEY | WinApi.KEYEVENTF_KEYUP, UIntPtr.Zero);
WinApi.keybd_event((byte)WinApi.VKeys.RCONTROL, 0x45, WinApi.KEYEVENTF_EXTENDEDKEY | WinApi.KEYEVENTF_KEYUP, UIntPtr.Zero);
Application.DoEvents();

Ничего не помогает. Кто нибудь знает что за бред то творится??

Лог перехвата сделайте в Memo что-бы видно было.

Так вы заблокировали до прихода WM_KEYUP. Скорее всего неверно блокируете.

Так что именно заблокировал то??
Ведь удержание ctrl то программа видит. Даже блокировку уже отключил. То есть всегда передаются сообщения следующему по очереди. Все равно что то держит контрол.

Подозреваю одна строка лишняя

//WinApi.keybd_event((byte)WinApi.VKeys.CONTROL, 0x45, WinApi.KEYEVENTF_EXTENDEDKEY | - - WinApi.KEYEVENTF_KEYUP, UIntPtr.Zero);
WinApi.keybd_event((byte)WinApi.VKeys.LCONTROL, 0x45, WinApi.KEYEVENTF_EXTENDEDKEY | WinApi.KEYEVENTF_KEYUP, UIntPtr.Zero);
WinApi.keybd_event((byte)WinApi.VKeys.RCONTROL, 0x45, WinApi.KEYEVENTF_EXTENDEDKEY | WinApi.KEYEVENTF_KEYUP, UIntPtr.Zero);

Зачем отслеживать общий Control если отслеживаются левый и правый отдельно?

Попробуйте слать дуплетом

KEYEVENTF_KEYDOWN
KEYEVENTF_KEYUP

так все равно не работает

Так а в коде что?
И в логе?
:arrow_down:

Ладно … позже дойдут руки до лога.

Вот лог. Вроде бы все верно но нихрена не работает

Catch WM_KEYDOWN: RETURN
Catch WM_KEYUP: RETURN
Catch WM_KEYDOWN: KEY_1
Catch WM_KEYUP: KEY_1
Catch WM_KEYDOWN: OEM_MINUS
Catch WM_KEYUP: OEM_MINUS
Catch WM_KEYDOWN: KEY_Z
Catch WM_KEYUP: KEY_Z

// Показали меню
// Нажал и удерживаю контрол и ввожу 14
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: KEY_1
Catch WM_KEYUP: KEY_1
Catch WM_KEYDOWN: KEY_4
Catch WM_KEYUP: KEY_4
Catch WM_KEYUP: LCONTROL  <- отпустил кнопку 
Catch WM_KEYDOWN: RCONTROL <- отправляю программно команды нажатия и отжатия кнопки
Catch WM_KEYDOWN: LCONTROL
Catch WM_KEYDOWN: RCONTROL
Catch WM_KEYUP: RCONTROL
Catch WM_KEYUP: LCONTROL
Catch WM_KEYUP: RCONTROL

// но в окружении контрол все равно нажат и вводится хрень полная

Вот здесь рекомендуют функцию keybd_event заменить на SendInput
И если чесно, не могу понять что выполняет параметр 0х45. Microsoft его в пример с NumLock пихает, первая ссылка этого поста.

Ну раз МС пихает то и нам нужно.

В общем глюк какой то странный. Оказывается он проявляется только в notepad++
В других программах все нормально.
Всякие задержки не помогают… мистика блин.

А что то у меня с ней не срослось. Уже не помню даже почему…

Так это сканкод намлока.

bScan
A hardware scan code for the key.

https://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html

Но сканкоды вроде игнорируются многими приложениями:
https://stackoverflow.com/a/15065099/964478

It is indeed a scan code and for many keyboards it is the scan code for the NumLock key.

The example code attached to the documentation of keybd_event is an example of how to toggle the NumLock state. And so naturally 0x45 is used as the scan code. My guess is that lots of the other examples that you found simply copied blindly that value from the keybd_event MSDN example. Since applications typically ignore the scan code and respond to the virtual key code, it usually doesn’t matter what value is passed as the scan code.

Finally, you’ll want to use SendInput rather than keybd_event . The reason being that that former allows you to place a sequence of events in the queue. With keybd_event you place the events in the queue one at a time and it’s possible that your faked events can get interspersed with real events. And that problem is one of the main reasons why SendInput was introduced.

ХЗ что за параметр. C#. Советы программистам на стр. 265 тот-же код применяют по отношению к CapsLock

Так выше ж написано что это )
И что большинство программ игнорируют это, используя виртуальные коды. Поэтому во многих примерах скопипасчен 0х45 из примера МС для намлока, но работает.

Так дело в том что 0х45 виртуальный код клавиши E.
Virtual-Key Codes
Или что не то понимаю?

Так у keybd_event виртуальный код в первом параметре, второй параметр — сканкод.
Виртуальные коды и сканкоды не совпадают.

The scancodes in translated scancode set 2 are given in hex. Between parentheses the keycap on a US keyboard. The scancodes are given in order, grouped according to groups of keys that are usually found next to each other.

0f (Tab), 10 (Q), 11 (W), 12 (E), 13 ®, 14 (T), 15 (Y), 16 (U), 17 (I), 18 (O), 19 §, 1a ([{), 1b (]})
1c (Enter)
1d (LCtrl)

3a (CapsLock)
3b (F1), 3c (F2), 3d (F3), 3e (F4), 3f (F5), 40 (F6), 41 (F7), 42 (F8), 43 (F9), 44 (F10)
45 (NumLock)
46 (ScrollLock)

Если по этим кодам, то нет разделения на правый и левый Ctrl. У них общий код 0x1d. Так выходит?

Не общий, e0 1d и 1d.
Просто

Often, the codes are chosen in such a way that something meaningful happens when the receiver just discards the e0

Может стоит попробовать стандартные hex коды?
Ctrl = 0x11
или
RCtrl = 0xA3
LCtrl = 0xA2

Попробую конечно. Спасибо.