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

获取窗口内鼠标位置异常求助:坐标与窗口分辨率不符

解决窗口客户区光标坐标与预期分辨率不符的问题

你遇到的核心问题是混淆了「窗口整体尺寸」和「客户区(渲染区域)尺寸」——你设置的1680x1050是包含标题栏、边框的整个窗口大小,Windows会自动从这个尺寸里扣除边框和标题栏的占用空间,导致实际渲染区域的尺寸比预期小,所以光标移到最右侧只能到1660左右。下面一步步给你解决思路:

一、为什么会出现坐标偏差?

CreateWindowEx中传入的宽高参数对应的是整个窗口的尺寸(包含标题栏、边框),而非你需要的渲染区域(客户区)尺寸。系统会根据窗口样式自动计算边框、标题栏的宽度/高度,从总尺寸中扣除后才是客户区的实际大小,这就是坐标达不到预期值的根本原因。

另外,你提到光标在标题栏内时y坐标为0:标题栏属于窗口的非客户区,此时ScreenToClient转换后的坐标本应落在客户区范围之外(通常y为负数),你看到的0可能是特殊场景下的表现,但我们的核心目标是获取客户区内的有效坐标,所以先聚焦到正确设置客户区尺寸上。

二、创建客户区尺寸为1680x1050的窗口

要让渲染区域正好是1680x1050,你需要用AdjustWindowRectEx函数,根据目标客户区尺寸反算出所需的窗口整体大小(包含边框和标题栏)。修改你的窗口创建代码如下:

// 定义目标客户区尺寸
const int targetClientWidth = 1680;
const int targetClientHeight = 1050;

// 计算能容纳目标客户区的窗口整体尺寸
RECT windowRect = {0, 0, targetClientWidth, targetClientHeight};
AdjustWindowRectEx(
    &windowRect,
    (WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME) | WS_VISIBLE,
    FALSE,
    0
);

// 创建窗口时使用计算后的尺寸
HWND windowHandle = CreateWindowEx(
    0,
    windowClass.lpszClassName,
    L"D3D11 Rendering",
    (WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME) | WS_VISIBLE,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    windowRect.right - windowRect.left,  // 窗口实际宽度
    windowRect.bottom - windowRect.top,  // 窗口实际高度
    0,
    0,
    hInstance,
    0
);

AdjustWindowRectEx会根据你指定的窗口样式,自动计算出刚好能容纳目标客户区的窗口大小,这样创建出来的窗口,客户区就完全符合你想要的1680x1050了。

三、正确获取客户区内的光标坐标

窗口尺寸设置正确后,两种方法都能准确获取客户区坐标:

方法1:通过WM_MOUSEMOVE事件获取

WM_MOUSEMOVE消息的lParam参数本身就是相对于客户区左上角的坐标,直接解析即可,无需额外转换:

case WM_MOUSEMOVE:
{
    int clientX = GET_X_LPARAM(lParam);
    int clientY = GET_Y_LPARAM(lParam);
    // clientX范围是0~1679,clientY范围是0~1049,完全对应客户区
    break;
}

注意:该消息仅在光标处于客户区内时触发,所以得到的坐标一定是有效的渲染区域坐标。

方法2:用GetCursorPos + ScreenToClient主动获取

如果需要在主循环中主动查询光标位置,这个方法依然有效,现在窗口尺寸正确后,转换结果会准确对应客户区:

POINT cursorPos;
GetCursorPos(&cursorPos);
ScreenToClient(windowHandle, &cursorPos);

// 可选:判断光标是否在客户区内,避免处理非客户区的无效坐标
RECT clientRect;
GetClientRect(windowHandle, &clientRect);
if (PtInRect(&clientRect, cursorPos))
{
    // cursorPos.x和cursorPos.y是有效的客户区坐标
}

额外说明

  • 你用WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME去掉窗口可调边框的样式,不会影响AdjustWindowRectEx的计算逻辑,上面的代码完全适用。
  • 如果后续需要动态调整客户区尺寸,同样可以用AdjustWindowRectEx重新计算窗口大小,再调用SetWindowPos更新窗口。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:07:43