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
?
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.
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).
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()));
}
And the result is here: (the blue dashed is drawn by GDI and the gray is drawn by GDI+)
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?
How would I go about investigating/debugging this? This happens in the bowels of windows so I'm unfortunately unable to debug it.
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:
Take two coordinates (origin and a second appropriate point) in screen space and transform them to logical coordinates using GDI (
DPtoLP
function).Reset the GDI transformation to
MM_TEXT
.Use the transformed points to construct a transformation matrix for GDI+ which represent the same transformation
And finally use this matrix to construct a GDI+ context with the correct transformation.
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.