In memory Metafile

  • Thread starter Thread starter Marco Rego
  • Start date Start date
M

Marco Rego

Please, how do I create an in memory Metafile ? Which device context should I
associate it to ?
Thanks for any help.

______
Marco
 
Please, how do I create an in memory Metafile ? Which device context
should I
associate it to ?

Is this in the context of a Forms application? If so, you can call
CreateGraphics() on some Control instance (for example, your main form).
If not, or if you want specific control over the graphics properties of
the DC, you can create a Bitmap instance and use Graphics.FromImage() to
get a Graphics instance from that.

Once you've got a Graphics instance, you can use the GetHdc() method to
get a DC handle that you can then pass to one of the Metafile constructors
that takes one. In that way you can create a Metafile from scratch.

And of course, once you've got your Metafile instance, you can use
Graphics.FromImage() again to get a Graphics instance that you can use to
draw into the metafile.

For example (in a method in a Control instance):

Metafile mf = null;

using (Graphics gfx = this.CreateGraphics())
{
mf = new Metafile(gfx.GetHdc(), EmfType.EmfOnly);

using (Graphics gfxMetafile = Graphics.FromImage(mf))
{
gfxMetafile.DrawEllipse(Pens.Blue, new Rectangle(10,
10, 20, 10));
}
}

return mf;

Obviously where I call DrawEllipse(), you'd put whatever actual drawing
code you want.

Pete
 
Peter Duniho said:
Is this in the context of a Forms application? If so, you can call
CreateGraphics() on some Control instance (for example, your main form).
If not, or if you want specific control over the graphics properties of
the DC, you can create a Bitmap instance and use Graphics.FromImage() to
get a Graphics instance from that.

Once you've got a Graphics instance, you can use the GetHdc() method to
get a DC handle that you can then pass to one of the Metafile constructors
that takes one. In that way you can create a Metafile from scratch.

And of course, once you've got your Metafile instance, you can use
Graphics.FromImage() again to get a Graphics instance that you can use to
draw into the metafile.

For example (in a method in a Control instance):

Metafile mf = null;

using (Graphics gfx = this.CreateGraphics())
{
mf = new Metafile(gfx.GetHdc(), EmfType.EmfOnly);

using (Graphics gfxMetafile = Graphics.FromImage(mf))
{
gfxMetafile.DrawEllipse(Pens.Blue, new Rectangle(10,
10, 20, 10));
}
}

return mf;

Obviously where I call DrawEllipse(), you'd put whatever actual drawing
code you want.

Pete


Pete, thanx for your reply.
Well, it didn't work for me. I did:

Metafile pic = new Metafile(new Panel().CreateGraphics().GetHdc(),
EmfType.EmfOnly);

graph = Graphics.FromImage(pic);
... draw string, line, rectangle, etc ...

Now, when I try to print pic (setting the proper Size for it) and it doesn't
show on the page. Then I try to show pic in a picture box (using Size(800,
800) and PictureBoxSizeMode.StretchImage) it shows nothing again (just the
form).

What am I doing wrong ?

______
Marco
 
Pete, thanx for your reply.
Well, it didn't work for me. I did:

Metafile pic = new Metafile(new Panel().CreateGraphics().GetHdc(),
EmfType.EmfOnly);

graph = Graphics.FromImage(pic);
... draw string, line, rectangle, etc ...

Now, when I try to print pic (setting the proper Size for it) and it
doesn't
show on the page. Then I try to show pic in a picture box (using
Size(800,
800) and PictureBoxSizeMode.StretchImage) it shows nothing again (just
the
form).

What am I doing wrong ?

I don't know. The first question that comes to mind is: did you step
through the code and ensure that each statement is executing as expected?
Or put another way, are you positive that no exception is occurring in
that code?

The only thing of what you posted that looks odd is that you create a new
Panel instance just to get a Control from which you ultimately get the
HDC. Normally, the window handle for the control won't be created right
away, but if I recall correctly calling things that would require the
window handle will force it to be created. So even thought it's not very
orthodox, I don't see any obvious reason that wouldn't work. But it's
still odd, and different from what I did, so you might want to try an
alternative method of getting your reference DC.

If you don't have a Control instance already handy and ready to use, I
would instead get your Graphics instance from a Bitmap instance you
create. A single-pixel Bitmap with whatever other characteristics you
want (dpi, color depth, etc.) should be fine, I think.

If that's not the issue, then you should post a concise-but-complete
sample of code that reliably demonstrates the problem. In this case, I
would post a sample that simply tries to display the metafile on-screen
(e.g. in a PictureBox). Adding printing to the scenario just complicates
things unnecessary, given that you say that it also doesn't work just
trying to show it on the screen.

Note also that "concise-but-complete" means that there's no additional
code that anyone needs to write to get your code to execute. The default
Forms designer application will have at least three files, one containing
the Program class, and two others representing the custom and
designer-generated portions of your custom Form-derived class,
respectively.

Make your example as simple as possible, and post all of the code in the
example.

Also, this doesn't seem like the sort of thing that should be dependent on
the version of .NET you're using, but you might want to state that
information anyway, just in case. The code I posted was tested and works
on .NET 2.0 SP1, running on Windows XP SP2.

Pete
 
Peter Duniho said:
I don't know. The first question that comes to mind is: did you step
through the code and ensure that each statement is executing as expected?
Or put another way, are you positive that no exception is occurring in
that code?

The only thing of what you posted that looks odd is that you create a new
Panel instance just to get a Control from which you ultimately get the
HDC. Normally, the window handle for the control won't be created right
away, but if I recall correctly calling things that would require the
window handle will force it to be created. So even thought it's not very
orthodox, I don't see any obvious reason that wouldn't work. But it's
still odd, and different from what I did, so you might want to try an
alternative method of getting your reference DC.

If you don't have a Control instance already handy and ready to use, I
would instead get your Graphics instance from a Bitmap instance you
create. A single-pixel Bitmap with whatever other characteristics you
want (dpi, color depth, etc.) should be fine, I think.

If that's not the issue, then you should post a concise-but-complete
sample of code that reliably demonstrates the problem. In this case, I
would post a sample that simply tries to display the metafile on-screen
(e.g. in a PictureBox). Adding printing to the scenario just complicates
things unnecessary, given that you say that it also doesn't work just
trying to show it on the screen.

Note also that "concise-but-complete" means that there's no additional
code that anyone needs to write to get your code to execute. The default
Forms designer application will have at least three files, one containing
the Program class, and two others representing the custom and
designer-generated portions of your custom Form-derived class,
respectively.

Make your example as simple as possible, and post all of the code in the
example.

Also, this doesn't seem like the sort of thing that should be dependent on
the version of .NET you're using, but you might want to state that
information anyway, just in case. The code I posted was tested and works
on .NET 2.0 SP1, running on Windows XP SP2.

Pete



Some progress here ...
I could display the picture in a PictureBox. I just needed to redraw it when
showing on the form.
Now that I know that the picture is OK, my real need is to print it. I tried
several DrawImage variations but none of them worked.
I can draw on the Graphics object from the PrintPageEventArg with DrawLine,
DrawRectangle, etc., but the DrawImage is not working. Well, it works with a
Bitmap but not with the Metafile.

______
Marco
 
Some progress here ...
I could display the picture in a PictureBox. I just needed to redraw it
when
showing on the form.
Now that I know that the picture is OK, my real need is to print it. I
tried
several DrawImage variations but none of them worked.
I can draw on the Graphics object from the PrintPageEventArg with
DrawLine,
DrawRectangle, etc., but the DrawImage is not working. Well, it works
with a
Bitmap but not with the Metafile.

Okay, so you have solved your original question and can now create a valid
memory-based Metafile instance.

So now the question is different: how to get that Metafile to print. A
different question deserves a different thread. That way if someone else
is trying to do the same thing, they can more easily find the question you
asked. So please restate your question clearly in a new thread.

I will warn you that I'm probably not going to be as much help for the
printing question. Assuming you've been able to get other stuff to print,
you've done about as much .NET printing as I have. I don't have any
specialized experience with printing Metafiles per se. My best guess is
that you need to be explicit about the size of the Metafile as printed,
either by using a DrawImage() overload that takes a destination rectangle
or by setting the Metafile size directly. But if that's not the issue, I
don't have any other guesses at the moment.

As before, posting some actual code with your question will help others
understand better what you're doing now that isn't working and provide an
answer that fits in with that context. Assuming someone does have an
answer, of course (I haven't seen many printing-related questions come up
here, and even fewer get answered...it turns out most applications don't
print and so most people won't have the necessary experience to answer a
question about printing).

Pete
 
Back
Top