从剪贴板复制增强型图元文件并将其保存为图像

5
我正在使用以下C#代码从剪贴板复制图像。
if (Clipboard.ContainsData(System.Windows.DataFormats.EnhancedMetafile))
{
    /* taken from http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/a5cebe0d-eee4-4a91-88e4-88eca9974a5c/excel-copypicture-and-asve-to-enhanced-metafile*/

    var img = (System.Windows.Interop.InteropBitmap)Clipboard.GetImage();
    var bit = Clipboard.GetImage();
    var enc = new System.Windows.Media.Imaging.JpegBitmapEncoder();

    var stream = new FileStream(fileName + ".bmp", FileMode.Create);

    enc.Frames.Add(BitmapFrame.Create(bit));
    enc.Save(stream);
}

我从这里获得了这段代码:这里。控制流确实进入了if条件语句。Clipboard.GetImage()返回null。请问有人能够建议一下出现了什么问题吗?
我还尝试了以下代码片段。
Metafile metafile = Clipboard.GetData(System.Windows.DataFormats.EnhancedMetafile) as Metafile;

Control control = new Control();
Graphics grfx = control.CreateGraphics();
MemoryStream ms = new MemoryStream();
IntPtr ipHdc = grfx.GetHdc();

grfx.ReleaseHdc(ipHdc);
grfx.Dispose();
grfx = Graphics.FromImage(metafile);
grfx.Dispose();

这个也不起作用。
2个回答

6

您可以通过以下方式使用user32.dll

public const uint CF_METAFILEPICT = 3;
public const uint CF_ENHMETAFILE = 14;

[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool OpenClipboard(IntPtr hWndNewOwner);

[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool CloseClipboard();

[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr GetClipboardData(uint format);

[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool IsClipboardFormatAvailable(uint format);

现在,您可以阅读您的元文件:
Metafile emf = null;
if (OpenClipboard(IntPtr.Zero))
{
    if (IsClipboardFormatAvailable(CF_ENHMETAFILE))
    {
        var ptr = GetClipboardData(CF_ENHMETAFILE);
        if (!ptr.Equals(IntPtr.Zero))
            emf = new Metafile(ptr, true);
    }

    // You must close ir, or it will be locked
    CloseClipboard();
}

我的原始需求涉及对元文件的一些处理,所以我创建了一个MemoryStream

using (var graphics = Graphics.FromImage(new Bitmap(1,1,PixelFormat.Format32bppArgb)))
{
    var hdc = graphics.GetHdc();
    using (var original = new MemoryStream())
    {
        using (var dummy = Graphics.FromImage(new Metafile(original, hdc)))
        {
            dummy.DrawImage(emf, 0, 0, emf.Width, emf.Height);
            dummy.Flush();
        }
        graphics.ReleaseHdc(hdc);

        // do more stuff
    }
}

也许可以帮助到某些人,这里还有一种将元文件保存为位图的方法 http://csharphelper.com/blog/2016/04/make-use-metafile-c/ - ilCosmico

1
以下代码可行。如果需要,您可以更改保存的图像格式。
 if (Clipboard.ContainsImage())
 {
     Image image = Clipboard.GetImage();
     image.Save(@"c:\temp\image.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
 }

仅在您不想将其保存为 EMF 格式时才起作用。如果您需要 EMF,似乎您需要使用 P Invoke 方法。 - A Burns

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接