如何显示Windows图元文件?

时间:2012-04-13 19:41:47

标签: c# .net wpf .emf metafile

我需要使用WPF显示Windows Metafile(EMF),我该怎么办?

编辑:

我要保持基于矢量的图像。

2 个答案:

答案 0 :(得分:14)

查看3rd party library Ab2d.ReadWmf

更新#1:概述

首先,this post表示Microsoft不打算在WPF中支持EMF文件。这并不意味着它无法完成,只是他们不会支持它们。

查看有关WMF / EMF格式的Wikipedia page,我看到它将EMF描述为:

  

实质上,WMF文件存储必须发布到Windows图形设备接口(GDI)层以在屏幕上显示图像的函数调用列表。由于某些GDI函数接受指向错误处理的回调函数的指针,因此WMF文件可能错误地包含可执行代码。

如果您使用过WPF,那么您就知道WPF与GDI根本不同。可以快速浏览here。这意味着您需要读入EMF文件并将GDI调用转换为WPF调用。 Here's a thread他们在那里讨论这个过程。这对我来说听起来很多。

幸运的是,Microsoft提供了一个用于在Windows图元文件中阅读的界面。看一下this thread示例和documentation available here,但这只会让你到达一半,因为它不是WPF Visual。在这一点上,我认为最简单的解决方案是在WPF应用程序中创建一个WinForms控件并将其托管在WindowsFormsHost控件中。

更新#2:代码示例

在WPF应用程序中显示EMF文件:

  1. 创建WinForms UserControl
  2. 将EMF文件加载到MetaFile对象中,并在OnPaint处理程序中绘制它。
  3. 添加对WindowsFormsIntegration库的引用
  4. 在WindowsFormsHost元素中托管WinForms控件
  5. 用户控件:

    public partial class UserControl1 : UserControl
    {
         private Metafile metafile1;
    
         public UserControl1()
         {
             InitializeComponent();
             metafile1 = new Metafile(@"C:\logo2.emf");
         }
    
         protected override void OnPaint(PaintEventArgs e)
         {
             e.Graphics.DrawImage(metafile1, 0, 0);
         }
    }
    

    XAML:

    <Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:app="clr-namespace:WpfApplication1" 
        Title="MainWindow" Height="200" Width="200">
    
         <Grid>
             <WindowsFormsHost>
                 <app:UserControl1/>
             </WindowsFormsHost>
         </Grid>
     </Window>
    

答案 1 :(得分:10)

这是一个实用程序函数,它加载EMF文件并将其转换为WPF BitmapSource

public static class Emfutilities
{
        public static BitmapSource ToBitmapSource(string path)
        {
            using (System.Drawing.Imaging.Metafile emf = new System.Drawing.Imaging.Metafile(path))
            using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(emf.Width, emf.Height))
            {
                bmp.SetResolution(emf.HorizontalResolution, emf.VerticalResolution);
                using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmp))
                {
                    g.DrawImage(emf, 0, 0);
                    return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bmp.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                }
            }
        }
}

您只需使用它:

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            // img is of Image type for example
            img.Source = Emfutilities.ToBitmapSource("SampleMetafile.emf");
        }
    }

}

缺点是您需要将System.Drawing.dll(GDI +)引用到您的WPF应用程序中,但这不应该是一个大问题。