我正在构建一个应用程序,它从另一台计算机接收鼠标移动/按下/释放命令,并使用Windows Sendinput功能模拟它们。
除非我点击生成Sendinput调用的同一窗口的最小化或最大化或关闭按钮,否则一切正常。
在这种情况下,鼠标指针在最小化按钮(或最大化或关闭)之上冻结,并且UI事件循环似乎完全冻结。 如果我手动点击屏幕上的某个位置,UI会解冻,一切都会再次运作。
以下是在最小化按钮上生成sendinput调用时会发生什么情况的屏幕截图:
这是我用来模拟鼠标移动/按下/释放的代码: 的 Mouse.cpp
#include "Mouse.h"
#ifdef _WIN32
#include <windows.h>
#endif
#ifdef _WIN32
void Mouse::moveToPoint(const int x, const int y)
{
// get screen resolution
HDC hDCScreen = GetDC(NULL);
int horres = GetDeviceCaps(hDCScreen, HORZRES);
int vertres = GetDeviceCaps(hDCScreen, VERTRES);
ReleaseDC(NULL, hDCScreen);
const int points_in_line = 65535;
const double points_in_x_pixel = points_in_line / static_cast<double>(horres);
const double points_in_y_pixel = points_in_line / static_cast<double>(vertres);
INPUT event;
event.type = INPUT_MOUSE;
event.mi.dx = x * points_in_x_pixel; //+ 0.5;
event.mi.dy = y * points_in_y_pixel; //+ 0.5;
event.mi.mouseData = 0;
event.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
event.mi.time = 0;
event.mi.dwExtraInfo = 0;
SendInput(1, &event, sizeof(event));
}
void Mouse::press(Qt::MouseButton button)
{
DWORD btn = button == Qt::LeftButton ? MOUSEEVENTF_LEFTDOWN :
button == Qt::RightButton ? MOUSEEVENTF_RIGHTDOWN :
button == Qt::MidButton ? MOUSEEVENTF_MIDDLEDOWN : 0;
INPUT event;
event.type = INPUT_MOUSE;
event.mi.dx = 0;
event.mi.dy = 0;
event.mi.mouseData = 0;
event.mi.dwFlags = btn;
event.mi.time = 0;
event.mi.dwExtraInfo = 0;
SendInput(1, &event, sizeof(event));
}
void Mouse::release(Qt::MouseButton button)
{
DWORD btn = button == Qt::LeftButton ? MOUSEEVENTF_LEFTUP :
button == Qt::RightButton ? MOUSEEVENTF_RIGHTUP :
button == Qt::MidButton ? MOUSEEVENTF_MIDDLEUP : 0;
INPUT event;
event.type = INPUT_MOUSE;
event.mi.dx = 0;
event.mi.dy = 0;
event.mi.mouseData = 0;
event.mi.dwFlags = btn;
event.mi.time = 0;
event.mi.dwExtraInfo = 0;
SendInput(1, &event, sizeof(event));
}
void Mouse::scroll(int value)
{
INPUT event;
event.type = INPUT_MOUSE;
event.mi.dx = 0;
event.mi.dy = 0;
event.mi.mouseData = value * WHEEL_DELTA;
event.mi.dwFlags = MOUSEEVENTF_WHEEL;
event.mi.time = 0;
event.mi.dwExtraInfo = 0;
SendInput(1, &event, sizeof(event));
}
void Mouse::doubleClick(Qt::MouseButton button)
{
press(button);
release(button);
std::chrono::milliseconds dura(100);
std::this_thread::sleep_for(dura);
press(button);
release(button);
}
#endif
和头文件: Mouse.h
#ifndef MOUSE_H
#define MOUSE_H
#include <thread>
#include <QtGlobal>
#include <QtEvents>
#include <QDebug>
#include <iostream> //std::cout
class Mouse {
public:
// fails if given coordinates are not in the screen's rect
// Linux: fails if there is an opening X display error
static void moveToPoint(const int x, const int y);
static void doubleClick(Qt::MouseButton button);
// fails if the given button is not Qt::LeftButton, Qt::RightButton or Qt::MiddleButton
// Linux: fails if there is an opening X display error
static void press(Qt::MouseButton button);
static void release(Qt::MouseButton button);
// Linux: fails if there is an opening X display error
static void scroll(int value); //positive values for scrolling up, negative for scrolling down
private:
static Qt::MouseButtons bp;
static void selectArea(const int x, const int y);
};
#endif // MOUSE_H
这种奇怪行为可能是什么原因?
答案 0 :(得分:3)
正如您所发现的,单击其中一个标题按钮会导致Windows进入自己的消息循环,等待按钮释放。
当Windows处于此消息循环中时,您自己的消息循环正在等待的任何消息(知道何时释放按钮)都不会发送给您。您永远不会收到释放鼠标按钮的消息,因此请不要注入该输入,因此指针似乎已冻结。
解决方案是将您的SendInput
调用移至非GUI线程。