|   |   | 
| 
 | Внешняя компонента для генерации внешнего события при клавиатурном вводе | ☑ | ||
|---|---|---|---|---|
| 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; } | 
 
 | Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |