На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Задержка при имитации событий мыши из низкоуровневой hook-процедуры мыши.
    Доброго времени суток!
    Пишу сюда, потому что тут, помнится, сидят матёрые программисты с вагоном опыта. На StackOverflow ребята пожимают плечами.
    ExpandedWrap disabled
      #include <Windows.h>
       
      void InputRButtonDown()
      {
          INPUT inp;
          inp.type = INPUT_MOUSE;
          inp.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
       
          SendInput(1, &inp, sizeof(INPUT));
      }
       
      void InputRButtonUp()
      {
          INPUT inp;
          inp.type = INPUT_MOUSE;
          inp.mi.dwFlags = MOUSEEVENTF_RIGHTUP;
       
          SendInput(1, &inp, sizeof(INPUT));
      }
       
      LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
      {
          if (nCode >= 0)
          {
              WORD button;
              switch (wParam)
              {
              case WM_LBUTTONDOWN:
                  break;
       
              case WM_LBUTTONUP:
                  break;
       
              case WM_RBUTTONDOWN:
                  break;
       
              case WM_RBUTTONUP:
                  break;
       
              case WM_XBUTTONDOWN:
                  button = HIWORD(((MSLLHOOKSTRUCT*)lParam)->mouseData);
                  if (button == XBUTTON2) {
                      InputRButtonDown();
                  }
                  break;
       
              case WM_XBUTTONUP:
                  button = HIWORD(((MSLLHOOKSTRUCT*)lParam)->mouseData);
                  if (button == XBUTTON2) {
                      InputRButtonUp();
                  }
                  break;
              }
          }
       
          return CallNextHookEx(NULL, nCode, wParam, lParam);
      }
       
      int main()
      {
          SetWindowsHookExW(WH_MOUSE_LL, MouseProc, NULL, 0);
       
          MSG msg;
          while (GetMessageW(&msg, NULL, 0, 0) != NULL) {
              TranslateMessage(&msg);
              DispatchMessageW(&msg);
          }
      }

    Есть вот такой простой код. Тут устанавливается LowLevel Mouse Hook, обрабатывающий глобально нажатия кнопок мыши. При нажатии на XBUTTON2, одну из боковых кнопок, вызывается функция InputRButtonDown, при отжатии — InputRButtonUp, которые отправляют сигналы нажатия и отжатия другой кнопки мыши (правой) соответственно. Т.е. пока программа запущена, клик на XBUTTON2 должен дополнительно полностью имитировать клик правой кнопки мыши и вызывать контекстное меню. Так и происходит, но перед выпадом контекстного меню случается задержка (полсекунды или чуть меньше).
    Если я немного меняю код и вызываю те же самые SendInput, но не в hook-процедуре мыши, а в аналогичной hook-процедуре клавиатуры, скажем, при нажатии на клавишу А, никакой задержки нет. Если я, наоборот, отправляю с помощью SendInput сигналы нажатия клавиши клавиатуры из любой из hook-процедур, будь то hook-процедура мыши или клавиатуры, задержки тоже нет, нажатие клавиши имитируется мгновенно. Т.е. задержка возникает только при отправке инпута мыши из hook-процедуры мыши.
    Пробовал вызывать SendInput при получении WM_LBUTTONDOWN/UP, вместо WB_XBUTTONDOWN/UP — задержка сохраняется. Обнулять структуру INPUT перед вызовом SendInput тоже пробовал — разницы никакой.
    На StackOverflow мне скинули вот эту ссылку, мотивируя тем, что эта задержка возникает из-за очереди обработки событий, мол, это нормально, и поделать с этим ничего нельзя. Однако, 400-500 миллисекунд — не великовато ли? Кроме того, различные автокликеры, вроде AutoHotKey и AutoIt, выполняют подобные задачи без всяких задержек, значит избежать их всё-таки можно, и я что-то делаю не так.
    Второй день бьюсь, не могу понять, из-за чего возникает проблема и как её решить. Не мог бы кто-нибудь из опытных Win32API-программистов пролить свет на ситуацию и объяснить мне? Буду очень благодарен.
      Подозреваю, что ребята с БиткомНабитогоМагазина могут быть не так уж и неправыми. Как там с 32-/64- битностью?
        Цитата lem0nify @
        Т.е. задержка возникает только при отправке инпута мыши из hook-процедуры мыши.

        А инпут "оформлен" правильно и достаточно?
        Меня во эта статья убеждает - что не очень.
          Цитата Qraizer @
          Подозреваю, что ребята с БиткомНабитогоМагазина могут быть не так уж и неправыми. Как там с 32-/64- битностью?

          Система 64-битная, конечно. Компьютер почти современный. Программу компилирую тоже под х64, конечно же.

          Цитата JoeUser @
          А инпут "оформлен" правильно и достаточно?
          Меня во эта статья убеждает - что не очень.

          Насколько я понимаю, в этой статье симулируется клик в определённую точку с абсолютной позицией, поэтому указывается флаг MOUSEEVENTF_ABSOLUTE и указываются координаты точки. Мне нужен клик в текущую фактическую позицию курсора мыши, т.е. позиция выбирается не абсолютно, а относительно, поэтому данный флаг я не указываю, а inp.mi.dx и inp.mi.dy оставляю равными нулю.

          Ещё раз, на всякий случай, обращу ваше внимание на то, что при любых других обстоятельствах данный способ отправки инпута работает превосходно. Задержка возникает ТОЛЬКО при отправке его из Low Level Mouse Hook Procedure.
          Сообщение отредактировано: lem0nify -
            Хорошо, уточню:
            Цитата SetWindowsHookExW
            Because hooks run in the context of an application, they must match the "bitness" of the application. If a 32-bit application installs a global hook on 64-bit Windows, the 32-bit hook is injected into each 32-bit process (the usual security boundaries apply). In a 64-bit process, the threads are still marked as "hooked." However, because a 32-bit application must run the hook code, the system executes the hook in the hooking app's context; specifically, on the thread that called SetWindowsHookEx. This means that the hooking application must continue to pump messages or it might block the normal functioning of the 64-bit processes.

            If a 64-bit application installs a global hook on 64-bit Windows, the 64-bit hook is injected into each 64-bit process, while all 32-bit processes use a callback to the hooking application.

            To hook all applications on the desktop of a 64-bit Windows installation, install a 32-bit global hook and a 64-bit global hook, each from appropriate processes, and be sure to keep pumping messages in the hooking application to avoid blocking normal functioning. If you already have a 32-bit global hooking application and it doesn't need to run in each application's context, you may not need to create a 64-bit version.


            Добавлено
            Вопрос не в конкретной разрядности, вопрос в совпадении битности хукающего и хукаемого.
              Что-то я не очень понимаю. Если я кликаю в определённом приложении (допустим, стандартный Windows'овский блокнот), разве не только его разрядность и разрядность моей программы играет роль? Клик всё равно обрабатывается всеми хуками, инжектнутыми во все приложения в системе? Хорошо, допустим. А как создать два разных хука разной разрядности и распределить по ним приложения соответствующей разрядности?
              И почему с клавиатурными хуками, тогда, всё в порядке? Это касается только MouseHook'ов?
                lem0nify, чет я не совсем понимаю кода. Ты пытаешься отловить мышь в консольном приложении?
                Может все же GUI окно создать сперва?
                  Цитата JoeUser @
                  lem0nify, чет я не совсем понимаю кода. Ты пытаешься отловить мышь в консольном приложении?
                  Может все же GUI окно создать сперва?

                  Какая разница? Это же глобальный хук. Я не в своём окне мышь ловлю, а по всей системе. И она прекрасно ловится, проблема в другом. Вы пост-то полностью прочитали? Там же всё объяснено.
                    Цитата lem0nify @
                    Какая разница? Это же глобальный хук.

                    Понятно сейчас.

                    Цитата lem0nify @
                    задержки тоже нет

                    А чем задержку считаем, просто на глаз?
                      Цитата JoeUser @
                      А чем задержку считаем, просто на глаз?

                      Да, просто на глаз. Ну там, как бы, совершенно очевидно, что она нездорово большая. Это не какое-то подвисание железа или типа того, а прям такая заметная системная задержка. Компьютер, как уже говорил, вполне приличный.
                        Цитата lem0nify @
                        Есть вот такой простой код. Тут устанавливается LowLevel Mouse Hook, обрабатывающий глобально нажатия кнопок мыши.

                        А это точно можно делать ?
                        Насколько я помню, для установки глобального хука процедура
                        обработчика должна быть в dll.
                        Любая моя попытка сделать "SetWindowsHookEx(WH_MOUSE_LL, MouseProc.." в теле основной
                        программы обязательно приводит к ошибке.
                        В примере выше результат выполнения этой функции даже не проверяется. :(
                        -----
                        Что касается задержки - у меня был старый проект, я быстренько
                        его модифицировал. Но для x86 и с использованием dll.
                        Так вот, большой задержки я не вижу, даже с учётом накладного
                        по времени вывода диагностики. Хотя разница между кликами
                        иногда бывает заметна. Но Виндус "мгновенной" реакции и не гарантирует.
                        -----
                        Попробовал запуститься в виртуальной машине (Win7 x64).
                        Для обеих сборок - x86 и x64 - задержек не обнаружено.
                        Сообщение отредактировано: ЫукпШ -
                          Цитата ЫукпШ @
                          Насколько я помню, для установки глобального хука процедура
                          обработчика должна быть в dll.

                          Видите ли, на самом деле, это всё вообще в конечном итоге будет в виде аддона к Node.js. Моя цель — джаваскриптуемый автокликер на базе ноды. Аддон к ноде — это и есть самая обычная DLL, просто с расширением .node и особым форматом. Разницы в поведении, что в виде аддона для ноды, что в виде отдельного консольного приложения Windows, я не замечаю. Просто, дабы не отягощать тему лишней информацией и специфичным для Napi кодом, я накидал отдельную консольную программу и выложил сюда её код.

                          Цитата ЫукпШ @
                          Любая моя попытка сделать "SetWindowsHookEx(WH_MOUSE_LL, MouseProc.." в теле основной
                          программы обязательно приводит к ошибке.

                          Это странно. Вы уверены? Вы пробовали скомпилировать у себя мой код в проекте консольного приложения? Почему у меня он не выкидывает никаких ошибок, а у Вас выкидывает?
                            Цитата lem0nify @
                            Цитата ЫукпШ @
                            Любая моя попытка сделать "SetWindowsHookEx(WH_MOUSE_LL, MouseProc.." в теле основной
                            программы обязательно приводит к ошибке.

                            Это странно. Вы уверены? Вы пробовали скомпилировать у себя мой код в проекте консольного приложения?

                            Абсолютно уверен.
                            И, конечно же, я не компилировал предложенный исходник.
                            Создал тестовый проект, взял каркас оконного приложения итд.
                            Разобрал старый учебный проект, вспомнил, что и раньше было так же.
                            Скрытый текст

                            Да вот, пожалуйста:
                            Обсуждение похожей проблемы
                            Цитата

                            Ребят подскажите пожалуйста где у меня ошибка почему при нажатиии мыши у меня не срабатывает моя хук процедура вот код

                            Цитата

                            ...Поэкспериментируйте. Просто обычно хуки нужны для чужих процессов и делются в DLL, а не так вот. Какой смысл в хуке на самого себя?

                            Цитата

                            chel-0007, как правильно сказал kukuruku310, глобальный хук должен находиться в dll. Поэтому глобальным хуком здесь и не пахнет.

                              Цитата ЫукпШ @
                              Да вот, пожалуйста:
                              Обсуждение похожей проблемы

                              Вам не кажется, что у автора той темы хук некорректно устанавливается только по той причине, что он сопровождает в функцию SetWindowsHookEx третий параметр не равным NULL? На MSDN ведь чётко и ясно сказано, что третий параметр должен быть равен NULL в том случае, если хук-процедура расположена в коде текущего процесса, что само по себе говорит о том, что так делать можно.

                              Цитата SetWindowsHookExA
                              hmod

                              Type: HINSTANCE

                              A handle to the DLL containing the hook procedure pointed to by the lpfn parameter. The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by the current process and if the hook procedure is within the code associated with the current process.
                                Цитата lem0nify @
                                Вам не кажется, что у автора той темы хук некорректно устанавливается только по той причине, что он сопровождает в функцию SetWindowsHookEx третий параметр не равным NULL? На MSDN ведь чётко и ясно сказано, что третий параметр должен быть равен NULL в том случае, если хук-процедура расположена в коде текущего процесса, что само по себе говорит о том, что так делать можно.

                                Не спорю - может быть и можно.
                                я лишь рассказал, что у меня лично получилось и не получилось.
                                И как правильно поставить глобальный хук.
                                (А мысли поставить хук локально меня ни разу не посещали :( )
                                А ссылку я дал чтобы обратить внимание на необходимость
                                размещения процедуры перехватчика глобального хука в dll.
                                ---
                                Если же посмотреть подробнее на исходник по ссылке, так там
                                он либо не полный, либо явно ошибочный.
                                Причём автор не объяснил, где ошибку сделал.
                                Вероятно, тут:
                                ExpandedWrap disabled
                                  HINSTANCE hmod;

                                Какое значение у этой переменной перед подачей на "SetWindowsHookEx"?
                                Сообщение отредактировано: ЫукпШ -
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0511 ]   [ 17 queries used ]   [ Generated: 16.04.24, 22:47 GMT ]