Вход | Регистрация
 

Внешняя компонента для генерации внешнего события при клавиатурном вводе

Внешняя компонента для генерации внешнего события при клавиатурном вводе
Я
   TormozIT
 
29.09.20 - 23:48
Заюзал внешнюю компоненту с исходниками для перехвата клавиатурного ввода http://forum.infostart.ru/forum28/topic42414/message1778089/#message1778089
Компонента отправляет внешнее событие при каждом физическом нажатии.
Но если я удерживаю клавишу (например клавишу "Вниз"), то хочу чтобы и логические нажатия начали циклически приходить. А они не генерируются этой компонентой.
Если вам известна подобная компонента для 1С, которая умеет генерировать события при удержании клавиш, поделитесь со мной.
   TormozIT
 
1 - 30.09.20 - 00:23
Эх. Надо было в заголовок добавить "Вызов для настоящих ГУРУ"
   TormozIT
 
2 - 30.09.20 - 08:21
Ап
   Ёпрст
 
3 - 30.09.20 - 08:49
(0) так подойдет ?
https://cloud.mail.ru/public/2u3e/463pBSYsk

ОФ :)
   TormozIT
 
4 - 30.09.20 - 09:08
(3) Нет. Думаю нужно раз в 50 больше времени потратить чтобы решить эту задачу. Наверняка кто то уже прошел этот путь. Жду его здесь, чтобы не проходить этот путь самому.
   Garykom
 
5 - 30.09.20 - 09:11
(4) Бесплатно?
   TormozIT
 
6 - 30.09.20 - 09:12
(5) Сколько просишь?
   Garykom
 
7 - 30.09.20 - 09:13
(6) За совет нисколько. За реализацию хз.

Совет: "настройки генерации события при нажатии или отпускании клавиши"
   Кирпич
 
8 - 30.09.20 - 09:17
Там же исходники есть
   TormozIT
 
9 - 30.09.20 - 09:18
(8) Может тогда подскажешь и где там что изменить?
   Кирпич
 
10 - 30.09.20 - 09:22
(9) Так это смотреть надо :)
   TormozIT
 
11 - 30.09.20 - 09:27
(10) Я посмотрел. Мне не помогло.
   Злопчинский
 
12 - 30.09.20 - 09:29
Узнал все буквы, но не смог прочитать слово... ;-)
   TormozIT
 
13 - 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;

}
   Garykom
 
14 - 30.09.20 - 09:34
Зачем менять в C++ когда можно в 1С?
   Garykom
 
15 - 30.09.20 - 09:35
(10) Не надо ничего смотреть блин.

ВК делает события на нажатия и ОТПУСКАНИЯ кнопок. Ну?
   Garykom
 
16 - 30.09.20 - 09:40
(0) >Если вам известна подобная компонента для 1С, которая умеет генерировать события при удержании клавиш, поделитесь со мной.

ВК должна делать разные события при
1. Нажатии кнопки
2. Отпускании кнопки
3. Циклическое событие между нажатием и отпусканием? А с какой частотой?
   Garykom
 
17 - 30.09.20 - 09:43
(16)+ Упс просто частоту указать в ВК недостаточно, там нужно указывать время после первоначального нажатия (чтобы избежать "ааа" когда хотели просто "а" но задумались) и затем время повторов.
   TormozIT
 
18 - 30.09.20 - 09:45
(15) Юзер нажал клавишу и держит ее нажатой. При этом через паузу в 1-2 сек в очередь событий приложения WinAPI начинает слать циклически с задержкой типа 50мс (repeat rate) события нажатия и отпускания этой клавиши, хотя физически она не меняет состояние.
А эта ВК шлет только при физических изменениях состояния клавиши, причем либо только при нажатии, либо только при отпускании. Ну это я смогу доработать конечно - будет допустим слать и при нажатии и при отпускании. Но мне надо циклически генерировать нажатия и ровно также как это делает WinAPI, чтобы юзер не почуял разницы.
   Кирпич
 
19 - 30.09.20 - 09:46
(13) Лучше тест на 1с покажи. На чем пробовать
   Garykom
 
20 - 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
   trad
 
22 - 30.09.20 - 10:21
(20) ты предлагаешь сидеть в цикле в одинесе пока нажата и не отпущена клавиша?
   Garykom
 
23 - 30.09.20 - 10:24
(22) Логично что на сервере в 1С нет смысла в кнопках, значит клиент.
На клиенте в формах есть ПодключитьОбработчикОжидания
   TormozIT
 
24 - 30.09.20 - 10:25
(23) 50мс?
   Garykom
 
25 - 30.09.20 - 10:26
(24) "<Интервал> (обязательный)
Тип: Число. 
Интервал времени в секундах с точностью до 1/10 секунды, через который будет осуществляться вызов процедуры (положительное число)."

100мс можно
   trad
 
26 - 30.09.20 - 10:30
(23) "Логично что на сервере в 1С нет смысла в кнопках, значит клиент."
Логично, кто ж спорит ))
   trad
 
27 - 30.09.20 - 10:32
(23) "ПодключитьОбработчикОжидания"
А в какой момент отключать обработчик?
На кейап?
А если он случился не в фокусе?
   trad
 
28 - 30.09.20 - 10:35
Я не изучал как устроен этот кхук с иса, но знаю что WM_KEYDOWN генерится и при физическом нажатии и при автоповторе
   Garykom
 
29 - 30.09.20 - 10:38
(27) Вне 1С? Ну это засада с данной ВК в целом
   trad
 
30 - 30.09.20 - 10:42
(29) Ну конечно вне 1с.
Организовывать автоповтор внутри, в данной ситуации, бесперспективная затея
 
 Рекламное место пустует
   trad
 
31 - 30.09.20 - 10:44
Посмотрел.
Там где-то вокруг вот этого надо поплясать
int Action    = (pm->m_FirstInterception ? HC_NOREMOVE : HC_ACTION);
и выкурить это блокирование автоповтора
   trad
 
32 - 30.09.20 - 10:45
более полная цитата:
int Action    = (pm->m_FirstInterception ? HC_NOREMOVE : HC_ACTION);
  if (pm->m_HookEnabled && (nCode == Action))
   TormozIT
 
33 - 30.09.20 - 11:01
(32) Если ты думаешь, что "m_FirstInterception" это типа "первое нажатие", то нет. Это "перехват первым до обработки приложением".
   trad
 
34 - 30.09.20 - 11:04
(33) слабо мне понятная муть ))
   TormozIT
 
35 - 30.09.20 - 11:10
(34) Это объяснение от автора ВК.
   TormozIT
 
36 - 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;
}


Список тем форума
Рекламное место пустует  Рекламное место пустует
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.