Freigeben über


Save a diagram to Image File

I’ve been asked a couple of times now about how to save one of our UML diagrams out to an image file. We don’t have a menu item that does that exact thing in the diagrams themselves. We of course support a select-all, copy, then paste which satisfies most, but a few customers have been asking how they can automate that process for documentation generation or what have you.

Turns out it is actually quite easy to write a simple extension to do exactly this.

Below is the code required to add a menu item that will appear as a context menu in any of the five UML diagrams shipping in VS2010 ( UML class, sequence, activity, component, and use case diagrams ).

The piece of “magic” in the code below is this line:

Diagram dslDiagram = Context.CurrentDiagram.GetObject<Diagram>();

You can ask an IDiagramContext to give you a Microsoft.VisualStudio.Modeling.Diagrams.Diagram object via the GetObject<>() method. For those of you familiar with the DSL programming model, this is indeed a DSL Diagram object, which gives you access to the public ( and documented ) DSL APIs that we have built the UML diagrams on.

We’ve tried to simplify the APIs needed to manipulate the UML object models, which is why we didn’t make the DSL underlying implementation more obvious.

Regardless, here’s the code needed to get a menu item called “Save To Image…” on your UML diagrams. Most of the code is manipulating the SaveFileDialog object. :)

This will work in the current RC build for VS2010.

Enjoy!

Cameron

using System;
using System.Linq;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Presentation;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;
using Microsoft.VisualStudio.Modeling.ExtensionEnablement;
using Microsoft.VisualStudio.Uml.Classes;
using Microsoft.VisualStudio.Modeling.Diagrams;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace SaveToImage
{
    // Custom context menu command extension
    // See https://msdn.microsoft.com/en-us/library/ee329481(VS.100).aspx
    [Export( typeof( ICommandExtension ) )]
    [ClassDesignerExtension]

    [UseCaseDesignerExtension]
    [SequenceDesignerExtension]
    [ComponentDesignerExtension]
    [ActivityDesignerExtension]
    class CommandExtension : ICommandExtension
    {
        [Import]
        IDiagramContext Context { get; set; }

        public void Execute( IMenuCommand command )
        {
            Diagram dslDiagram = Context.CurrentDiagram.GetObject<Diagram>();

            if( dslDiagram != null )
            {
                SaveFileDialog dialog = new SaveFileDialog();
                dialog.AddExtension = true;
                dialog.DefaultExt = "image.bmp";
                dialog.Filter = "Bitmap ( *.bmp )|*.bmp|JPEG File ( *.jpg )|*.jpg|Enhanced Metafile (*.emf )|*.emf|Portable Network Graphic ( *.png )|*.png";
                dialog.FilterIndex = 1;
                dialog.Title = "Save Diagram to Image";

                if( dialog.ShowDialog() == DialogResult.OK && !string.IsNullOrEmpty( dialog.FileName))
                {
                    Bitmap bitmap = dslDiagram.CreateBitmap( dslDiagram.NestedChildShapes, Diagram.CreateBitmapPreference.FavorClarityOverSmallSize );
                    bitmap.Save( dialog.FileName, GetImageType( dialog.FilterIndex ));
                }
            }
        }

        public void QueryStatus( IMenuCommand command )
        {
            if( Context.CurrentDiagram != null && Context.CurrentDiagram.ChildShapes.Count() > 0 )
            {
                command.Enabled = true;
            }
            else
            {
                command.Enabled = false;
            }
        }

        public string Text
        {
            get { return "Save To Image…"; }
        }

        private ImageFormat GetImageType( int filterIndex )
        {
            ImageFormat result = ImageFormat.Bmp;

            switch( filterIndex )
            {
                case 2:
                    result = ImageFormat.Jpeg;
                    break;
                case 3:
                    result = ImageFormat.Emf;
                    break;
                case 4:
                    result = ImageFormat.Png;
                    break;
            }
            return result;
        }
    }
}

Comments

  • Anonymous
    March 11, 2010
    Do you have a link which talks about creating new extension in VS2010?

  • Anonymous
    March 12, 2010
    If you are interested in the extension points that we are enabling with all the visualization and modeling tools in 2010, check out this link:http://msdn.microsoft.com/en-us/library/ee329484(VS.100).aspxIf you are looking for VS2010 extensibility in general, check out this one:http://msdn.microsoft.com/en-us/library/bb166441(VS.100).aspxAnd if you are just looking for more general VS information, I also recommend checking out the VS team blog here:http://blogs.msdn.com/visualstudio/default.aspxCheers!Cameron

  • Anonymous
    March 31, 2010
    I couldn't find this assembly.Microsoft.VisualStudio.Modeling.ExtensionEnablementI have VS2010 RC1.

  • Anonymous
    March 31, 2010
    You need to be sure to install the VSVMSDK installed. Check out this post for more details. http://blogs.msdn.com/camerons/archive/2010/02/10/visual-studio-2010-visualization-and-modeling-sdk-rc.aspxI also recommend hitting the forums if you have further questions like this, as you'll get a faster response. :)http://social.msdn.microsoft.com/Forums/en-US/vsarch/threadsThanks!Cameron

  • Anonymous
    April 21, 2010
    Is there any way to extend the layer diagram? Or is there any tool can help me to save the layer diagram as image?

  • Anonymous
    April 22, 2010
    Hey Jifeng,Cameron's post above will work for layer diagrams as well. So you canUse copy/paste to save the diagram as an image.Use the sample code above to write a tool that will. We are currently working on some fairly extensive extensibility for the layer diagram. This will supportAccess to the layer model and the ability to create commands etc. much like the extensibility for the rest of our UML models likehttp://msdn.microsoft.com/en-us/library/ee329484Creation of custom validation rules to support your own architectural enforcement.Look for news and release information on that in the near future.ThanksSuhail

  • Anonymous
    January 04, 2011
    Thanks for the code sample, much appreciated. We experimented with this approach (built a VSIX and all) but found the fidelity of the resulting bitmaps to be too low so we are using print to PDF/XPS instead. It would be a big help to have advice on how to configure our project to auto-generate the image files (whether bitmap or PDF) whenever there is a Build of the modeling project. And auto-post these to TFS source control and/or the TFS team project portal.

  • Anonymous
    January 05, 2011
    @John - Take a look at the "readonly" APIs for loading a model without having VS opened. I believe you should be able to do what you are sugggesting via those APS. Here's the link: msdn.microsoft.com/.../ee329477.aspx