关于GDI/GDI +坐标兼容性?

Yng*_*and 17 c++ windows gdi+ gdi

我在使用GDI和GDI +交替绘图时遇到了问题.页面转换 - 特别是缩放 - 似乎在两者之间略微偏离.除了SetViewportExt和之外,GDI上下文的哪些属性会影响输出的缩放SetWindowExt

该代码几乎只使用GDI进行绘图,但在少数需要其特征(半透明)的情况下使用GDI +.它使用SetViewportExt,SetWindowExtSetViewportOrg启用缩放和滚动.

当需要GDI +时,我Gdiplus::Graphics在HDC周围构建一个对象并进行绘制.我假设这使图形上下文包装设备上下文并将其呈现中继到设备上下文.如果我提取GDI +图形上下文的变换矩阵,我看到它是单位矩阵,因此缩放是在别处完成的(在设备上下文中我猜).

我设计了一个简单的测试,我用GDI和GDI +绘制相同的矩形数组,以确保在两种情况下所有的变换都是相同的.代码段如下:

CRect rect = ...;

// Draw the rectangle using GDI
CPen cpen(PS_DASH, 0, RGB(0,0,255));
pDC->SelectObject(&cpen);
pDC->Rectangle(rect);

{
    // Draw the rectangle using GDI+
    Gdiplus::Graphics graphics(pDC->m_hDC);

    Gdiplus::Pen pen(Gdiplus::Color(180,180,180));
    graphics.DrawRectangle(
        &pen,
        Gdiplus::Rect(rect.left, rect.top, rect.Width(), rect.Height()));
}
Run Code Online (Sandbox Code Playgroud)

结果如下:(蓝色虚线由GDI绘制,灰色由GDI +绘制)

代码绘制的结果

我可以清楚地看到两个坐标系是不同的.我期待一些舍入错误,但不是这里看到的缩放错误.此外,当我更改缩放系数时,GDI +会根据变焦在两个方向上跳跃±4像素.这也在屏幕截图中突出显示,因为与GDI矩形相比,GDI +矩形在X轴上具有正偏移并且在Y轴上具有负偏移.

  • 有谁知道这里发生了什么?

  • 我该如何调查/调试这个?这发生在窗户的内部,所以我很遗憾无法调试它.

作为参考,这是我的视口/窗口org/ext的样子:

Window Ext: (134000, 80500)
Window Org: (0, 0)
Viewport Ext: (1452 872)
Viewport Org: (35 35)
Run Code Online (Sandbox Code Playgroud)

更新:

我已经解决了这个问题,但它并不漂亮.基本方法是:

  1. 在屏幕空间中取两个坐标(原点和第二个适当的点),并使用GDI(DPtoLP函数)将它们转换为逻辑坐标.

  2. 将GDI转换重置为MM_TEXT.

  3. 使用变换后的点构建GDI +的变换矩阵,表示相同的变换

  4. 最后使用此矩阵构造具有正确变换的GDI +上下文.

这有点像黑客,但它确实有效.我仍然不知道为什么两者之间存在差异.至少它表明可以有一个GDI +上下文模仿GDI转换.

mya*_*lim 5

简答:打电话 graphics.SetPageUnit(Gdiplus::UnitPixel)

我遇到了与/sf/answers/342647861/相同的问题:打印时,GDI +(Gdiplus :: Graphics)的坐标与GDI(HDC)的坐标不匹配.

graphics.GetPageUnit()回来了UnitDisplay.文档UnitDisplay是:

指定显示单位.例如,如果显示设备是监视器,则该单位是1个像素.

我错误地认为对于打印机,UnitDisplay会使用打印机点.经过多次努力,我终于发现它实际上使用了1/100英寸的原因.如果我使用Gdiplus :: UnitPixel,则GDI +坐标与GDI坐标相同.


rep*_*vsd -1

要记住的一件事是,大多数 GDI 通常在硬件上运行(即 GDI 功能映射到在硅上实现某些功能的显示驱动程序)GDI+ 应该获得硬件加速,但它仍然作为单独的软件渲染器。

尝试通过 GDI+ 和 GDI 手动设置一些像素,看看它们是否不同。

也许您的特定显卡转换坐标的方式与 GDI+ 中发生的方式有所不同