Follow us on Twitter

Creating Map Images in C#

Share:

A program can create MapPoint images (bitmaps) in a number of ways. Common approaches are to copy a map image to the clipboard, or to save the map as a web page and to extract the resulting GIF image. These are both messy approaches. A third approach is often ignored by .NET programmers, and that is to use the GetPictureFromObject() method. This method creates a Visual Basic (VB6) Picture object which is different to the .NET Image object. This article shows you how to use GetPictureFromObject() in a C# program, and to convert the Picture into a form that can be used by .NET, and to save it as a PNG bitmap file.

Converting a Picture to an Image

There are a number of approaches to converting a VB6 Picture to a .NET Image. Some rely on out-dated compatibility libraries. Virtually all assume the Picture is a bitmap. The reality is that both the Picture and Image classes can encapsulate different image types, and GetPictureFromObject() returns the image as metafile and not a pure bitmap. Windows Metafile (WMF) is a vector format that dates back to the early 1990s, but continues to be supported by .NET. It can also include bitmaps and icons.

A VB6 Picture is actually a COM object that implements the IPictureDisp interface. Knowing this, we can use the IPictureDisp interface to query the Picture object, and to extract the internal metafile.

The following implementation is based on the second approach in Andrew Whitechapel’s article “Converting between IPictureDisp and System.Drawing Image”. This only worked with pure bitmaps, but I have amended the PictureDispToImage() method to also handle metafiles. I have also removed the (reverse) Image to IPictureDisp conversion because this is not required.

The conversion code has been implemented as a method in a static conversion class. Before compiling it, you will need to add a reference to the COM library stdole. This library includes the definition of the IPictureDisp interface. Here is the conversion code:

 

Calling GetPictureFromObject

Next we need a demonstration program that calls GetPictureFromObject() and uses the above class to convert the image into a usable form. The following code is a simple form application that includes a PictureBox control and a “Go” button. Pressing “Go” starts MapPoint in the background, draws something interesting (pushpins for the various venues in London’s Olympic Park), creates an image, displays it in the PictureBox and saves it as a PNG to the desktop.

For simplicity, I have not included the GUI definition. The PictureBox is named ‘myPictureBox’ and the ‘Go’ button has a click handler called ‘buttonGo_click()’. You should include references to stdole and System.Drawing (as above), and the MapPoint COM library. This particular implementation was built with MapPoint 2011 Europe but it also compiles with MapPoint 2013 North America – unfortunately MapPoint 2013 Europe had yet to be released when this article was written.

The namespace references are as above, plus the addition of the MapPoint namespace:

We need to perform some unit conversions, so we define a static constant:

GetPictureFromObject() returns an object defined in HIMETRIC units. This is a VB6-era device independent unit that is similar to a twip, but has no direct support in .NET’s Drawing library. There are 100 HIMETRIC units in a millimetre. Hence Inch2HIMETRIC contains the number of HIMETRIC units in an inch.

Here is the definition for buttonGo_Click():

And that is it! Here is the final results of the form and PictureBox:

The PictureBox example

The PictureBox example

Converting Picture objects into .NET Drawing.Image objects can be messy due to the lack of any good casts or conversion functions. Also online examples invariably concentrate on pure bitmaps and not the metafiles used by MapPoint. However, as you can see, conversion is not too difficult, and the end result is much easier and cleaner than using the clipboard or the “Save to Web Page” function.

3 comments to Creating Map Images in C#

  • Joe Colon

    Hello, this is an amazing article. Is there anyway to do this from ASP.Net? I tried to run the code from a web page but it fails when it reaches the stdole line. Probably an out of process permission issue? It would be great to get this working from ASP.Net.

    • It might be that stdole.dll isn’t installed, or it hasn’t been installed into the GAC properly? It could be permissions – I am far from being an ASP.NET expert.

      Note that using MapPoint in a web server environment is generally not recommended, for the same reasons as Word and Excel are not recommended. This is because they are desktop user applications, and they are difficult to manage in what is essentially a headless server environment. The user can’t respond to error messages, life cycle management is ‘dirty’, etc.

  • Todd

    Excellent and concise article. I got this working with Windows 7, VS 2011 and MapPoint 2013 NA. I believe this would work with VS 2013 no problem.

    I chose a C# Windows Forms Application and then simple used the ToolBox to draw a picture box into the default form and renamed it myPictureBox. Then I added a button and included the supplied code into its method.

    The references by default here:

    C:\Program Files (x86)\Microsoft.NET\Primary Interop Assemblies\stdole.dll
    C:\Program Files (x86)\Microsoft MapPoint 2013\MPNA83.tlb

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">