我在使用 GDI 和 GDI+ 进行绘图时遇到问题。其中页面变换,特别是缩放,在两者之间似乎有些微小差别。除了 SetViewportExt
和 SetWindowExt
,GDI 上下文中哪些属性会影响输出的缩放?
代码几乎全部使用 GDI 进行绘制,但在需要半透明效果时会使用 GDI+。代码中使用了 SetViewportExt
、SetWindowExt
和 SetViewportOrg
来实现缩放和滚动。
当需要使用 GDI+ 时,我会在 HDC 周围构建一个 Gdiplus::Graphics
对象并进行绘制。我认为这使得图形上下文包装设备上下文,并将其渲染到设备上下文中。如果我提取 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()));
}
结果如下所示:(蓝色虚线由GDI绘制,灰色由GDI+绘制)
我可以清楚地看到两个坐标系是不同的。我期望会有一些舍入误差,但没有像这里看到的比例误差。此外,当我改变缩放因子时,GDI+会在两个方向上跳动±4像素。这也在截图中突出显示,因为与GDI矩形相比,GDI+矩形在X轴上具有正偏移量,在Y轴上具有负偏移量。
有人知道这里发生了什么吗?
我该如何进行调查和调试?这发生在Windows的内部,所以我无法对其进行调试。
供参考,这是我的视口/窗口org/ext的样子:
Window Ext: (134000, 80500)
Window Org: (0, 0)
Viewport Ext: (1452 872)
Viewport Org: (35 35)
更新:
问题已经解决,但并不美观。基本方法如下:
在屏幕空间中采用两个坐标(原点和适当的第二个点),并使用 GDI(
DPtoLP
函数)将它们转换为逻辑坐标。将 GDI 转换重置为
MM_TEXT
。使用转换后的点构建一个 GDI+ 的变换矩阵,该矩阵表示相同的变换。
最后,使用此矩阵构造一个具有正确变换的 GDI+ 上下文。
这有点像 hack,但它确实有效。尽管我仍然不知道为什么两者之间存在差异。但至少可以说明,GDI+ 上下文能够模仿 GDI 转换。