11

我需要使用 WPF 显示Windows 图元文件(EMF),我该怎么做?

编辑:

我会保持图像矢量为基础。

4

2 回答 2

15

看看第3 方库 Ab2d.ReadWmf

更新 #1:概述

首先,这篇文章指出微软不打算在 WPF 中支持 EMF 文件。这并不意味着它不能完成,只是他们不会支持他们。

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

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

如果您使用过 WPF,您就会知道 WPF 从根本上不同于 GDI。此处提供了快速概览。这意味着您需要读取 EMF 文件并将 GDI 调用转换为 WPF 调用。这是他们讨论该过程的线程。这对我来说听起来像是很多工作。

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

更新 #2:代码示例

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

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

用户控制:

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>
于 2012-04-13T19:49:45.890 回答
12

这是一个实用程序函数,它加载 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 应用程序中,但这应该不是什么大问题。

于 2012-06-19T14:05:10.440 回答