HOW TO: Automate the MapPoint 2002 Control by Using Managed Visual C++ .NET (302900)



The information in this article applies to:

  • Microsoft MapPoint 2002
  • Microsoft Visual C++ .NET (2003)
  • Microsoft Visual C++ .NET (2002)

This article was previously published under Q302900
For a Microsoft Visual C# version of this article, see 302898.

SUMMARY

Use this step-by-step guide to build a managed Visual C++ .NET application that places the Microsoft MapPoint 2002 MapPoint Control on a Windows form, and automates MapPoint through the control.

By using this control, you can access most, but not all, MapPoint application functionality. For example, you cannot programmatically save a map in HTML format with the ActiveX control. You can save the map as a MapPoint .ptm file by using the control, and then programmatically open the .ptm file in the MapPoint application and save it as HTML. This article contains sample code that demonstrates how to do this.

Windows Forms can host only Windows Forms controls. All Windows Forms controls are classes that are derived from the System.Windows.Forms.Control class. To host a MapPoint Control on a form, it must appear to be a Windows Forms control. Conversely, the MapPoint Control must appear to be hosted in an ActiveX control container. The System.Windows.Forms.AxHost class (which derives from System.Windows.Forms.Control) acts as a Windows Forms control "on the outside" and acts as a MapPoint Control container "on the inside". In order to host MapPoint Control, you must create a wrapper class that derives from System.Windows.Forms.AxHost. This control hosts the MapPoint Control and exposes its properties, methods, and events (PMEs) as PMEs of the generated control.

This article demonstrates the following:
  • How to build an AxHost wrapper and use it on a Windows Form.
  • How to automate the MapPoint Control.
  • How to open a .mpt file and save it as an HTML file by using the MapPoint application.

Wrap the MapPoint Control in AxHost and Import the MapPoint Object Library

The following steps demonstrate how to build:
  • AxMappoint.dll: The AxHost wrapper for the MapPoint Control. This wrapper control contains an instance of the underlying ActiveX control.
  • MapPoint.dll: The common language run-time proxy for the COM types in the MapPoint ActiveX control.
  • MapPointApp.dll: The COM interop assembly for the MapPoint 2002 type library that you can use to automate the MapPoint application. Since the MapPoint Control and the MapPoint application both use the default "MapPoint" namespace, you will specify the "MapPointApp" namespace to avoid a namespace collision.
  1. On the Windows Start menu, point to Programs, point to Visual Studio.NET, point to Visual Studio.NET Tools and then click Visual Studio.NET Command Prompt.
  2. At the Visual Studio.NET command prompt, type the following commands:

    cd\
    cd Program Files\Microsoft MapPoint
    Aximp mappointcontrol.ocx /out:AxMappoint.dll

    The following report appears:

    Generated Assembly: C:\Program Files\Microsoft MapPoint\MapPoint.dll
    Generated Assembly: C:\Program Files\Microsoft MapPoint\AxMappoint.dll

  3. At the Visual Studio.NET command prompt, type the following command:

    tlbimp mpna81.tlb /namespace:MapPointApp /out:MapPointApp.dll

    The following result appears:

    Type Library imported to C:\Program Files\Microsoft MapPoint\MapPointApp.dll

  4. Close the Visual Studio.NET command prompt window.


Build the Visual C++ .NET Application

  1. Create a new Managed C++ Application and name it MappointControl.
  2. On the Build menu, click Build Solution to create a Debug folder in the project directory.
  3. From the C:\Program Files\Microsoft MapPoint folder, copy the following three files

    AxMappoint.dll
    Mappoint.dll
    MapPointApp.dll

    into the MappointControl\Debug folder.
  4. Replace the contents of MappointControl.cpp with the following code:
    // 
    // This is the main project file for the Visual C++ application project 
    // generated by using an Application Wizard.
    // 
    // For help with AxHost, see
    // http://gdndev/quickstart/winforms/doc/WinFormsAxHosting.aspx
    
    #include "stdafx.h"
    #using <mscorlib.dll>  // Comparable to the #import directive.
    #using "debug\AxMapPoint.dll"
    #using "debug\MapPoint.dll"
    #using "debug\MapPointApp.dll"
    
    using namespace System;
    using namespace System::IO;
    using namespace AxMapPoint;  // The Control in IL.
    using namespace MapPoint;    // The Control's version of MapPoint, in IL.
    using namespace MapPointApp; // MapPoint's TypeLib imported into IL.
    
    // Required dlls for WinForms.
    #using "System.dll"
    #using "System.Windows.Forms.dll"
    #using "System.Drawing.dll" 
    
    // Required namespaces for WinForms.
    using namespace System::ComponentModel;
    using namespace System::Windows::Forms;
    using namespace System::Drawing;
    using namespace System::Runtime::InteropServices;
    using namespace System::Collections;
    using namespace System::Windows::Forms::Design;
    
    __gc class WinForm: public Form      // Note - GarbageCollected
    {
    private:
       AxMappointControl                  *mappointctl;
       MapPointApp::ApplicationClass      *pApp;
       MapPointApp::Map                   *pAppMap;
    
       MapPoint::Map                      *pMap;
       MapPoint::Route                    *pRoute;
       MapPoint::Waypoints                *pWaypoints;
       MapPoint::FindResults              *pResults;
       MapPoint::Waypoint                 *pStartPoint;
       MapPoint::Waypoint                 *pMidPoint1;
       MapPoint::Waypoint                 *pMidPoint2;
       MapPoint::Waypoint                 *pEndPoint;
       System::Collections::IEnumerator   *pItem;
    
       Button          *button1;
       Button          *button2;
       Button          *button3;
       String          *windir;
       String          *caption;     // Caption of the WinForm
       Drawing::Size   FormSize;     // Size of the WinForm
    
    public:
       WinForm() 
       {
          // Set caption and size of the WinForm.
    
          caption = "Form1";
          FormSize.Width = SystemInformation::WorkingArea.Width;
          FormSize.Height = SystemInformation::WorkingArea.Height;
          windir=System::Environment::GetEnvironmentVariable("windir");
          InitForm();
       } 
    
       void InitForm()
       {
          // Setup controls here.
          // Basic WinForm Settings.     
    
          SuspendLayout();
          mappointctl = new AxMappointControl();
          mappointctl->BeginInit();
          mappointctl->Name = "mappointctl";
          mappointctl->Location = Drawing::Point(233,32);
          mappointctl->Size = Drawing::Size(FormSize.Width - 252,FormSize.Height - 64);
          Controls->Add(mappointctl);
          mappointctl->EndInit();
          mappointctl->OpenMap("C:\\Program Files\\Microsoft MapPoint\\Templates\\New North American Map.ptt");
    
          // button1
          button1 = new Button();
          button1->Name = "button1";
          button1->Size = Drawing::Size(180, 23);
          button1->TabIndex = 1;
          button1->Location = Drawing::Point(24,32);
          button1->Click += (new EventHandler(this, &WinForm::button1_Click));
          Controls->Add(button1); 
    
          // button2
          button2 = new Button();
          button2->Name = "button2";
          button2->Size = Drawing::Size(180, 23);
          button2->TabIndex = 2;
          button2->Location = Drawing::Point(24,64);
          button2->Click += (new EventHandler(this, &WinForm::button2_Click));
          Controls->Add(button2);
    
          // button3
          button3 = new Button();
          button3->Name = "button3";
          button3->Size = Drawing::Size(180, 23);
          button3->TabIndex = 3;
          button3->Location = Drawing::Point(24,96);
          button3->Click += (new EventHandler(this, &WinForm::button3_Click));
          Controls->Add(button3); 
    
          Size = FormSize;
    
          Name = "Form1";
          Text = "Form1";
          Load += new System::EventHandler(this, Form1_Load);
          Closing += new System::ComponentModel::CancelEventHandler(this,Form1_Closing);
          ResumeLayout(false);
       }
    
       void button1_Click(Object *sender, EventArgs *e)
       {	  	  
          // Plan a route
          pMap = mappointctl->get_ActiveMap();
          // The sixth parameter of FindAddressResults calls for an object. GeoCountry enums are integers
          Object* US  =  __box(MapPoint::GeoCountry::geoCountryUnitedStates);  // boxing converts enum to object!!
    
          pRoute = pMap->get_ActiveRoute();
          pWaypoints = pRoute->get_Waypoints();
          pResults = pMap->FindAddressResults("16011 N. E. 36th Way","Redmond","","WA","98052",US);
    
          if (pResults->get_Count()>= 1)
          {
             pItem = pResults->GetEnumerator();
             pItem->Reset();
             pItem->MoveNext();
             pStartPoint = pWaypoints->Add(pItem->get_Current(),"Loc1");
             MapPoint::Location *pLocation = pStartPoint->get_Location();
             pMap->AddPushpin(pLocation,"Start");
             pMap->ZoomIn();
          }
          else
          {
             MessageBox::Show("Didn't find 16011 N. E. 36th Way in Redmond");
             return;
          }
    
          pResults = pMap->FindAddressResults("11235 SE 6th Street", "Bellevue", "", "WA", "98004", US);
          if (pResults->get_Count()>= 1)
          {
             pItem = pResults->GetEnumerator();
             pItem->Reset();
             pItem->MoveNext();
             pMidPoint1 = pWaypoints->Add(pItem->get_Current(),"Loc2");
             MapPoint::Location *pLocation = pMidPoint1->get_Location();
             pMap->AddPushpin(pLocation,"Stop 1");
             pMap->ZoomIn();
          }
          else
          {
             MessageBox::Show("Didn't find 11235 SE 6th Street in Bellevue");
             return;
          }
          pRoute->Calculate();
    
          double dLeg1;
          dLeg1 = pRoute->get_DrivingTime();
          pResults = pMap->FindAddressResults("22011 SE 51st Street", "Issaquah", "", "WA", "98027", US);
          if (pResults->get_Count()>= 1)
          {
             pItem = pResults->GetEnumerator();
             pItem->Reset();
             pItem->MoveNext();
             pMidPoint2 = pWaypoints->Add(pItem->get_Current(),"Loc3");
             MapPoint::Location *pLocation = pMidPoint2->get_Location();
             pMap->AddPushpin(pLocation,"Stop 2");
             pMap->ZoomIn();
          }
          else
          {
             MessageBox::Show("Didn't find 22011 SE 51st Street in Issaquah");
             return;
          }
    
          pRoute->Calculate();
    
          double dElapsedTime1 = pRoute->DrivingTime;
          double dLeg2 = dElapsedTime1 - dLeg1;
          // Finished calculating trip time to this waypoint, and Leg 2 drive time.
    
          pResults = pMap->FindAddressResults("16011 N.E. 36th Way", "Redmond", "", "WA", "98052", US);
          if (pResults->get_Count()>= 1)
          {
             pItem = pResults->GetEnumerator();
             pItem->Reset();
             pItem->MoveNext();
             pEndPoint = pWaypoints->Add(pItem->get_Current(),"Loc4");
             MapPoint::Location *pLocation = pEndPoint->get_Location();
             pMap->AddPushpin(pLocation,"End");
             pMap->ZoomIn();
          }
          else
          {
             MessageBox::Show("Didn't find 16011 N.E. 36th Way in Redmond");
             return;
    
          }
    
          pRoute->Calculate();
    
          double dElapsedTime = pRoute->DrivingTime;
          double dLeg3 = dElapsedTime - dElapsedTime1;
          // End planning trip back to EndPoint and calculating Leg 3 time.
    
          double StopTime = 0; // Layover or delivery time.
          StopTime = 0.3 * MapPoint::GeoTimeConstants::geoOneHour; // between 18 and 19 minutes
          DateTime dtStartTime = System::DateTime::Parse("8:00:00 AM");
    
          pStartPoint->PreferredDeparture = dtStartTime;
          DateTime dtMid1Time = dtStartTime.AddDays(dLeg1+StopTime);
          pMidPoint1->PreferredDeparture = dtMid1Time;
    
          DateTime dtMid2Time = dtMid1Time.AddDays(dLeg2+StopTime);
          pMidPoint2->PreferredDeparture = dtMid2Time;
    
          mappointctl->SaveMapAs("C:\\ATestMap.ptm");	  
          pMap->set_Saved(true);
          pMap->ZoomOut();
       } 
    
       void button2_Click(Object *sender, EventArgs *e)
       {
          // Open the map and re-save it as HTML.   
          pApp = new MapPointApp::ApplicationClass();
          if (System::IO::File::Exists("C:\\ATestMap.ptm"))
          {
             pAppMap = pApp->OpenMap("C:\\ATestMap.ptm", false);
             pAppMap->SaveAs("C:\\ATestMap.htm", MapPointApp::GeoSaveFormat::geoFormatHTMLMapAndDirections, false);
             pAppMap->set_Saved(true);
          }
          pApp->Quit();
       }
    
       void button3_Click(Object *sender, EventArgs *e)
       {
          this->Close();
       }
    
       void Form1_Load(Object *sender, EventArgs *e)
       {
          button1->Text = "Plan a Route";
          button2->Text = "Copy Map to HTML";
          button3->Text = "Cleanup and Quit";
       }
    
       void Form1_Closing(System::Object __gc* pObj, System::ComponentModel::CancelEventArgs __gc* pArgs)
       {
          if(pMap != 0)
          {
             pMap->set_Saved(true);
          }
       }
    
    }; // End of class WinForm.
    
    int __stdcall WinMain()
    {
       System::Threading::Thread::get_CurrentThread()->set_ApartmentState(Threading::ApartmentState::STA);
    
       // This line creates an instance of WinForm, and 
       // uses it as the Main Window of the application.
       System::Windows::Forms::Application::Run(new WinForm());
       return 0;
    }
    					
  5. Press F5 to build and run the program.
  6. Click Plan a Route.

    The program builds a route and then saves the map as C:\ATestMap.ptm.
  7. Click Copy Map as HTML.

    The program saves a new copy of the map as C:\ATestMap.htm.
  8. Click Cleanup and Quit to close the form and quit the demonstration.
  9. Start Internet Explorer and open C:\ATestMap.htm to view the HTML copy of the map.

REFERENCES

For additional information, visit the following Microsoft Web site: For more information about creating Windows Forms in managed extensions for Visual C++, see the sample "ManagedCWinFormWiz" in Visual Studio .NET Help.

For another example of using Windows Forms from Visual C++ .NET, click the article number to view the article in the Microsoft Knowledge Base:

307398 HOW TO: Do Basic File I/O in Visual C++ .NET

For more information about hosting ActiveX controls on a Windows form visit the following Web sites:

Modification Type:MinorLast Reviewed:11/18/2005
Keywords:kbAutomation kbHOWTOmaster KB302900 kbAudDeveloper