关于GDI/GDI +坐标兼容性? [英] About GDI/GDI+ coordinate compatibility?
问题描述
在同时使用GDI和GDI +进行绘图时,我遇到了问题.页面转换-尤其是缩放-似乎在两者之间有些偏离.除了SetViewportExt
和SetWindowExt
之外,GDI上下文的哪些属性会影响输出的缩放?
I have a problem while drawing with both GDI and GDI+ interchangeably. The page transformation—in particular scaling—seems to be a little bit off between the two. Which properties of the GDI context affects the scaling of the output other than SetViewportExt
and SetWindowExt
?
该代码几乎完全将GDI用于其绘图,但在少数需要其功能(半透明)的情况下使用GDI +.它使用SetViewportExt
,SetWindowExt
和SetViewportOrg
启用缩放和滚动.
The code uses almost exclusively GDI for its drawing, but uses GDI+ in a few cases where its features (semitransparency) are needed. It uses SetViewportExt
, SetWindowExt
and SetViewportOrg
to enable zooming and scrolling.
当需要GDI +时,我围绕HDC构造一个Gdiplus::Graphics
对象并进行绘制.我认为这会使图形上下文包装设备上下文并将其渲染中继到设备上下文.如果我提取GDI +图形上下文的转换矩阵,就会发现它是单位矩阵,因此缩放是在其他位置(我想是在设备上下文中)完成的.
When GDI+ is needed I construct a Gdiplus::Graphics
object around the HDC and do the drawing. I assume this makes the graphics context wrap the device context and relay its rendering to the device context. If I extract the transformation matrix of the GDI+ graphics context, I see that it is the identity matrix, so the scaling is done elsewhere (in the device context I guess).
我设计了一个简单的测试,使用GDI和GDI +绘制相同的矩形数组,以确保在两种情况下所有转换都是相同的.该代码段如下:
I devised a simple test where I draw the same array of rectangles with GDI and GDI+ to be sure that all the transformations are the same in both cases. The code snippet follows:
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 +绘制)
And the result is here: (the blue dashed is drawn by GDI and the gray is drawn by GDI+)
我可以清楚地看到两个坐标系是不同的.我预计会有一些舍入错误,但不会出现如此处所示的缩放错误.另外,当我更改缩放系数时,取决于缩放比例,GDI +在两个方向上都围绕±4像素跳动.屏幕快照中还突出显示了这一点,因为与GDI矩形相比,GDI +矩形在X轴上具有正偏移,在Y轴上具有负偏移.
I can clearly see that the two coordinate systems are different. I expected some round-off errors, but not a scaling error as seen here. Also, when I change the zoom factor, the GDI+ jumps around ±4 pixel in both directions depending on the zoom. This is also highlighted in the screenshot as the GDI+ rectangle has a positive offset on the X axis and a negative offset on the Y axis as compared to the GDI rectangle.
-
有人知道这是怎么回事吗?
Does anybody know what's going on here?
我将如何进行调查/调试?这种情况发生在Windows的肠道中,因此很遗憾,我无法对其进行调试.
How would I go about investigating/debugging this? This happens in the bowels of windows so I'm unfortunately unable to debug it.
作为参考,这是我的视口/窗口org/ext的外观:
For reference, this is what my viewport/window org/ext looks like:
Window Ext: (134000, 80500)
Window Org: (0, 0)
Viewport Ext: (1452 872)
Viewport Org: (35 35)
更新:
我已经解决了问题,但这不是很漂亮.基本方法是:
Update:
I have fixed the problem, but it's not pretty. The basic approach is:
-
在屏幕空间中获取两个坐标(原点和第二个适当的点),并使用GDI(
DPtoLP
函数)将其转换为逻辑坐标.
Take two coordinates (origin and a second appropriate point) in screen space and transform them to logical coordinates using GDI (
DPtoLP
function).
将GDI转换重置为MM_TEXT
.
使用变换后的点为GDI +构造一个表示相同变换的变换矩阵
Use the transformed points to construct a transformation matrix for GDI+ which represent the same transformation
最后使用此矩阵构造具有正确转换的GDI +上下文.
And finally use this matrix to construct a GDI+ context with the correct transformation.
这有点hack,但是可以用.不过,我仍然不知道为什么两者之间会有区别.至少它表明,有可能在GDI +上下文中模仿GDI转换.
This is a bit of a hack, but it works. I still don't know why there is a difference between the two, though. At least it goes to show that it is possible to have a GDI+ context mimic the GDI transformation.
推荐答案
简短答案:呼叫graphics.SetPageUnit(Gdiplus::UnitPixel)
我的问题与 https://stackoverflow.com/a/4894969/700027 相同:在打印时, GDI +(Gdiplus :: Graphics)的坐标与GDI(HDC)的坐标不匹配.
I had the same problem as https://stackoverflow.com/a/4894969/700027: when printing, the coordinates for GDI+ (Gdiplus::Graphics) did not match the coordinates from GDI (HDC).
graphics.GetPageUnit()
返回UnitDisplay
. UnitDisplay
的文档是:
指定显示单位.例如,如果显示设备是监视器,则单位是1像素.
Specifies display units. For example, if the display device is a monitor, then the unit is 1 pixel.
我错误地认为对于打印机,UnitDisplay
将使用打印机点.经过艰苦的努力,我终于发现它实际上是出于未知原因使用了1/100英寸.如果我使用Gdiplus :: UnitPixel,则GDI +坐标与GDI坐标相同.
I had wrongly assumed that for a printer, UnitDisplay
would use printer dots. After much struggle I finally found out that it was actually using 1/100 of inches for an unknown reason. If I use Gdiplus::UnitPixel then GDI+ coordinates are the same as GDI coordinates.
这篇关于关于GDI/GDI +坐标兼容性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!