这是 Windows / GUI 编程中三种最常见的坐标系概念,用通俗方式给你解释:
🧭 三种坐标系空间关系概览
图例说明:
- 蓝色矩形:屏幕坐标系(原点在屏幕左上角)
- 紫色矩形:客户区坐标系(原点在窗口客户区左上角)
- 绿色矩形:父窗口坐标(子控件相对父窗口客户区偏移)
- 箭头指示
ClientToScreen/ScreenToClient等转换方向
1️⃣ 屏幕坐标(Screen Coordinates)
以整个屏幕左上角为原点 (0, 0)
- X 轴向右增大,Y 轴向下增大
- 适用于:鼠标全局位置、SetWindowPos(HWND_TOPMOST)、GetCursorPos()
示例:
+-- 屏幕 ----------------------+
| (0,0) |
| +---- 窗口 --------------+|
| | (client 0,0) ||
| +------------------------+|
+------------------------------+
API 例:
POINT pt;
GetCursorPos(&pt); // pt.x, pt.y 是屏幕坐标
2️⃣ 客户区坐标(Client Coordinates / 客户区 DC)
以窗口"客户区"左上角为原点 (0, 0)
- 不含标题栏、边框、菜单、滚动条
- 只算可绘制区域
- 适用于:
WM_LBUTTONDOWN的lParam、CDC 绘图(TextOut、LineTo)
示例:
+---------------- 窗口边框 ----------------+
| 标题栏 |
| +----------- 客户区 --------------------+ |
| | (0,0) 这里是客户区坐标原点 | |
| | | |
| +----------------------------------------+ |
+--------------------------------------------+
代码:
// WM_LBUTTONDOWN 中
int x = LOWORD(lParam); // 客户区 X
int y = HIWORD(lParam); // 客户区 Y
3️⃣ 父窗口坐标(Parent / Window Coordinates)
子窗口相对于其父窗口客户区左上角为 (0,0)
- 用于
CreateWindowEx()中指定子控件位置(按钮、编辑框等) - 父窗口可以是主窗口,也可以是容器(Group Box 等)
- 对话框单位(DLU)最终也会转成这个坐标系
示例:
// 在父窗口 hWnd 上创建按钮
CreateWindowEx(
0,
L"BUTTON",
L"确定",
WS_CHILD | WS_VISIBLE,
20, 30, // ← 相对于父窗口客户区 (20,30)
100, 30,
hWnd, // 父窗口
(HMENU)IDC_BTN_OK,
hInst,
NULL
);
🔄 坐标相互转换(非常重要)
Windows 提供 API 做转换:
// 客户区 → 屏幕
ClientToScreen(hWnd, &pt);
// 屏幕 → 客户区
ScreenToClient(hWnd, &pt);
// 子窗口坐标 → 父窗口坐标(其实就是 ClientToScreen 再 ScreenToClient 到父)
MapWindowPoints(hChild, hParent, &pt, 1);
坐标系关系与转换流程图
图表说明:
- 屏幕坐标(蓝色):以整个屏幕左上角为原点,通过
GetCursorPos获取 - 客户区坐标(紫色):以窗口客户区左上角为原点,通过
ScreenToClient从屏幕坐标转换 - 父窗口坐标(绿色):子控件相对于父窗口客户区的位置,通过
MapWindowPoints转换
转换方向:
- 屏幕 ↔ 客户区:
ScreenToClient/ClientToScreen - 客户区 ↔ 父窗口坐标:
MapWindowPoints(实际是ClientToScreen+ScreenToClient组合)
📌 一句话记忆
| 坐标系 | 原点在哪 | 常见用途 |
|---|---|---|
| 屏幕坐标 | 屏幕左上角 (0,0) | 鼠标位置、置顶窗口、拖拽 |
| 客户区坐标 | 窗口客户区左上角 | WM_PAINT、鼠标点击客户区 |
| 父窗口坐标 | 父窗口客户区左上角 | CreateWindowEx 子控件位置 |
659

被折叠的 条评论
为什么被折叠?



