c++ - 如何在 Windows 10 (C++) 中生成全局滚动事件并禁用鼠标移动?
问题描述
我正在编写一个程序来在触摸板上实现手性滚动。我有读取原始触摸板数据的代码,并且我对如何实现手势有一个粗略的了解。我的问题是如何实现滚动行为。这些是我的要求:
- 我的程序需要能够生成滚动事件,就像默认的触摸板手势或鼠标滚轮一样。这应该会影响任何正在运行的程序,就像真正的鼠标或触摸板滚动一样。最好,滚动也应该是平滑的(不是大刻度)。
- 当滚动手势生效时,应该禁用正常的鼠标移动。这很重要,因为它将确保正在滚动的 UI 元素在滚动期间不会发生变化。
- 不应影响其他内置触摸板手势。
我在这里有什么选择?
有没有可以提供帮助的图书馆?
这是否需要作为某种驱动程序来实现?
我已经想到并研究了一些可能的解决方案,但它们似乎都不完整:
- 可能有某种程序化的虚拟鼠标库,如果是这样我可以使用它来生成滚轮事件,但是我还没有找到这样的库,我不确定它是否可以实现#2。
- 我已经阅读了一些关于 Windows 钩子的内容,但它看起来只能修改现有的鼠标事件,这在此处不起作用。
- 我还阅读了一些关于 SentInput 函数的信息,但听起来它也无法实现 #2,而且我不确定它是否会影响所有其他程序。
解决方案
我认为 hook 和SendInput可以满足您的需求。
这是一个快速的gif演示。
运行代码,
- 按“L”键=>安装鼠标钩(开始)
- 按鼠标左键 => 开始滚动
- 按鼠标右键 => 停止滚动
- 按“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;
}
推荐阅读
- c++ - 转换数据类型以添加到 QByteArray 以将原始数据写入文件
- python - 迭代空列表的时间复杂度
- android - android:gravity="center" 在 Pre-Lollipop 操作系统中不起作用?
- javascript - 使用 Bactracking 的子集总和
- ios - UIDynamicItemBehavior.density 不影响 UIFieldBehavior 中的对象物理?
- regex - 使用正则表达式以相同的顺序搜索一组关键字
- python - Tensorflow-GPU 安装 ImportError: DLL load failed: 找不到指定的模块
- python - 如果有符号链接,Python distutils copy_tree 无法更新
- mysql - 在多个表中查询总和
- git - bfg Cleaner 后无法推送