我有一个使用 Win32 API 的简单 Windows C++ 程序:
#include <windows.h>
#include <windowsx.h> // GET_Y_LPARAM
#include <string>
#include <iostream>
// clang++ -std=c++23 mouse.cc -o mouse.exe -luser32 -lgdi32
// Handler for WM_MOUSEMOVE
void OnMouseMove(HWND hwnd, int x, int y) {
MOUSEMOVEPOINT inputPoint;
ZeroMemory(&inputPoint, sizeof(inputPoint)) ;
inputPoint.x = x;// & 0x0000FFFF ;
inputPoint.y = y;// & 0x0000FFFF ;
//std::cerr << x << " " << y << std::endl;
//inputPoint.time = GetMessageTime(); // Use the time of the current message
//inputPoint.dwExtraInfo = GetMessageExtraInfo();
MOUSEMOVEPOINT points[64]; // Adjust size based on your needs
int pointsRetrieved = GetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &inputPoint, points, 64, GMMP_USE_DISPLAY_POINTS);
if (pointsRetrieved > 0) {
std::cerr << pointsRetrieved << std::endl;
}
else {
//std::cerr << "Error retrieving mouse move points. Error: " << GetLastError() << std::endl;
}
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int MyWindowCreation(HINSTANCE hInstance) {
const char CLASS_NAME[] = "Sample Window Class";
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(
0,
CLASS_NAME,
"Mouse Position Display",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
if (hwnd == NULL) {
return 0;
}
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_MOUSEMOVE: {
int xPos = GET_X_LPARAM(lParam);
int yPos = GET_Y_LPARAM(lParam);
OnMouseMove(hwnd, xPos, yPos);
std::string mousePosition = "X: " + std::to_string(xPos) + ", Y: " + std::to_string(yPos);
SetWindowText(hwnd, mousePosition.c_str());
//OnMouseMove(hwnd, xPos, yPos);
break;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int main() {
HINSTANCE hInstance = GetModuleHandle(NULL);
MyWindowCreation(hInstance);
return 0;
}
我将它们放在一起尝试使用获取鼠标数据GetMouseMovePointsEx()
。我尝试了不同的方法,但我不断收到pointsRetrieved = -1
错误消息,指出它无法在缓冲区中找到该位置的鼠标数据。
我查看了该函数的 MS 文档。遗憾的是,他们提供的代码无法编译(它不尊重函数签名)。至少这段代码可以编译。我& 0x0000FFFF
在设置x
和时尝试了 with 和 without y
,但没有什么区别。传过来的坐标WM_MOUSEMOVE
是正确的。
一定是很简单的事情吧!?是否会以某种方式与硬件相关?我的意思是,也许在某些配置上,Windows 只是不记录鼠标历史记录?我使用的是 Windows 10。
有没有替代的、更好的方法来做到这一点?这是一种过时的方法吗?
那是因为你一开始就给了它错误的坐标。
根据
GetMouseMovePointsEx()
文档,它希望输入点以屏幕坐标表示:但是,为您提供了以客户端坐标
WM_MOUSEMOVE
表示的鼠标点:在处理程序内部
WM_MOUSEMOVE
,您需要先将ClientToScreen()
提供的客户端坐标转换为屏幕坐标,然后再将它们传递给GetMouseMovePointsEx()
.文档
GetMouseMovePointsEx()
甚至说了这么多: