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

如何正确绘制不受显示器分辨率影响的6英寸GDI+矩形

正确实现方法

要在不同DPI的显示器上精确绘制指定物理长度的图形,需遵循以下步骤:

1. 确认DPI感知模式正确性

你已设置PROCESS_PER_MONITOR_DPI_AWARE和DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2,这是当前推荐的高DPI感知方案——V2模式支持窗口跨显示器移动时的动态DPI调整,无需重启或重新布局。

2. 精确计算物理长度对应像素数

物理长度与像素数的核心关系为:像素数 = 物理长度(英寸) × 当前显示器DPI。直接用GetDpiForWindow(hwnd)获取窗口所在显示器的实时DPI即可。

3. 修正GDI+ Pen的绘制偏移

GDI+的Pen默认采用居中对齐(PenAlignmentCenter),当Pen宽度为1像素时,矩形边框会在路径两侧各延伸0.5像素,导致实际显示的矩形比设置尺寸宽1像素。修正偏移有两种可靠方式:

方式一:设置Pen为内部对齐

将Pen对齐方式改为PenAlignmentInset,让Pen宽度完全绘制在矩形路径内部,不会额外扩展尺寸:

Pen colP(Color(255, 255, 255));
colP.SetAlignment(PenAlignmentInset);

auto dpi = GetDpiForWindow(hwnd);
int targetWidth = lround(6.0f * dpi); // 6英寸 × DPI = 目标像素宽度

gr.DrawRectangle(&colP, 0, 0, targetWidth, 30);

方式二:调整矩形坐标与尺寸

若不想修改Pen对齐逻辑,可将矩形宽度减1,并将X坐标偏移0.5像素,抵消Pen居中绘制的偏移:

Pen colP(Color(255, 255, 255));

auto dpi = GetDpiForWindow(hwnd);
int targetWidth = lround(6.0f * dpi);

gr.DrawRectangle(&colP, 0.5f, 0, targetWidth - 1, 30);

4. 确保Graphics对象使用正确DPI

创建Gdiplus::Graphics时,建议直接从窗口句柄创建(Graphics gr(hwnd)),它会自动匹配窗口当前DPI;若必须从HDC创建,需手动设置Graphics的DPI:

HDC hdc = GetDC(hwnd);
Graphics gr(hdc);
auto dpi = GetDpiForWindow(hwnd);
gr.SetDpiX(dpi);
gr.SetDpiY(dpi);

临时方案生效的原因分析

你的临时方案2*dpi - USER_DEFAULT_SCREEN_DPI - 2能生效,本质是错误计算刚好抵消了两处偏差:

  1. Graphics对象DPI不匹配偏差:若你的Graphics默认使用系统标准DPI(96)而非窗口实时DPI,绘制时会按dpi/96比例自动缩放图形。2*dpi - 96的错误放大倍数,刚好抵消了这个缩放带来的尺寸偏差。
  2. Pen居中绘制的偏移:减去的数值2,刚好抵消了Pen居中对齐导致的左右各0.5像素扩展(总偏移1像素),再加上取整误差的修正,最终得到了接近精确的6英寸尺寸。

这种方案完全是误打误撞,没有理论支撑,在不同DPI设置、不同Pen宽度的场景下会失效,建议替换为上述标准实现方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 20:00:11