Metafiles - MS help please

G

Guest

Can someone at Microsoft please tell me if this is a bug with the metafile support in the framework or am I doing something wrong

I can't get Metafiles to appear in the correct size or position

Example
Assuming a Graphics object "G" with PageUnit set to mm, this C# code wil
draw a circle of radius 20mm, with an "X" on top

G.DrawEllipse(Pen, -20, -20, +40, +40)
G.DrawLine(Pen, -20, -20, +20, +20)
G.DrawLine(Pen, -20, +20, +20, -20)

I want to store this figure in a metafile to play later, so I create
metafile "M" (allowing a frame margin of 10mm)

DC := G.GetHdc()
R := new RectangleF(-30.0F, -30.0F, +60.0F, +60.0F)
M := new Metafile(DC, R, MetafileFrameUnit.Millimeter)
G.ReleaseHdc(DC)

then create a new Graphics object based on this metafile, set its PageUni
to mm, run the preceding 3 draw instructions on this new Graphics object
and discard then discard it

Graphics G2 = Graphics.FromImage(M)
G2.PageUnit = GraphicsUnit.Millimeter

<Execute the same 3 drawing instructions as before on G2

G2.Dispose()

Finally I try playing the metafile, usin

G.DrawImage(M, -30, -30)

This works fine when using UnitPixel everywhere, but with UnitMillimeter (o
UnitPoint) the image appears slightly the wrong size, and very much in th
wrong place. Looking into the metafile header, I find values for DPI an
LogicalDPI. Scaling X and Y by the ratio (DPI / LogicalDPI ) seems almost t
move the image to the correct location; but it is still very slightly out o
position, and still slightly the wrong size (readily seen by drawing bot
"direct" and metafile versions together)

What could explain the inconsistency of the two drawing methods

How can I more accurately "correct" the figure's size and position? (usin
pixels instead of mm is not an option

Craig Hynd
 
J

John Hornick [MSFT]

Hi Craig,

I'm not sure if you ever got a reply to this, so here goes:

The problem you describe below is due to the mixing and matching of various
GetDeviceCaps() calls. It is possible, even common, for video drivers to
report mathematically inconsistent values when queried for LOGPIXELSX/Y
versus HORZRES/VERTRES/HORZSIZE/VERTSIZE. Let's call the former "Approach
A" and the latter "Approach B". Each can be used to determine the DPI of
the screen, but the results obtained by using approach A frequently don't
match the results obtained by using approach B.

A is typically used to implement system font size, while B is used in
metafiles and in much of the rest of GDI. Unfortunately, if code which is
written using A must interact with code which uses B, inconsistencies occur.

That's what's happening below. GDI is using B, but the .NET Framework uses
A in some of its calculations. While neither approach is technically
"wrong", they don't always match up.

The solution is to avoid the disparate code paths. Hence using Pixels works
- no DPI calculation needs to be performed and you avoid the problem
completely. Alternatively, you could PInvoke to GetDeviceCaps(), determine
the amount by which the two calculations differ, and account for it in a
scaling and translation transform when drawing the figure.

Thanks,
- John
Microsoft Developer Support
This posting is provided "AS IS" with no warranties, and confers no rights.
Visit http://www.microsoft.com/security for current information on security.





Can someone at Microsoft please tell me if this is a bug with the
metafile support in the framework or am I doing something wrong?

I can't get Metafiles to appear in the correct size or position.

Example:
Assuming a Graphics object "G" with PageUnit set to mm, this C# code will
draw a circle of radius 20mm, with an "X" on top:

G.DrawEllipse(Pen, -20, -20, +40, +40);
G.DrawLine(Pen, -20, -20, +20, +20);
G.DrawLine(Pen, -20, +20, +20, -20);

I want to store this figure in a metafile to play later, so I create a
metafile "M" (allowing a frame margin of 10mm):

DC := G.GetHdc();
R := new RectangleF(-30.0F, -30.0F, +60.0F, +60.0F);
M := new Metafile(DC, R, MetafileFrameUnit.Millimeter);
G.ReleaseHdc(DC);

then create a new Graphics object based on this metafile, set its PageUnit
to mm, run the preceding 3 draw instructions on this new Graphics object,
and discard then discard it.

Graphics G2 = Graphics.FromImage(M);
G2.PageUnit = GraphicsUnit.Millimeter;

<Execute the same 3 drawing instructions as before on G2>

G2.Dispose();

Finally I try playing the metafile, using

G.DrawImage(M, -30, -30);

This works fine when using UnitPixel everywhere, but with UnitMillimeter (or
UnitPoint) the image appears slightly the wrong size, and very much in the
wrong place. Looking into the metafile header, I find values for DPI and
LogicalDPI. Scaling X and Y by the ratio (DPI / LogicalDPI ) seems almost to
move the image to the correct location; but it is still very slightly out of
position, and still slightly the wrong size (readily seen by drawing both
"direct" and metafile versions together).

What could explain the inconsistency of the two drawing methods?

How can I more accurately "correct" the figure's size and position? (using
pixels instead of mm is not an option)

Craig Hynd
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top