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

如何获取Windows系统DPI缩放后的精确光标位图?

获取屏幕实际显示的精确光标位图解决方案

要解决高DPI环境下获取系统光标精确位图的问题,核心是处理DPI感知并获取对应分辨率的光标资源,以下是具体实现步骤:

1. 启用应用的DPI感知

只有让应用支持Per-Monitor DPI感知,才能避免系统自动缩放,获取到真实的光标尺寸。

  • 通过应用清单配置(推荐):
    <application xmlns="urn:schemas-microsoft-com:asm.v3">
      <windowsSettings>
        <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
      </windowsSettings>
    </application>
    
  • 或在代码中动态设置(Windows 10 1703及以上版本):
    SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
    

2. 获取当前DPI下的光标真实尺寸

根据显示器DPI计算光标实际显示的尺寸:

// 获取系统DPI(或用GetDpiForWindow(hWnd)获取窗口所在显示器的DPI)
UINT dpi = GetDpiForSystem();
// 获取当前DPI对应的光标宽高
int cursorWidth = GetSystemMetricsForDpi(SM_CXCURSOR, dpi);
int cursorHeight = GetSystemMetricsForDpi(SM_CYCURSOR, dpi);

3. 绘制并获取精确的光标位图

创建带Alpha通道的32位DIB位图,在内存DC中绘制光标以保留透明效果和高分辨率:

// 初始化BITMAPINFO,创建32位带Alpha的DIB
BITMAPINFO bmi = {0};
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = cursorWidth;
bmi.bmiHeader.biHeight = -cursorHeight; // 采用顶部向下的图像存储格式
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;

void* pBitmapBits = nullptr;
HBITMAP hCursorBitmap = CreateDIBSection(nullptr, &bmi, DIB_RGB_COLORS, &pBitmapBits, nullptr, 0);

// 创建兼容内存DC并绑定DIB位图
HDC hMemDC = CreateCompatibleDC(nullptr);
HGDIOBJ hOldBitmap = SelectObject(hMemDC, hCursorBitmap);

// 获取当前光标句柄并绘制到内存DC
HCURSOR hCurrentCursor = GetCursor();
DrawIconEx(hMemDC, 0, 0, hCurrentCursor, cursorWidth, cursorHeight, 0, nullptr, DI_NORMAL | DI_COMPAT);

// 此时hCursorBitmap即为屏幕实际显示的精确光标位图,可用于后续像素操作

// 清理资源(使用完位图后再调用DeleteObject)
SelectObject(hMemDC, hOldBitmap);
DeleteDC(hMemDC);
// DeleteObject(hCursorBitmap);

4. 替代方案:获取高分辨率光标资源

如果需要直接获取光标对应的高分辨率位图,可先将光标转换为对应DPI的版本,再提取位图:

// 将原始光标转换为当前DPI对应的高分辨率版本
HCURSOR hHiResCursor = CopyImage(hCursor, IMAGE_CURSOR, cursorWidth, cursorHeight, LR_COPYFROMRESOURCE);

// 调用GetIconInfoExW获取高分辨率位图信息
ICONINFOEXW iconInfo = {0};
iconInfo.cbSize = sizeof(ICONINFOEXW);
GetIconInfoExW(hHiResCursor, &iconInfo);

// iconInfo.hbmColor即为高分辨率的彩色光标位图
// 使用完后清理资源
DeleteObject(iconInfo.hbmColor);
DeleteObject(iconInfo.hbmMask);
DestroyCursor(hHiResCursor);

关键注意事项

  • 必须启用DPI感知,否则系统会对应用的DC进行缩放,导致绘制的光标为低分辨率放大版本。
  • 采用32位带Alpha通道的DIB位图,才能正确保留光标的透明效果,避免绘制时出现透明像素失真。
  • DrawIconEx的DI_COMPAT标志确保高DPI环境下光标渲染符合系统缩放规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 23:17:10