На главную Наши проекты:
Журнал   ·   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-процедуры мыши.
    Цитата ЫукпШ @
    И как правильно поставить глобальный хук.
    (А мысли поставить хук локально меня ни разу не посещали )

    А чем, собственно, мой хук, чья процедура расположена не в DLL, а в коде текущего процесса, не глобальный, если он прекрасно ловит клики мышкой во всех запущенных приложениях? Локальный хук — это хук, который отлавливает что-то в одном приложении. И для этого, как раз, нужно написать и инжектнуть в сторонний процесс DLL. А для установки глобального хука, как видно из моего примера, вовсе не обязательно. :-?
    Или я неправильно понимаю значение понятий глобального и локального хука?
      Во-первых, LowLevelHooks не внедряются в другие процессы. Вместо этого ОСь переключает контекст на процесс, нитка которого инсталлировала хук, вызывает в нём функцию хука, а затем переключается обратно. Собственно поэтому такие глобальные хуки не надо размещать в DLL.
      Во-вторых, ввиду того, что lowlevel-события в подавляющем большинстве случаев будут приходить в поток асинхронно, ОСь не может вот просто взять и прервать поток хука на полуслове, чтобы сделать якобы вызов его функции посреди дороги. Ни одному приложению не понравится, если посреди потока его инструкций внезапно из-за прерывания вдруг сменится окружающий контекст, типа там регистры процессора, переменные в памяти, закешированные оптимизатором в регистрах не volatile переменные из памяти итп. Прервать поток можно только в безопасные к таким нюансам моменты времени. И обработка сообщений самое для этого место и время. Поэтому поток должен обрабатывать свою очередь сообщений, чтобы получать вызовы своего хука. Достаточно просто вызвать GetMessage(), и пока она не вернула управление, ОСь может безопасно вызвать функцию хука без любых неожиданностей для окружающего поток контекста.
      В-третьих, у тебя в примере нет окон, сообщения выбираются прямо из очереди потока. Внимание – вопрос: хрен с TranslateMessage(), но что там делает DispatchMessage()? Сообщения потока так не обрабатываются, у него нет оконной функции.
        Цитата lem0nify @
        Какая разница? Это же глобальный хук.

        Ну вот такие ответы есть на SO, мож они чем помогут:

        1)
        Цитата
        The events are posted to the active window. Console windows are owned by the console subsystem, csrss.exe, and it receives the events, then translates them to characters and puts them in the console object which is your application's stdin.

        If you want to process events the Win32 GUI way, you should use a Win32 window (e.g. RegisterClass and CreateWindow), not a console window.

        If you just want the callbacks to work for a certain period of time, you can use an alertable wait such as SleepEx or MsgWaitForMultipleObjects, which accept a timeout.

        2)
        Цитата
        The problem is that SetWindowHookEx is based upon the Win32 message handling model. Console windows are children of the Kernel itself and do not create their own message pumps or windows.

        AFAIK doing what you want directly is not possible.

        3)
        Цитата
        The low-level hooks, WH_KEYBOARD_LL and WH_MOUSE_LL are different from all the other hooks. They don't require a DLL to be injected into the target process. Instead, Windows calls your hook callback directly, inside your own process. To make that work, a message loop is required. There is no other mechanism for Windows to make callbacks on your main thread, the callback can only occur when you've called Get/PeekMessage() so that Windows is in control.

        A global hook like WH_KEYBOARD is very different. It requires a DLL and the callback occurs within the process that processes the keyboard message. You need some kind of inter-process communication to let your own program be aware of this. Named pipes are the usual choice. Which otherwise of course requires that this injected process pumps a message loop. It wouldn't get keyboard messages otherwise.

        Favor a low-level hook, they are much easier to get going. But do pump or it won't work. And beware of timeouts, if you're not responsive enough then Windows will kill your hook without notice.

        Таким образом, я бы сперва попробовал ради теста залепить хук в GUI приложении, посмотреть изменилась ли обработка по времени. Так ли обрабатываются сообщения винды. Всеж, как писали выше, консольное приложение имеет отличия от обычных (GUI). Ну и если нет очевидного и аргументированного ответа - что еще поможет как собственные тесты и разборки?

        Добавлено
        Цитата Qraizer @
        Сообщения потока так не обрабатываются, у него нет оконной функции.

        Вот и я об этом уже второй пост пишу :-?
          Цитата Qraizer @
          В-третьих, у тебя в примере нет окон

          Цитата JoeUser @
          Таким образом, я бы сперва попробовал ради теста залепить хук в GUI приложении, посмотреть изменилась ли обработка по времени.

          Нарисовал окошко:
          ExpandedWrap disabled
            #include <Windows.h>
             
            void InputRButtonDown()
            {
                INPUT inp;
                memset(&inp, 0, sizeof(INPUT));
             
                inp.type = INPUT_MOUSE;
                inp.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
             
                SendInput(1, &inp, sizeof(INPUT));
            }
             
            void InputRButtonUp()
            {
                INPUT inp;
                memset(&inp, 0, sizeof(INPUT));
             
                inp.type = INPUT_MOUSE;
                inp.mi.dwFlags = MOUSEEVENTF_RIGHTUP;
             
                SendInput(1, &inp, sizeof(INPUT));
            }
             
            LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
            {
                MSLLHOOKSTRUCT* mhs = (MSLLHOOKSTRUCT*)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(mhs->mouseData);
                        if (button == XBUTTON2) {
                            InputRButtonDown();
                        }
                        break;
             
                    case WM_XBUTTONUP:
                        button = HIWORD(mhs->mouseData);
                        if (button == XBUTTON2) {
                            InputRButtonUp();
                        }
                        break;
                    }
                }
                
                return CallNextHookEx(NULL, nCode, wParam, lParam);
            }
             
            LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
            {
                static HHOOK hHook;
                switch (msg)
                {
                case WM_CREATE:
                    hHook = SetWindowsHookExW(WH_MOUSE_LL, MouseProc, NULL, 0);
                    break;
             
                case WM_CLOSE:
                    UnhookWindowsHookEx(hHook);
                    DestroyWindow(hWnd);
                    break;
             
                case WM_DESTROY:
                    PostQuitMessage(0);
                    break;
             
                default:
                    return DefWindowProcW(hWnd, msg, wParam, lParam);
                }
                return 0;
            }
             
            int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
            {
                static const wchar_t className[] = L"MyWindowClass";
             
                WNDCLASSEX wc;
                memset(&wc, 0, sizeof(wc));
             
                wc.cbSize = sizeof(WNDCLASSEX);
                wc.style = 0;
                wc.lpfnWndProc = WndProc;
                wc.cbClsExtra = 0;
                wc.cbWndExtra = 0;
                wc.hInstance = hInstance;
                wc.hIcon = LoadIconW(NULL, IDI_APPLICATION);
                wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
                wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
                wc.lpszMenuName = NULL;
                wc.lpszClassName = className;
                wc.hIconSm = LoadIconW(NULL, IDI_APPLICATION);
             
                if (!RegisterClassExW(&wc))
                {
                    MessageBoxW(NULL, L"Class registration failed!", L"Error", MB_ICONERROR | MB_OK);
                    return 0;
                }
             
                HWND hWnd = CreateWindowExW(
                    WS_EX_CLIENTEDGE,
                    className,
                    L"Window",
                    WS_OVERLAPPEDWINDOW,
                    CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
                    NULL, NULL, hInstance, NULL
                );
             
                if (hWnd == NULL)
                {
                    MessageBoxW(NULL, L"Window creation failed!", L"Error", MB_ICONERROR | MB_OK);
                    return 0;
                }
             
                ShowWindow(hWnd, nCmdShow);
                UpdateWindow(hWnd);
             
                MSG msg;
                while (GetMessageW(&msg, NULL, 0, 0) != 0) {
                    TranslateMessage(&msg);
                    DispatchMessageW(&msg);
                }
             
                return msg.wParam;
            }


          Прекрасно, только разницы никакой: как была задержка, так и осталась. Что теперь не так?
            Цитата lem0nify @
            Прекрасно, только разницы никакой: как была задержка, так и осталась. Что теперь не так?

            Завтра попробую у себя. Интересно.
              Ну что могу сказать. Задержка возникает уже на приёме управления хуком, т.е. система её вызывает с задержкой. Думаю, причина в оптимизации ОСью возможных очень частых событий.
              Попробуй другие ОСи, если есть возможность. Я пробовал в Win10Pro x64. Ещё попробуй всё ж обычный WH_MOUSE, не _LL. Но для него реально нужна будет DLL.
                Цитата lem0nify @
                Прекрасно, только разницы никакой: как была задержка, так и осталась.

                1. А как ведёт себя задержка для стандартных клавиш мыши ?
                2. Как ведёт себя задержка для стандартных клавиш мыши у "стандартной"
                мыши. Без наворотов с дополнительными клавишами, колёсами итд. ?
                ---
                Исследуй ситуацию, ставь эксперименты.
                За тебя этого никто не сделает.
                ---
                Может, мы совершенно по-разному оцениваем результаты ?
                То, что ты считаешь недопустимой задержкой я полагаю
                допустимой. Отсюда и разночтения. :(
                ---
                Вот, я приаттачил тесты. Попробуй их запустить.
                Вывод производится в окно утилиты DbgView.
                Прикреплённый файлПрикреплённый файлtest.7z (181,68 Кбайт, скачиваний: 468)
                Сообщение отредактировано: ЫукпШ -
                  Цитата ЫукпШ @
                  1. А как ведёт себя задержка для стандартных клавиш мыши ?

                  Точно так же.
                  Цитата ЫукпШ @
                  2. Как ведёт себя задержка для стандартных клавиш мыши у "стандартной"
                  мыши. Без наворотов с дополнительными клавишами, колёсами итд. ?

                  Нет стандартной мыши под рукой, к сожалению. Только Bloody T70, однако я её софт даже не ставил, так что она должна восприниматься системой как самая обычная мышь, по идее.
                    Цитата lem0nify @
                    Только Bloody T70, однако я её софт даже не ставил, так что она должна восприниматься системой как самая обычная мышь, по идее.

                    3. А если установить софт и попробовать ?
                    4. также интересно - мышь проводная или беспроводная ?
                    Есть ли разница между этими вариантами ?
                      Цитата ЫукпШ @
                      3. А если установить софт и попробовать ?
                      4. также интересно - мышь проводная или беспроводная ?

                      С софтом то же самое. Мышь проводная. Да нет, тут явно мышь ни при чём, это что-то в системе. В виртуалках даже пробовал, всё одно и то же.
                        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                        0 пользователей:


                        Рейтинг@Mail.ru
                        [ Script execution time: 0,0394 ]   [ 17 queries used ]   [ Generated: 19.03.24, 02:18 GMT ]