You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何使用Windows API无法获取正确的光标坐标?

问题原因与解决方案

你的问题核心是对CreateWindowExA的宽高参数理解有误:

  • 你传入的600, 600是**整个窗口(包含标题栏、边框等非客户区)**的尺寸,不是程序内部可操作的客户区尺寸。当你期望光标在客户区右下角显示(600,600)时,实际客户区的宽高本来就小于600,所以坐标会出现偏差。

解决方法

1. 计算正确的窗口尺寸以得到指定大小的客户区

使用AdjustWindowRectEx函数,根据目标客户区尺寸和窗口样式,反推需要的窗口整体尺寸。修改CreateWindowExA的调用代码:

int clientWidth = 600;
int clientHeight = 600;
RECT windowRect = {0, 0, clientWidth, clientHeight};
// 根据窗口样式调整矩形,计算包含非客户区的窗口尺寸
AdjustWindowRectEx(&windowRect, WS_OVERLAPPEDWINDOW, FALSE, 0);

HWND Window = CreateWindowExA(0, "WindowClass", "Window", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 
    CW_USEDEFAULT, CW_USEDEFAULT, 
    windowRect.right - windowRect.left, // 窗口实际宽度
    windowRect.bottom - windowRect.top, // 窗口实际高度
    0, 0, hInstance, 0);

这样创建的窗口,其客户区的宽高会是你想要的600x600,光标移动到右下角时,坐标会接近(600,600)(注意客户区坐标从(0,0)开始,右下角实际像素索引为(599,599))。

2. 直接使用WM_MOUSEMOVE的参数获取客户区坐标

在WM_MOUSEMOVE消息中,LPARAM参数本身已经包含了光标在客户区的坐标,不需要调用GetCursorPos和ScreenToClient,直接用GET_X_LPARAM和GET_Y_LPARAM即可,代码更简洁:

case WM_MOUSEMOVE:
{
    int x = GET_X_LPARAM(LParam);
    int y = GET_Y_LPARAM(LParam);

    char Buffer[256];
    snprintf(Buffer, sizeof(Buffer), "X: %d, Y: %d\n", x, y);
    OutputDebugStringA(Buffer);
} break;

3. 验证客户区实际大小

如果需要确认当前客户区的真实尺寸,可以调用GetClientRect:

RECT clientRect;
GetClientRect(Window, &clientRect);
int actualClientWidth = clientRect.right - clientRect.left;
int actualClientHeight = clientRect.bottom - clientRect.top;
// 输出实际客户区尺寸,就能直观看到之前的偏差来源

内容的提问来源于stack exchange,提问作者Noah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 15:12:37