|
Внешняя компонента для генерации внешнего события при клавиатурном вводе | ☑ | ||
---|---|---|---|---|
0
TormozIT
гуру
29.09.20
✎
23:48
|
Заюзал внешнюю компоненту с исходниками для перехвата клавиатурного ввода http://forum.infostart.ru/forum28/topic42414/message1778089/#message1778089
Компонента отправляет внешнее событие при каждом физическом нажатии. Но если я удерживаю клавишу (например клавишу "Вниз"), то хочу чтобы и логические нажатия начали циклически приходить. А они не генерируются этой компонентой. Если вам известна подобная компонента для 1С, которая умеет генерировать события при удержании клавиш, поделитесь со мной. |
|||
1
TormozIT
гуру
30.09.20
✎
00:23
|
Эх. Надо было в заголовок добавить "Вызов для настоящих ГУРУ"
|
|||
2
TormozIT
гуру
30.09.20
✎
08:21
|
Ап
|
|||
3
Ёпрст
30.09.20
✎
08:49
|
||||
4
TormozIT
гуру
30.09.20
✎
09:08
|
(3) Нет. Думаю нужно раз в 50 больше времени потратить чтобы решить эту задачу. Наверняка кто то уже прошел этот путь. Жду его здесь, чтобы не проходить этот путь самому.
|
|||
5
Garykom
гуру
30.09.20
✎
09:11
|
(4) Бесплатно?
|
|||
6
TormozIT
гуру
30.09.20
✎
09:12
|
(5) Сколько просишь?
|
|||
7
Garykom
гуру
30.09.20
✎
09:13
|
(6) За совет нисколько. За реализацию хз.
Совет: "настройки генерации события при нажатии или отпускании клавиши" |
|||
8
Кирпич
30.09.20
✎
09:17
|
Там же исходники есть
|
|||
9
TormozIT
гуру
30.09.20
✎
09:18
|
(8) Может тогда подскажешь и где там что изменить?
|
|||
10
Кирпич
30.09.20
✎
09:22
|
(9) Так это смотреть надо :)
|
|||
11
TormozIT
гуру
30.09.20
✎
09:27
|
(10) Я посмотрел. Мне не помогло.
|
|||
12
Злопчинский
30.09.20
✎
09:29
|
Узнал все буквы, но не смог прочитать слово... ;-)
|
|||
13
TormozIT
гуру
30.09.20
✎
09:31
|
LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam, LPARAM lParam)
{ wchar_t output[300]; bool QueueEnabled = true; if (nCode == HC_ACTION || nCode == HC_NOREMOVE) { IComponentBase * pObject = 0; pObject = listOfObjects.GetNextObjectByName(pObject, L"KeyboardHook"); while (pObject) { CAddInNative *pm = dynamic_cast< CAddInNative* >(pObject); int Action = (pm->m_FirstInterception ? HC_NOREMOVE : HC_ACTION); if (pm->m_HookEnabled && (nCode == Action)) { bool KeyPressed = !((DWORD)lParam & 0x40000000); if ((pm->m_EventOnKeyPressed && KeyPressed) || (!pm->m_EventOnKeyPressed && !KeyPressed)) { unsigned int RepeatCount = (DWORD) lParam & 0xFFFF; unsigned int ScanCode = ((DWORD) lParam >> 16) & 0xFF; unsigned int ExtendedKey = (((DWORD) lParam >> 24) & 0x01); unsigned int PreviousKeyState = (((DWORD) lParam >> 30) & 0x01); unsigned int VirtualKey = wParam; BYTE keystatebuff[256]; wchar_t SymbolString[10]; ::wmemset(SymbolString,0,10); if (::GetKeyboardState(keystatebuff)) { unsigned int ExtScanCode = ScanCode; unsigned int flags = (((DWORD) lParam >> 29) & 0x0001) ^ 0x0001; int numsymbol = ::ToUnicode(VirtualKey, ExtScanCode, keystatebuff, SymbolString, 10, flags); if (numsymbol == 10) ::wmemset(SymbolString,0,10); } ULONG ReturnCode = 0; if (::GetKeyState(VK_LSHIFT) & 0x80) ReturnCode = ReturnCode | 0x1; ReturnCode <<= 1; if (::GetKeyState(VK_RSHIFT) & 0x80) ReturnCode = ReturnCode | 0x1; ReturnCode <<= 1; if (::GetKeyState(VK_LCONTROL) & 0x80) ReturnCode = ReturnCode | 0x1; ReturnCode <<= 1; if (::GetKeyState(VK_RCONTROL) & 0x80) ReturnCode = ReturnCode | 0x1; ReturnCode <<= 1; if (::GetKeyState(VK_LMENU) & 0x80) ReturnCode = ReturnCode | 0x1; ReturnCode <<= 1; if (::GetKeyState(VK_RMENU) & 0x80) ReturnCode = ReturnCode | 0x1; ReturnCode <<= 1; ReturnCode = ReturnCode | ExtendedKey; ReturnCode <<= 8; ReturnCode = ReturnCode | (VirtualKey & 0x00FF); int StringLength = swprintf_s(output, 300, L"%05u%s", ReturnCode, SymbolString); pm->SendEvent(output); } QueueEnabled = QueueEnabled & !pm->m_KeyboardLocked; } pObject = listOfObjects.GetNextObjectByName(pObject, L"KeyboardHook"); } } if (nCode < 0 || QueueEnabled) { LRESULT RetVal = CallNextHookEx( CAddInNative::m_KeyBoardHook, nCode, wParam, lParam ); return RetVal; } return -1; } |
|||
14
Garykom
гуру
30.09.20
✎
09:34
|
Зачем менять в C++ когда можно в 1С?
|
|||
15
Garykom
гуру
30.09.20
✎
09:35
|
(10) Не надо ничего смотреть блин.
ВК делает события на нажатия и ОТПУСКАНИЯ кнопок. Ну? |
|||
16
Garykom
гуру
30.09.20
✎
09:40
|
(0) >Если вам известна подобная компонента для 1С, которая умеет генерировать события при удержании клавиш, поделитесь со мной.
ВК должна делать разные события при 1. Нажатии кнопки 2. Отпускании кнопки 3. Циклическое событие между нажатием и отпусканием? А с какой частотой? |
|||
17
Garykom
гуру
30.09.20
✎
09:43
|
(16)+ Упс просто частоту указать в ВК недостаточно, там нужно указывать время после первоначального нажатия (чтобы избежать "ааа" когда хотели просто "а" но задумались) и затем время повторов.
|
|||
18
TormozIT
гуру
30.09.20
✎
09:45
|
(15) Юзер нажал клавишу и держит ее нажатой. При этом через паузу в 1-2 сек в очередь событий приложения WinAPI начинает слать циклически с задержкой типа 50мс (repeat rate) события нажатия и отпускания этой клавиши, хотя физически она не меняет состояние.
А эта ВК шлет только при физических изменениях состояния клавиши, причем либо только при нажатии, либо только при отпускании. Ну это я смогу доработать конечно - будет допустим слать и при нажатии и при отпускании. Но мне надо циклически генерировать нажатия и ровно также как это делает WinAPI, чтобы юзер не почуял разницы. |
|||
19
Кирпич
30.09.20
✎
09:46
|
(13) Лучше тест на 1с покажи. На чем пробовать
|
|||
20
Garykom
гуру
30.09.20
✎
09:55
|
(18) Вот эту строчку
if ((pm->m_EventOnKeyPressed && KeyPressed) || (!pm->m_EventOnKeyPressed && !KeyPressed)) исправь и будет слать и при нажатии и при отпускании |
|||
21
Кирпич
30.09.20
✎
10:05
|
А может оно и не должно работать на повтор. Может там надо ставить хук на WH_KEYBOARD_LL, а не на WH_KEYBOARD
|
|||
22
trad
30.09.20
✎
10:21
|
(20) ты предлагаешь сидеть в цикле в одинесе пока нажата и не отпущена клавиша?
|
|||
23
Garykom
гуру
30.09.20
✎
10:24
|
(22) Логично что на сервере в 1С нет смысла в кнопках, значит клиент.
На клиенте в формах есть ПодключитьОбработчикОжидания |
|||
24
TormozIT
гуру
30.09.20
✎
10:25
|
(23) 50мс?
|
|||
25
Garykom
гуру
30.09.20
✎
10:26
|
(24) "<Интервал> (обязательный)
Тип: Число. Интервал времени в секундах с точностью до 1/10 секунды, через который будет осуществляться вызов процедуры (положительное число)." 100мс можно |
|||
26
trad
30.09.20
✎
10:30
|
(23) "Логично что на сервере в 1С нет смысла в кнопках, значит клиент."
Логично, кто ж спорит )) |
|||
27
trad
30.09.20
✎
10:32
|
(23) "ПодключитьОбработчикОжидания"
А в какой момент отключать обработчик? На кейап? А если он случился не в фокусе? |
|||
28
trad
30.09.20
✎
10:35
|
Я не изучал как устроен этот кхук с иса, но знаю что WM_KEYDOWN генерится и при физическом нажатии и при автоповторе
|
|||
29
Garykom
гуру
30.09.20
✎
10:38
|
(27) Вне 1С? Ну это засада с данной ВК в целом
|
|||
30
trad
30.09.20
✎
10:42
|
(29) Ну конечно вне 1с.
Организовывать автоповтор внутри, в данной ситуации, бесперспективная затея |
|||
31
trad
30.09.20
✎
10:44
|
Посмотрел.
Там где-то вокруг вот этого надо поплясать int Action = (pm->m_FirstInterception ? HC_NOREMOVE : HC_ACTION); и выкурить это блокирование автоповтора |
|||
32
trad
30.09.20
✎
10:45
|
более полная цитата:
int Action = (pm->m_FirstInterception ? HC_NOREMOVE : HC_ACTION); if (pm->m_HookEnabled && (nCode == Action)) |
|||
33
TormozIT
гуру
30.09.20
✎
11:01
|
(32) Если ты думаешь, что "m_FirstInterception" это типа "первое нажатие", то нет. Это "перехват первым до обработки приложением".
|
|||
34
trad
30.09.20
✎
11:04
|
(33) слабо мне понятная муть ))
|
|||
35
TormozIT
гуру
30.09.20
✎
11:10
|
(34) Это объяснение от автора ВК.
|
|||
36
TormozIT
гуру
12.10.20
✎
16:20
|
Заработало. Опубликовал код тут https://github.com/tormozit/KeyboardHook_1C
Вот исправленная процедура - хук тот же самый. LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { wchar_t output[300]; bool QueueEnabled = true; if (nCode == HC_ACTION || nCode == HC_NOREMOVE) { IComponentBase * pObject = 0; pObject = listOfObjects.GetNextObjectByName(pObject, L"KeyboardHook"); while (pObject) { CAddInNative *pm = dynamic_cast< CAddInNative* >(pObject); if (pm->m_HookEnabled) { unsigned int TransitionState = (((DWORD)lParam >> 31) & 0x01); if (TransitionState == 0) { unsigned int RepeatCount = (DWORD) lParam & 0xFFFF; unsigned int ScanCode = ((DWORD) lParam >> 16) & 0xFF; unsigned int ExtendedKey = (((DWORD) lParam >> 24) & 0x01); unsigned int PreviousKeyState = (((DWORD) lParam >> 30) & 0x01); unsigned int VirtualKey = wParam; BYTE keystatebuff[256]; wchar_t SymbolString[10]; ::wmemset(SymbolString,0,10); if (::GetKeyboardState(keystatebuff)) { unsigned int ExtScanCode = ScanCode; unsigned int flags= (((DWORD) lParam >> 29) & 0x0001) ^ 0x0001; int numsymbol = ::ToUnicode(VirtualKey, ExtScanCode, keystatebuff, SymbolString, 10, flags); if (numsymbol == 10) ::wmemset(SymbolString,0,10); } ULONG ReturnCode = 0; if (::GetKeyState(VK_LSHIFT) & 0x80) ReturnCode = ReturnCode | 0x1; ReturnCode <<= 1; if (::GetKeyState(VK_RSHIFT) & 0x80) ReturnCode = ReturnCode | 0x1; ReturnCode <<= 1; if (::GetKeyState(VK_LCONTROL) & 0x80) ReturnCode = ReturnCode | 0x1; ReturnCode <<= 1; if (::GetKeyState(VK_RCONTROL) & 0x80) ReturnCode = ReturnCode | 0x1; ReturnCode <<= 1; if (::GetKeyState(VK_LMENU) & 0x80) ReturnCode = ReturnCode | 0x1; ReturnCode <<= 1; if (::GetKeyState(VK_RMENU) & 0x80) ReturnCode = ReturnCode | 0x1; ReturnCode <<= 1; ReturnCode = ReturnCode | ExtendedKey; ReturnCode <<= 8; ReturnCode = ReturnCode | (VirtualKey & 0x00FF); int StringLength = swprintf_s(output, 300, L"%05u%s", ReturnCode, SymbolString); pm->SendEvent(output); } QueueEnabled = QueueEnabled & !pm->m_KeyboardLocked; } pObject = listOfObjects.GetNextObjectByName(pObject, L"KeyboardHook"); } } if (nCode < 0 || QueueEnabled) { LRESULT RetVal = CallNextHookEx( CAddInNative::m_KeyBoardHook, nCode, wParam, lParam ); return RetVal; } return -1; } |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |