Как генерировать глобальные события прокрутки и отключить движение мыши в Windows 10 (С++)?

Я пишу программу для реализации хиральной прокрутки на сенсорной панели. У меня есть код для чтения необработанных данных сенсорной панели, и у меня есть приблизительное представление о том, как я хочу реализовать этот жест. Мой вопрос заключается в том, как реализовать поведение прокрутки. Это мои требования:

  1. Моя программа должна иметь возможность генерировать события прокрутки, как если бы это был жест сенсорной панели по умолчанию или колесо прокрутки мыши. Это должно повлиять на любую запущенную программу, точно так же, как реальная прокрутка мыши или сенсорной панели. Желательно, чтобы и прокрутка была плавной (не большими тиками).
  2. Во время действия жеста прокрутки обычное движение мыши должно быть отключено. Это важно, потому что это гарантирует, что прокручиваемый элемент пользовательского интерфейса не изменится во время прокрутки.
  3. Другие встроенные жесты сенсорной панели не должны выполняться.

Какие у меня здесь варианты? Есть ли библиотеки, которые могут помочь? Нужно ли это реализовать как какой-то драйвер?

Я подумал и рассмотрел несколько возможных решений, но ни одно из них не кажется полным:

  • Может быть какая-то программная библиотека виртуальной мыши, если это так, я мог бы использовать ее для генерации событий колеса прокрутки, но я еще не нашел такую ​​библиотеку, и я не уверен, сможет ли она достичь # 2.
  • Я немного читал о хуках Windows, но похоже, что они могут изменять только существующие события мыши, что здесь не сработает.
  • Я также немного читал о функции SentInput, но также не похоже, чтобы она могла достичь # 2, и я не уверен, что она может повлиять на все другие программы.

Этот вопрос требует большего внимания. В настоящее время он включает несколько вопросов в один. Он должен сосредоточиться только на одной проблеме. (И поскольку это Stack Overflow, речь должна идти о программировании.)

JHBonarius 21.12.2020 09:28

Здесь есть только один реальный вопрос: как создать прокрутку с поведением, которое я описал. Другие вопросы просто представляют некоторые вещи, о которых я подумал для контекста. Спрашивать кого-либо из них конкретно было бы проблемой XY. И я спрашиваю, как это сделать на C++, так что да, это вопрос программирования.

Derek 21.12.2020 10:57
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
2
2
461
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, что хук и SendInput могут удовлетворить ваши потребности.

Вот быстрая демонстрация gif.

Запустите код,

  1. Нажмите клавишу «L» => установите крючок для мыши (старт)
  2. Нажмите левую кнопку мыши => Начать прокрутку
  3. Нажать правую кнопку мыши => Остановить прокрутку
  4. Нажмите клавишу «P» => удалить крючок мыши (конец)

После того, как крючок установлен, мышь нельзя двигать. Нажмите левую кнопку мыши, и мышь будет автоматически прокручиваться. Нажмите правую кнопку мыши, чтобы остановить прокрутку. После нажатия клавиши P, чтобы удалить крючок, все вернется на круги своя.

Когда мышь автоматически прокручивается, я все еще могу вручную прокручивать колесико мыши.

Пример кода: (код приблизительный, только для справки)

#include <Windows.h>
#include <iostream>
#include <thread>

using namespace std;

UINT ScrollMouse(int scroll);
void SetHook();
LRESULT __stdcall MouseHookCallback(int, WPARAM, LPARAM);

HHOOK MouseHook;
BOOL flag = 0;

void fun1()
{
    while (1)
    {
        if (GetAsyncKeyState(0x50) & 0x0001)
        {
            UnhookWindowsHookEx(MouseHook);
        }
    }
}

void fun2()
{
    while (1)
    {
        if (flag)
        {
            ScrollMouse(50);
            Sleep(100);
        }
    }
}

int fun3()
{
    while (1)
    {
        if (GetAsyncKeyState(0x4C) & 0x0001)
        {
            SetHook();
            MSG msg;

            while(GetMessage(&msg, NULL, 0, 0))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            return msg.wParam;
        }       
    }   
}

UINT ScrollMouse(int scroll)
{
    INPUT input;
    POINT pos;
    GetCursorPos(&pos);

    input.type = INPUT_MOUSE;
    input.mi.dwFlags = MOUSEEVENTF_WHEEL;
    input.mi.time = NULL; //Windows will do the timestamp
    input.mi.mouseData = (DWORD)scroll; //A positive value indicates that the wheel was rotated forward, away from the user; a negative value indicates that the wheel was rotated backward, toward the user. One wheel click is defined as WHEEL_DELTA, which is 120.
    input.mi.dx = pos.x;
    input.mi.dy = pos.y;
    input.mi.dwExtraInfo = GetMessageExtraInfo();

    return SendInput(1, &input, sizeof(INPUT));
}

LRESULT __stdcall MouseHookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode >= 0)
    {
        switch (wParam)
        {
        case WM_MOUSEMOVE:
        {           
            return 1;         
        }
        case WM_LBUTTONDOWN:
        {
            flag = 1;            
        }
        break;
        case WM_RBUTTONDOWN:
        {
            flag = 0;
        }
        break;
        }
    }
    return CallNextHookEx(MouseHook, nCode, wParam, lParam);
}

void SetHook()
{
    if (!(MouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookCallback, NULL, 0)))
    {
        cout << "Failed to install MouseHook hook!" << endl;
    }
}

int main()
{
    thread t1(fun1);
    thread t2(fun2);   
    thread t3(fun3);  
    t3.join();

    return 0;
}

Отличный! Это делает именно то, что мне нужно! Гораздо проще, чем то, что я боялся, что мне тоже может понадобиться сделать.

Derek 23.12.2020 21:21

Другие вопросы по теме