WinAPI屏幕坐标操作异常:无法正确定位屏幕中心像素问题
WinAPI屏幕坐标操作问题:绘制位置偏差与屏幕区域未完全利用
我在使用WinAPI进行屏幕坐标操作时遇到问题,相关代码如下:
#include <stdio.h> #include <windows.h> typedef unsigned int ui; void GetSizeWindow(ui*, ui*); void GetCenterWindow(ui*, ui*); int main(){ HDC hdcwin = GetDC(NULL); ui x_center = 0, y_center = 0; POINT cours; GetSizeWindow(&x_center, &y_center); while (1) { system("cls"); for (ui x_center1 = 0; x_center1 < x_center; x_center1++) { SetPixelV(hdcwin, x_center1, y_center / 2, RGB(0, 255, 0)); } GetCursorPos(&cours); printf("(%d ; %d)\n", cours.x, cours.y); printf("[DEBUG] (%d ; %d)\n", x_center, y_center); } ReleaseDC(NULL, hdcwin); return 0; } void GetSizeWindow(ui* x, ui* y){ *x = GetSystemMetrics(SM_CXFULLSCREEN); *y = GetSystemMetrics(SM_CYFULLSCREEN); } void GetCenterWindow(ui *x, ui *y){ GetSizeWindow(x, y); *x /= 2; *y /= 2; }
最初需求是在屏幕中心绘制像素,逻辑上将屏幕宽高各除以2,但绘制的像素距中心偏差极大。为验证坐标平面,我尝试绘制贯穿屏幕长度的直线,却发现部分屏幕宽高区域未被利用。请问问题出在哪里?如何正确获取屏幕中心像素坐标?
解答
问题根源
- 误用
SM_CXFULLSCREEN/SM_CYFULLSCREEN宏:这两个宏返回的是主显示器的工作区尺寸(排除任务栏、系统停靠窗口等占用区域后的可用空间),并非整个屏幕的物理分辨率。因此你获取的宽高比实际屏幕小,导致直线无法铺满全屏,计算出的中心也只是工作区中心,而非屏幕真正的中心。 - 坐标体系不匹配:
GetCursorPos获取的是整个屏幕的绝对坐标,和你用工作区尺寸计算的中心坐标不属于同一体系,所以出现明显偏差。
正确解决方案
1. 获取完整屏幕分辨率
替换宏为SM_CXSCREEN和SM_CYSCREEN,这两个宏返回主显示器的完整屏幕分辨率(包含所有系统区域):
void GetSizeWindow(ui* x, ui* y){ *x = GetSystemMetrics(SM_CXSCREEN); *y = GetSystemMetrics(SM_CYSCREEN); }
2. 计算屏幕中心坐标
屏幕坐标从左上角(0,0)开始,中心坐标直接基于完整分辨率计算:
- 水平中心:
屏幕宽度 / 2 - 垂直中心:
屏幕高度 / 2
3. 修正后的完整代码
#include <stdio.h> #include <windows.h> typedef unsigned int ui; void GetSizeWindow(ui*, ui*); void GetCenterWindow(ui*, ui*); int main(){ HDC hdcwin = GetDC(NULL); ui screen_width = 0, screen_height = 0; ui center_x = 0, center_y = 0; POINT cours; GetSizeWindow(&screen_width, &screen_height); GetCenterWindow(¢er_x, ¢er_y); while (1) { system("cls"); // 绘制贯穿全屏的水平线(屏幕垂直中心) for (ui x = 0; x < screen_width; x++) { SetPixelV(hdcwin, x, center_y, RGB(0, 255, 0)); } // 在屏幕中心绘制红色标记点 SetPixelV(hdcwin, center_x, center_y, RGB(255, 0, 0)); GetCursorPos(&cours); printf("光标坐标: (%d ; %d)\n", cours.x, cours.y); printf("屏幕分辨率: (%d ; %d)\n", screen_width, screen_height); printf("屏幕中心坐标: (%d ; %d)\n", center_x, center_y); } ReleaseDC(NULL, hdcwin); return 0; } void GetSizeWindow(ui* x, ui* y){ *x = GetSystemMetrics(SM_CXSCREEN); *y = GetSystemMetrics(SM_CYSCREEN); } void GetCenterWindow(ui *x, ui *y){ GetSizeWindow(x, y); *x /= 2; *y /= 2; }
额外说明
如果涉及多显示器场景,SM_CXSCREEN/SM_CYSCREEN仅返回主显示器参数,若要获取多屏联合区域或特定显示器信息,可使用EnumDisplaySettings或GetMonitorInfo函数。
内容的提问来源于stack exchange,提问作者Penguin
相关产品推荐
相关产品推荐

