如何显示Windows图元文件?

gli*_*ite 9 .net c# wpf metafile .emf

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

编辑:

我要保持基于图像矢量.

Dan*_*sha 14

看看第三方图书馆Ab2d.ReadWmf.

更新#1:概述

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

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

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

如果您使用WPF很多,那么您就知道WPF与GDI根本不同.这里有一个快速概述.这意味着您需要读入EMF文件并将GDI调用转换为WPF调用.这是一个他们讨论过程的线程.这对我来说听起来很多.

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

更新#2:代码示例

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

  1. 创建一个WinForms UserControl
  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);
     }
}
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)


Sim*_*ier 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());
                }
            }
        }
}
Run Code Online (Sandbox Code Playgroud)

你只需使用它:

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

}
Run Code Online (Sandbox Code Playgroud)

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

  • 它工作+1.但是EMF用于矢量图形,BitmapSource(如你所知)是光栅.我怎样才能解决这个问题? (2认同)
  • 你没有在你的问题中指明你想保持基于矢量的图像.您需要将EMF记录转换为纯XAML.这是一项艰苦的工作(也可能是CPU密集型)并且不是免费午餐:-)请参阅Dan Busha对转换工具的回答. (2认同)