C# saving as EMF

This is a useful piece of code, created as an extension method on MetaFile to save a Metafile as a real Vector based emf not as a PNG. See : msdn on image encoders / decoders.

Here is the code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;

namespace System.Drawing.Imaging
{
    public static class ExtensionMethods
    {
        public static void SaveAsEmf(this Metafile me, string fileName)
        {
            /* http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/12a1c749-b320-4ce9-aff7-9de0d7fd30ea
                How to save or serialize a Metafile: Solution found
                by : SWAT Team member _1
                Date : Friday, February 01, 2008 1:38 PM
             */
            int enfMetafileHandle = me.GetHenhmetafile().ToInt32();
            int bufferSize = GetEnhMetaFileBits(enfMetafileHandle, 0, null); // Get required buffer size.
            byte[] buffer = new byte[bufferSize]; // Allocate sufficient buffer
            if (GetEnhMetaFileBits(enfMetafileHandle, bufferSize, buffer) <= 0) // Get raw metafile data.
                throw new SystemException("Fail");

            FileStream ms = File.Open(fileName, FileMode.Create);
            ms.Write(buffer, 0, bufferSize);
            ms.Close();
            ms.Dispose();
            if (!DeleteEnhMetaFile(enfMetafileHandle)) //free handle
                throw new SystemException("Fail Free");
        }

        [DllImport("gdi32")]
        public static extern int GetEnhMetaFileBits(int hemf, int cbBuffer, byte[] lpbBuffer);

        [DllImport("gdi32")]
        public static extern bool DeleteEnhMetaFile(int hemfbitHandle);
    }
}

How to use this code?

            //Set up reference Graphic
            Graphics refG = this.CreateGraphics(); //assumin this code is running on a control/form
            IntPtr refGrap = refG.GetHdc();
            var img = new Metafile(refGrap, EmfType.EmfPlusDual, "..");

            //Draw some silly drawing
            using (var g = Graphics.FromImage(img))
            {
                var r = new Rectangle(0,0,100,100);
                var reye1 = new Rectangle(20, 20, 20, 30);
                var reye2 = new Rectangle(70, 20, 20, 30);

                var pBlack = new Pen(Color.Black, 3);
                var pRed = new Pen(Color.Red, 2.5f);

                g.FillEllipse(Brushes.Yellow, r);
                g.FillEllipse(Brushes.White, reye1);
                g.FillEllipse(Brushes.White, reye2);
                g.DrawEllipse(pBlack, reye1);
                g.DrawEllipse(pBlack, reye2);
                g.DrawBezier(pRed, new Point(10, 50), new Point(10, 100), new Point(90, 100), new Point(90, 50));
            }

            refG.ReleaseHdc(refGrap); //cleanup
            refG.Dispose();

            img.SaveAsEmf("test.emf");  //chose this line

            //img.Save("test2.emf", ImageFormat.Emf); //or this line

The end result:

Leave a Reply