Search code examples
c#.netwpf.emfmetafile

How to display Windows Metafile?


I need to display a Windows Metafile (EMF) using WPF, how can I do?

Edit:

I'd to keep the image vector-based.


Solution

  • Take a look at the 3rd party library Ab2d.ReadWmf.

    Update #1: Overview

    First off, this post states that Microsoft does not intend support EMF files in WPF. That doesn't mean it can't be done, just that they will not support them.

    Looking at the Wikipedia page about the WMF/EMF format I see that it describes EMF as:

    Essentially, a WMF file stores a list of function calls that have to be issued to the Windows Graphics Device Interface (GDI) layer to display an image on screen. Since some GDI functions accept pointers to callback functions for error handling, a WMF file may erroneously include executable code.

    If you've worked with WPF much you know that WPF is fundamentally different than GDI. A quick overview is available here. This means that you'll need to read in your EMF file and translate the GDI calls to WPF calls. Here's a thread where they discuss the process. That sounds like a lot of work to me.

    Luckily, Microsoft provides an interface for reading in Windows Metafiles. Take a look at this thread for an example and the documentation available here, but this will only get you half way there since it's not a WPF Visual. At this point I think the easiest solution would be to create a WinForms control in your WPF app and host it inside a WindowsFormsHost control.

    Update #2: Code Sample

    To display an EMF file in a WPF application:

    1. Create a WinForms UserControl
    2. Load your EMF file into a MetaFile object and draw it in the OnPaint handler.
    3. Add a reference to the WindowsFormsIntegration library
    4. Host your WinForms control inside a WindowsFormsHost element

    UserControl:

    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>