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

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(&center_x, &center_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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 11:01:32