473,883 Members | 2,177 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

.NET, Clipboard, and metafiles

I'm trying to use .NET and C# to draw a metafile copied to the clipboard by
another application (Word 2003 in this case, but it shouldn't matter).

I naively thought that I'd be able to use the Clipboard class to get an
EnhancedMetafil e or MetafilePict object from the Clipboard, use that to
create a new Metafile object, and then draw that Metafile object using
Graphics.DrawIm age.

It doesn't seem to be that simple.

When I try to get the EnhancedMetafil e object from the Clipboard, .NET
crashes. When I have the debugger running, the MDA tells me I've got a
FatalExecutionE ngineError and that it's due either to improper use of unsafe
code or a bug in .NET. Since I'm not using any unsafe code, that leaves a
bug in .NET.

??? How could something this simple crash .NET?

Anyway, so I tried using the MetafilePict format instead. This doesn't
crash .NET, but the object that's returned is a MemoryStream. In and of
itself, that seems reasonable. You can construct a new Metafile object
using a MemoryStream. However, the MemoryStream returned is only 16 bytes
long, much too short to be the metafile I'm trying to get. Of course, I get
a whole new exception trying to use this MemoryStream object to construct a
Metafile, but even if I didn't, I'm sure it wouldn't be the data I want.

The code I'm trying to use is pretty straightforward :

mfstream = (Stream)Clipboa rd.GetData(Data Formats.Metafil ePict);
metafile = new Metafile(mfstre am);

(or DataForms.Enhan cedMetafile for the case that just crashes within the
..NET code)

I mean, I've written other code to do things like check the clipboard
formats and whatnot, but the problematic code boils down to those two lines.
(And yes, when I check the formats in the clipboard, both "Enhanced
Metafile" and "MetaFile Pict" are in there).

I Googled the issue a bit, and found two categories of messages: people who
also can't figure out how to do this, and suggestions to use inter-op. I
actually was able to inter-op to sort of accomplish it, but I wound up
having to basically use *no* .NET stuff...I just p/invoked the basic
clipboard and metafile functions required to draw a metafile to a DC,
passing the DC provided by the e.Graphics object for the OnPaint handler
(which is where, for the moment, I'm trying to get this to work...though
once I can draw the metafile succesfully on the screen, I have other plans
for it :) ).

If I wanted to do it that way, I'd just write a native Win32 program. I
suppose I may wind up doing that after all, but I was hoping to do this in
..NET. I've gotten spoiled not having to do any real work to build a UI. :)

Using inter-op in the way the online messages suggested did not work. In
particular, they recommend using the regular Win32 clipboard functions to
get the handle to the metafile, and then construct a new Metafile object
using that handle. When I try that, I get the same general "GDI+ error"
exception that I get just using .NET stuff (though perhaps for different
reasons...the exception is too generic to know for sure).

Given the degree of interest that there appears in doing this, and the lack
of useful information about *how* to do it, I'm not hopeful. But I figure I
gotta try...

Anyone reading this ever successfully use .NET to get a metafile (enhanced
or otherwise) from the clipboard and draw it to your form (or do anything
else with it)? If so, how do you do it? What am I doing wrong?

Thanks!
Pete
Dec 4 '06 #1
15 12319
"Peter Duniho" <Np*********@Nn OwSlPiAnMk.comw rote:
>I'm trying to use .NET and C# to draw a metafile copied to the clipboard by
another application (Word 2003 in this case, but it shouldn't matter).

Using inter-op in the way the online messages suggested did not work. In
particular, they recommend using the regular Win32 clipboard functions to
get the handle to the metafile, and then construct a new Metafile object
using that handle. When I try that, I get the same general "GDI+ error"
exception that I get just using .NET stuff (though perhaps for different
reasons...th e exception is too generic to know for sure).
I'm able to use interop to get a handle to the metafile, and then
construct a new Metafile object using that handle, without any
exceptions. Here's my code. It demonstrates interop to (1) copy an EMF
onto the clipboard, (2) paste an EMF from the clipboard onto a Bitmap.

I really don't know what's up with the .net clipboard/metafile stuff.
I wasn't able to do ANYTHING useful with it. I couldn't find out how
to copy a metafile onto the clipboard with .net except through using
an intermediate diskfile. And I couldn't find out how to paste a
metafile from the clipboard, i.e. the same problems you were having.
And in a console program I couldn't do ANY clipboard manipulation at
all. The Clipboard.GetDa taObject method simply returned null. My
suspicion is that metafiles are a little irksome, and didn't fit
cleanly into the .net class hierarchies they were building, so they
just didn't implement them. That's just a suspicion.
using System;
using System.Collecti ons.Generic;
using System.Text;
using System.Runtime. InteropServices ;
using System.Drawing; // add reference to System.Drawing
using System.Windows. Forms; // add reference to System.Windows. Forms
using System.Drawing. Imaging;

class Program
{

internal struct RECT {public int left; public int top; public int
right; public int bottom;}
[DllImport("gdi3 2.dll")] internal static extern IntPtr
CreateEnhMetaFi le(IntPtr hdcRef, IntPtr zero, ref RECT rc, IntPtr
zero2);
[DllImport("gdi3 2.dll")] internal static extern IntPtr
CloseEnhMetaFil e(IntPtr hdc);
[DllImport("user 32.dll")] [return: MarshalAs(Unman agedType.Bool)]
internal static extern bool OpenClipboard(I ntPtr hwnd);
[DllImport("user 32.dll")] [return: MarshalAs(Unman agedType.Bool)]
internal static extern bool EmptyClipboard( );
[DllImport("user 32.dll")] internal static extern IntPtr
SetClipboardDat a(uint format, IntPtr h);
[DllImport("user 32.dll")] internal static extern IntPtr
GetClipboardDat a(uint format);
[DllImport("user 32.dll")] [return: MarshalAs(Unman agedType.Bool)]
internal static extern bool CloseClipboard( );
[DllImport("user 32.dll")] internal static extern IntPtr GetDC(IntPtr
hwnd);
[DllImport("user 32.dll")] internal static extern Int32
ReleaseDC(IntPt r hwnd,IntPtr hdc);
[DllImport("gdi3 2.dll")] internal static extern bool
DeleteObject(In tPtr hObject);
[DllImport("gdi3 2.dll")] internal static extern IntPtr
CreateCompatibl eDC(IntPtr hdc);
[DllImport("gdi3 2.dll")] internal static extern int DeleteDC(IntPtr
hdc);
[DllImport("gdi3 2.dll")] internal static extern IntPtr
SelectObject(In tPtr hdc, IntPtr hgdiobj);
[DllImport("gdi3 2.dll")] internal static extern int BitBlt(IntPtr
hdcDst, int xDst, int yDst, int w, int h, IntPtr hdcSrc, int xSrc, int
ySrc, int rop);
static int SRCCOPY = 0x00CC0020;
static uint CF_ENHMETAFILE = 14;

public delegate void DrawCallback(Gr aphics g);
/// <summary>
/// Draws onto an EMF that we store on the clipboard
/// </summary>
/// <param name="hwnd">Han dle of a window that will own the clipboard
(use IntPtr.Zero for null)</param>
/// <param name="width">wi dth in logical units of the drawing</param>
/// <param name="height">h eight in logical units of the
drawing</param>
/// <param name="dpmm">how many logical units per millimeter</param>
/// <param name="callback" >user-supplied callback that does the actual
drawing</param>
static void CopyToClipboard (IntPtr hwnd, int width, int height, float
dpmm, DrawCallback callback)
{ // width,height are the size that our DrawCallback will draw (in
logical units)
// dpmm is the number of logical units per millimeter
float widthmm = (float)width/dpmm;
float heightmm = (float)height/dpmm;
IntPtr hdc = GetDC(hwnd);
RECT rc = new RECT(); rc.top=0; rc.left=0;
rc.right=(int)( widthmm*100.0); rc.bottom=(int) (heightmm*100.0 ); //
(it's in units of 0.01mm)
IntPtr mdc = CreateEnhMetaFi le(hdc,IntPtr.Z ero,ref rc,IntPtr.Zero) ;
Graphics mg = Graphics.FromHd c(mdc);
mg.PageUnit = GraphicsUnit.Mi llimeter; mg.PageScale = 1.0F/dpmm;
callback(mg);
mg.Dispose();
IntPtr hemf = CloseEnhMetaFil e(mdc);
ReleaseDC(hwnd, hdc);
//
OpenClipboard(h wnd);
EmptyClipboard( );
SetClipboardDat a(CF_ENHMETAFIL E,hemf);
CloseClipboard( );
}

/// <summary>
/// Draws a bitmap "b" onto the screen at coordinates (x,y)
/// </summary>
static void SplashImage(Sys tem.Drawing.Bit map b, int x, int y)
{ IntPtr hbm = b.GetHbitmap();
IntPtr sdc = GetDC(IntPtr.Ze ro);
IntPtr hdc = CreateCompatibl eDC(sdc);
SelectObject(hd c,hbm);
BitBlt(sdc,x,y, b.Width,b.Heigh t,hdc,0,0,SRCCO PY);
DeleteDC(hdc);
ReleaseDC(IntPt r.Zero,sdc);
DeleteObject(hb m);
}
static void DrawRandomLines (Graphics g)
{ Random r = new Random();
Pen p = new Pen(Color.Red);
for (int i=0; i<10; i++)
{ g.DrawLine(p,r. Next(1000), r.Next(1000), r.Next(1000),
r.Next(1000));
}
p = new Pen(Color.Blue) ;
g.DrawLine(p,0, 0,1000,1000);
g.DrawLine(p,10 00,0,0,1000);
}

static void Main(string[] args)
{
// First we'll try to paste an EMF from the clipboard onto a bitmap,
and splash it onscreen
OpenClipboard(I ntPtr.Zero);
IntPtr hemf = GetClipboardDat a(CF_ENHMETAFIL E);
CloseClipboard( );
if (hemf!=IntPtr.Z ero)
{ Metafile mf = new Metafile(hemf,t rue); // true means that we don't
need to release the hemf ourselves
Bitmap b = new Bitmap(1000,100 0);
Graphics g = Graphics.FromIm age(b);
g.FillRectangle (Brushes.White, 0,0,1000,1000);
GraphicsUnit unit = GraphicsUnit.Mi llimeter; RectangleF rsrc =
mf.GetBounds(re f unit);
g.DrawImage(mf, new Rectangle(0,0,1 000,1000), rsrc, unit);
SplashImage(b,0 ,0);
System.Threadin g.Thread.Sleep( 1000);
}

// Now we'll copy an EMF onto the clipboard
CopyToClipboard (IntPtr.Zero,10 00,1000,10,Draw RandomLines);
}

}
--
Lucian
Dec 4 '06 #2
Peter,

I remember this problem back in the v1.1 days but I thought it was fixed
in v2.0. In v1.1, I wrote a ClipboardEx class with a static GetEMF()
function to do the grunt work. I didn't paste in all of the constants
and such but you should get the gist of what I'm doing. Anyway, I've
used this code with much success.

Jason Newell
www.jasonnewell.net

public abstract class ClipboardEx
{
public static System.Drawing. Imaging.Metafil e GetEMF(IntPtr hWnd)
{
try
{
/* Attempt to open the Clipboard. */
//if (OpenClipboard( GetClipboardOwn er()))
if (User32.OpenCli pboard(hWnd))
{
/* Check the Clipboard data format. */
if
(User32.IsClipb oardFormatAvail able((uint)Clip boardFormats.CF _ENHMETAFILE))
{
/* Get the pointer to the data. */
IntPtr ptr =
User32.GetClipb oardData((uint) ClipboardFormat s.CF_ENHMETAFIL E);
if (!ptr.Equals(In tPtr.Zero))
{
/* Return the Metafile. */

return new Metafile(ptr, true);
}
else
{
throw new System.Exceptio n("Error extracting
CF_ENHMETAFILE from clipboard.");
}
}
else
{
throw new System.Exceptio n("CF_ENHMETAFI LE is not
available in clipboard.");
}
}
else
{
throw new System.Exceptio n("Error opening clipboard.");
}
}
catch (System.Excepti on e)
{
throw e;
}
finally
{
/* Important to close the Clipboard. */
User32.CloseCli pboard();
}
}
}

Peter Duniho wrote:
I'm trying to use .NET and C# to draw a metafile copied to the clipboard by
another application (Word 2003 in this case, but it shouldn't matter).

I naively thought that I'd be able to use the Clipboard class to get an
EnhancedMetafil e or MetafilePict object from the Clipboard, use that to
create a new Metafile object, and then draw that Metafile object using
Graphics.DrawIm age.

It doesn't seem to be that simple.

When I try to get the EnhancedMetafil e object from the Clipboard, .NET
crashes. When I have the debugger running, the MDA tells me I've got a
FatalExecutionE ngineError and that it's due either to improper use of unsafe
code or a bug in .NET. Since I'm not using any unsafe code, that leaves a
bug in .NET.

??? How could something this simple crash .NET?

Anyway, so I tried using the MetafilePict format instead. This doesn't
crash .NET, but the object that's returned is a MemoryStream. In and of
itself, that seems reasonable. You can construct a new Metafile object
using a MemoryStream. However, the MemoryStream returned is only 16 bytes
long, much too short to be the metafile I'm trying to get. Of course, I get
a whole new exception trying to use this MemoryStream object to construct a
Metafile, but even if I didn't, I'm sure it wouldn't be the data I want.

The code I'm trying to use is pretty straightforward :

mfstream = (Stream)Clipboa rd.GetData(Data Formats.Metafil ePict);
metafile = new Metafile(mfstre am);

(or DataForms.Enhan cedMetafile for the case that just crashes within the
.NET code)

I mean, I've written other code to do things like check the clipboard
formats and whatnot, but the problematic code boils down to those two lines.
(And yes, when I check the formats in the clipboard, both "Enhanced
Metafile" and "MetaFile Pict" are in there).

I Googled the issue a bit, and found two categories of messages: people who
also can't figure out how to do this, and suggestions to use inter-op. I
actually was able to inter-op to sort of accomplish it, but I wound up
having to basically use *no* .NET stuff...I just p/invoked the basic
clipboard and metafile functions required to draw a metafile to a DC,
passing the DC provided by the e.Graphics object for the OnPaint handler
(which is where, for the moment, I'm trying to get this to work...though
once I can draw the metafile succesfully on the screen, I have other plans
for it :) ).

If I wanted to do it that way, I'd just write a native Win32 program. I
suppose I may wind up doing that after all, but I was hoping to do this in
.NET. I've gotten spoiled not having to do any real work to build a UI. :)

Using inter-op in the way the online messages suggested did not work. In
particular, they recommend using the regular Win32 clipboard functions to
get the handle to the metafile, and then construct a new Metafile object
using that handle. When I try that, I get the same general "GDI+ error"
exception that I get just using .NET stuff (though perhaps for different
reasons...the exception is too generic to know for sure).

Given the degree of interest that there appears in doing this, and the lack
of useful information about *how* to do it, I'm not hopeful. But I figure I
gotta try...

Anyone reading this ever successfully use .NET to get a metafile (enhanced
or otherwise) from the clipboard and draw it to your form (or do anything
else with it)? If so, how do you do it? What am I doing wrong?

Thanks!
Pete

Dec 4 '06 #3
"Lucian Wischik" <lu***@wischik. comwrote in message
news:ak******** *************** *********@4ax.c om...
I'm able to use interop to get a handle to the metafile, and then
construct a new Metafile object using that handle, without any
exceptions. Here's my code. It demonstrates interop to (1) copy an EMF
onto the clipboard, (2) paste an EMF from the clipboard onto a Bitmap.
Thanks!

Are you successful in getting that code to use a metafile put on the
clipboard by some other process? I notice that in your example code, you
are creating the metafile as well as consuming it. Granted, you are
creating it using the native Win32 API, but I wonder if a) the code works
only with a certain metafile, or if b) the fact that you're drawing the
metafile using .NET makes a difference (even though the metafile itself was
initialized using the native Win32 function).

The reason I ask is that the code to retrieve the metafile is basically
identical to the code I tried, but my code fails on the call to the Metafile
construction (with the general GDI+ error). The only difference is the
source of the metafile.
And in a console program I couldn't do ANY clipboard manipulation at
all. The Clipboard.GetDa taObject method simply returned null.
Well, the native API requires a window handle, AFAIK. If you pass NULL to
open the clipboard, Windows defaults to your process's main window, but a
window it still used. Since a console program doesn't have a window, it
doesn't surprise me that clipboard operations might fail.
My
suspicion is that metafiles are a little irksome, and didn't fit
cleanly into the .net class hierarchies they were building, so they
just didn't implement them. That's just a suspicion.
Well, I suppose that's possible. But why expose a Metafile class at all in
that case? On the surface, the Metafile class *appears* to simply be a
wrapper on top of the regular Windows metafile stuff. It seems to fit in
pretty well with the .NET hiearchy, sharing equal status with the Bitmap as
an object derived from Image. With GDI+, there are new metafile records to
handle, but GDI+ is accessible outside of .NET so this is more a GDI+ thing
than a .NET thing. The actual object hierarchy seems easy enough.

In addition, metafiles are a core component of basic Windows inter-process
operations, especially via the clipboard. Most programs don't understand
other programs' data formats, but metafiles are a standard format that
allows one program to easily imbed their output into another program. I'd
think it ought to be a high priority for .NET (even if it appears that it's
not).

I guess absent input from someone else who has gotten this to work using
just .NET, I'll have to agree that Microsoft punted on dealing with
metafiles in .NET. But I'm still at a loss to explain why. It doesn't seem
like it should be that hard, and even if it is hard, it's also important.
By the way, one thing that also makes me nervous about the code like you
posted (and that I've seen elsewhere) is that the handle from the clipboard
is automatically disposed by the Metafile object when you pass "true" for
the constructor's second parameter. This is bad, because the handle
obtained from the GetClipboardDat a function is owned by the clipboard, not
by the application. If it's freed, then the clipboard itself winds up an
invalid handle in it.

I tried the code with both "true" and "false" for that parameter, and the
value did not affect my success in constructing a new Metafile object.
However, IMHO the correct value for that parameter is "false".

Actually, if you want to get picky about it, I'd say the correct value is
actually "true" *and* the metafile from the clipboard ought to be copied
immediately after getting it from the clipboard, and before closing the
clipboard and constructing the .NET Metafile. Either that, or don't close
the clipboard until after the drawing is done, to ensure that no other
process invalidates the metafile handle. My guess is that "false" is "good
enough" just to see about getting things to work though.

Anyway, thanks for your input...it's nice to know that someone has gotten
*some* semblance of clipboard operations to work under .NET, even if .NET
itself doesn't appear to support it. Inter-op is a pain, but doing a full
GUI without .NET forms is even more of a pain IMHO. I guess that's the
lesser of two evils. :)

Pete
Dec 4 '06 #4
"Jason Newell" <no@spam.comwro te in message
news:e0******** *****@TK2MSFTNG P04.phx.gbl...
I remember this problem back in the v1.1 days but I thought it was fixed
in v2.0. In v1.1, I wrote a ClipboardEx class with a static GetEMF()
function to do the grunt work. I didn't paste in all of the constants and
such but you should get the gist of what I'm doing. Anyway, I've used
this code with much success.
Thanks for the reply. Unfortunately, I've already basically tried that. As
I mentioned in the reply to Lucian that I just posted, it doesn't work for
me. Does your code to work with metafiles put on the clipboard by other
applications?

Also, as with all the other examples, I note that you pass "true" for the
"delete on dispose" parameter to the Metafile constructor. As I described
in that same reply, I suspect that's dangerous to do. Though, I can't
explain why if it's so dangerous, it shows up in every example (I've seen
bugs perpetuated like that in other FAQ-like code posted, for .NET and other
environments).

Pete
Dec 4 '06 #5
Peter,

Sorry it's not working for you. Yes, I was using a 3rd party CAD
ActiveX control to put the Metafile on the clipboard. Something like:

ActiveX.CopyEMF ToClipboard();
ClipboardEx().G etEMF();

I guess I never put that much thought into the passing "true" into the
constructor. It worked and I was happy ;-).

You say that you're using Word to copy the Metafile to the clipboard.
I'll whip up a test program to see if I can reproduce the problem and
let you know.

Jason Newell
www.jasonnewell.net

Peter Duniho wrote:
"Jason Newell" <no@spam.comwro te in message
news:e0******** *****@TK2MSFTNG P04.phx.gbl...
>I remember this problem back in the v1.1 days but I thought it was fixed
in v2.0. In v1.1, I wrote a ClipboardEx class with a static GetEMF()
function to do the grunt work. I didn't paste in all of the constants and
such but you should get the gist of what I'm doing. Anyway, I've used
this code with much success.

Thanks for the reply. Unfortunately, I've already basically tried that. As
I mentioned in the reply to Lucian that I just posted, it doesn't work for
me. Does your code to work with metafiles put on the clipboard by other
applications?

Also, as with all the other examples, I note that you pass "true" for the
"delete on dispose" parameter to the Metafile constructor. As I described
in that same reply, I suspect that's dangerous to do. Though, I can't
explain why if it's so dangerous, it shows up in every example (I've seen
bugs perpetuated like that in other FAQ-like code posted, for .NET and other
environments).

Pete

Dec 4 '06 #6
Peter,

I wrote a small console application. I did a "Print Screen", pasted
into Microsoft Word 2003, right clicked on the image and selected
"Copy", then ran the console application. It worked fine on my machine.

Metafile metafile = ClipboardEx.Get EMF(User32.GetD esktopWindow()) ;
metafile.Save(@ "C:\desktop.emf ");

If you'd like, I can upload the source to my website and make it
available for download if you want to try it.

Jason Newell
www.jasonnewell.net

Jason Newell wrote:
Peter,

Sorry it's not working for you. Yes, I was using a 3rd party CAD
ActiveX control to put the Metafile on the clipboard. Something like:

ActiveX.CopyEMF ToClipboard();
ClipboardEx().G etEMF();

I guess I never put that much thought into the passing "true" into the
constructor. It worked and I was happy ;-).

You say that you're using Word to copy the Metafile to the clipboard.
I'll whip up a test program to see if I can reproduce the problem and
let you know.

Jason Newell
www.jasonnewell.net

Peter Duniho wrote:
>"Jason Newell" <no@spam.comwro te in message
news:e0******* ******@TK2MSFTN GP04.phx.gbl...
>>I remember this problem back in the v1.1 days but I thought it was
fixed in v2.0. In v1.1, I wrote a ClipboardEx class with a static
GetEMF() function to do the grunt work. I didn't paste in all of the
constants and such but you should get the gist of what I'm doing.
Anyway, I've used this code with much success.

Thanks for the reply. Unfortunately, I've already basically tried
that. As I mentioned in the reply to Lucian that I just posted, it
doesn't work for me. Does your code to work with metafiles put on the
clipboard by other applications?

Also, as with all the other examples, I note that you pass "true" for
the "delete on dispose" parameter to the Metafile constructor. As I
described in that same reply, I suspect that's dangerous to do.
Though, I can't explain why if it's so dangerous, it shows up in every
example (I've seen bugs perpetuated like that in other FAQ-like code
posted, for .NET and other environments).

Pete
Dec 4 '06 #7
"Jason Newell" <no@spam.comwro te in message
news:%2******** **********@TK2M SFTNGP02.phx.gb l...
[...]
If you'd like, I can upload the source to my website and make it available
for download if you want to try it.
That would be wonderful. Maybe I did something wrong with the inter-op
declarations that's causing problems. Having actual working code in front
of me would surely go a long way in helping understand what I'm doing wrong.

Thanks!
Pete
Dec 4 '06 #8
"Peter Duniho" <Np*********@Nn OwSlPiAnMk.comw rote:
>Are you successful in getting that code to use a metafile put on the
clipboard by some other process?
Yes, I developed my code using Word+Wordpad+Po werpoint as the source
of my pasting operation, and target of my copying operation. (I only
combined the two together once it was finished in preparation for
posting here).

>the fact that you're drawing the
metafile using .NET makes a difference (even though the metafile itself was
initialized using the native Win32 function).
No it definitely doesn't.

>Well, the native API requires a window handle, AFAIK. If you pass NULL to
open the clipboard, Windows defaults to your process's main window, but a
window it still used. Since a console program doesn't have a window, it
doesn't surprise me that clipboard operations might fail.
Passing NULL to OpenClipboard works for a *console* program when I use
the win32 api. (the code I pasted was a console program). But yes,
reading the win32 docs, this does seem dodgy. It suggests that by
passing NULL, some subsequent call to EmptyClipboard will fail.

>My
suspicion is that metafiles are a little irksome, and didn't fit
cleanly into the .net class hierarchies they were building, so they
just didn't implement them. That's just a suspicion.
Well, I suppose that's possible. But why expose a Metafile class at all in
that case?
Reading through the docs, almost all of the metafile constructors were
for loading metafiles from somewhere else (be it stream or diskfile).
At least with a bitmap, you can create the bitmap and draw on it and
at every stage in the process it is a valid bitmap. The same isn't
true for win32 metafiles: you create them, and draw on them, but you
never actually receive the metafile handle until after you've "closed"
the drawing process.

That's what I mean to say that metafiles don't fit naturally into the
framework. They're not really like bitmaps or other images. And other
members of the Image class don't really work, like "RotateFlip " or
"IsAlphaPixelFo rmat" or "FromHBitma p". I even wonder if
"Metafile.Clone " is implemented?

Now reading metafiles from disk or stream seems to work fine in the
..net framework. I think that's why they exposed the Metafile class,
even though (as per above) they skimped on creating of metafiles.

The final questions: how to read a metafile off the clipboard, and how
to do it in the .net framework? What on earth is that 16-byte stream
that you get out of GetData(Metafil e)? (it seems to have the same
format each time: the number 8, two words, and one dword). And why
does GetData(EnhMeta File) not work? completely bizarre, all this.
>By the way, one thing that also makes me nervous about the code like you
posted (and that I've seen elsewhere) is that the handle from the clipboard
is automatically disposed by the Metafile object when you pass "true" for
the constructor's second parameter. This is bad, because the handle
obtained from the GetClipboardDat a function is owned by the clipboard, not
by the application. If it's freed, then the clipboard itself winds up an
invalid handle in it.
Actually, if you want to get picky about it, I'd say the correct value is
actually "true" *and* the metafile from the clipboard ought to be copied
immediately after getting it from the clipboard, and before closing the
clipboard and constructing the .NET Metafile.
Good point. I agree.
Dec 4 '06 #9
"Peter Duniho" <Np*********@Nn OwSlPiAnMk.comw rote:
>The reason I ask is that the code to retrieve the metafile is basically
identical to the code I tried, but my code fails on the call to the Metafile
construction (with the general GDI+ error). The only difference is the
source of the metafile.
(1) Create a c# console app, past my code exactly as it appears, and
see if you still get the same failure.

(2) tell us what the source of your metafile is so we can try to
reproduce it.

--
Lucian
Dec 4 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
11481
by: LG | last post by:
Just have a question with regards to the clipboard, and how to read what other applications (Adobe InDesignCS) place in the clipboard. I am currently in the process of creating a booklet from a database, and I need the data to be laid out in a tabular format, and set out in a specific way. At the current point in time, I am copy/pasting the raw text from the database into a table layout in InDesign. What I was thinking is that if I could...
2
8022
by: George Yefchak | last post by:
Hi I need to retrieve a metafile image from the clipboard and render it as a bitmap in my application. In particular, an image will be placed on the clipboard by pasting from PowerPoint (I really do need to do this!). The original image is a bitmap, but PowerPoint doesn't place it on the clipboard as such. A call to GetFormats() indicates that MetafilePict and EnhancedMetaFile are available formats. The following does NOT work:
7
11655
by: lgbjr | last post by:
Hello All, I¡¯m using a context menu associated with some pictureboxes to provide copy/paste functionality. Copying the image to the clipboard was easy. But pasting an image from the clipboard is proving to be more difficult. These pictureboxes are bound to an AccessDB. If the user wants to add an image, they select an image using an OpenFileDialog: Dim result As DialogResult = Pic_Sel.ShowDialog() If (result = DialogResult.OK) Then
0
1147
by: Christian Nein | last post by:
Hi, does anybody know a component or library that deals with metafiles? In particular I am searching for a way to build 1 Metafile from many metafiles by assembling them together. With bitmaps this is quite an easy task but with the vector-based metafile format i still don't k now how to do this. Thanx in advance for any help & best regards Christian
5
3455
by: nagar | last post by:
I have a .NET 2.0 application that needs to backup and restore the contents of the clipboard. When I back it up, I use this code: DataObject oldClipboard = Clipboard.GetDataObject(); IDataObject prevClipboard = new DataObject(); string formats; formats = oldClipboard.GetFormats(); //gets all the possible formats
2
2555
by: Alexander Gorbylev | last post by:
Hi! Let the size of vector is e.g. 3.5". I render the same vector on a printer & a screen on the same procedure: printDoc_BeginPrint(object sender, PrintEventArgs e) { .... vector.Width * g.DpiX ....
1
3644
by: bern11 | last post by:
I can get bitmaps from the clipboard, but how do I get Metafiles? The specific instance I am testing is copying a piece of Word clip-art into the clipboard and trying to read it in an application. It appears as a metafile type but isn't recognized as an image. Given: DataObject copyObject; copyObject = (DataObject)Clipboard.GetDataObject(); string types = copyObject.GetFormats();
20
7029
by: Joe Duchtel | last post by:
Hello - I have the following code to get a bitmap from the clipboard and to save it to a *.png file ... Dim lData As IDataObject = Clipboard.GetDataObject() If lData.GetDataPresent(DataFormats.Bitmap) Then Dim lPictureBox As New PictureBox
5
6295
by: AliR \(VC++ MVP\) | last post by:
Hi everyone, I need to draw some rft to the screen. And I found some code out there that uses a Richedit control and sends it an EM_FORMATRANGE to do exactly that. Now I need to add scaling to this code. What I'm trying to do is to have the richedit control draw to a metafile and then I can set the ScaleTrasform of the Graphics object and draw the metafile. But everytime I call Metafile.GetHenhmetafile() it throws a "Parameter is
0
9948
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9798
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
1
10864
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
7980
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
7137
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5807
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
6008
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4623
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
4230
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.