Automating Microsoft MapPoint

How to run MapPoint on your web server as an ASP or CGI

I'm going to show you how to turn your MapPoint PTM map file into a GIF file so it can be pushed over an http connection and be displayed on a browser. I'm not going to teach you about writing ASP or CGI code. I am not going to teach you how to use automation to stuff new data into an Access table. I kind of expect that you (or someone on your team) already knows these skills. Moreover, my code here will create a new instance of MapPoint each time. This means a load time of around 10 seconds (or more) for each map. And a memory penalty you don't want to pay if you launch multiple instances! So my code is only good for  low-volume applications. The MapPoint license is probably only good for one user at a time anyway.


The first thing that MUST be done regardless of what version of MapPoint you are using is to create a linked data set. Open up Microsoft Access, create a table, and fill it with data. Well, actually, you don't need to use Access. As you'll discover, MapPoint can link to several different data sources. Your data can be lat/lon sets (like I show here), street addresses, or anything that MapPoint needs to display your data. Be sure to include any labels, display types, etc. that must be associated with your data point(s). Save that table. Now open up MapPoint and link your pushpin data set to that table. Save the resulting Map. From now on, you will use that PTM file. The magic is that if you put new data in the database, all you have to do is open that PTM file and tell MapPoint to "Update Linked Sets" to display the new data. Again, it will be up to you to write code that will do all the queries, data lookups and whatever else is needed to repopulate that table each time before you update the linked sets on MapPoint.


I'll start off with an ASP solution to MapPoint 2001 or 2002. The "SendMap" subroutine is actually quite generic and can easily be reused or extended. This ASP uses the "save to html" function, then IGNORES the created HTML file and directly reads and sends the created gif file. To read the gif (something ASP can't do by itself), I use a control available here: http://www.ericphelps.com/q193998/index.htm. I'd rather forcibly read and push the gif like this than simply deliver the htm file. The reason is that although I know the htm file is sent, I can never be sure when the user's browser will get around to requesting the gif file. So I have to create unique names, store all generated files, and set up some sort of routine to periodically flush old files. If I don't create unique names, the user may reload the page and get someone else's map. Both these options bite. By forcibly sending the GIF, I know it's done. I can immediately delete it or reuse it. The ASP as written has several display options. Although I fix the pushpin style in the PTM, I allow the user to select the labeling style (nothing, a simple label, or a balloon label).

<%

Sub SendMap
Dim objBin 'As Q193998.BinRead 'from http://www.ericphelps.com/q193998/index.htm
Dim objMap 'As MapPoint.Map
Dim strDisplay
Const geoFormatHTMLMap = 2
Const geoDisplayName = 1
Const geoDisplayBalloon = 2
    strDisplay = Request.Item("display")
    If strDisplay = "" Then strDisplay = "none"
    Set objMap = CreateObject("MapPoint.Application").OpenMap(Server.MapPath(".") & "\MyMap.ptm")
    objMap.DataSets(1).UpdateLink
    If strDisplay <> "none" Then
        With objMap.DataSets(1).QueryAllRecords
        Do Until .EOF
            If Instr(strDisplay,"name") <> 0 Then .Pushpin.BalloonState = geoDisplayName
            If Instr(strDisplay,"balloon") <> 0 Then .Pushpin.BalloonState = geoDisplayBalloon
            .MoveNext
        Loop
        End With
    End If
    objMap.DataSets(1).ZoomTo
    objMap.SaveAs Server.MapPath(".") & "\temp.htm", geoFormatHTMLMap, False 
    Response.Buffer = False
    Response.ContentType = "image/gif"
    'Q193998 from http://www.ericphelps.com/q193998/index.htm
    Set objBin = Server.CreateObject("Q193998.BinRead")
    Response.BinaryWrite objBin.readBinFile(Server.MapPath(".") & "\temp_files\image_map.gif")
    Set objBin = Nothing
    Response.End
End Sub

%>

Why does my "CreateObject" fail?  First, read this Microsoft Knowledge Base article:
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q257757
Microsoft Office apps are only meant to be used by real users. Otherwise the app has no way of looking up the preferences each user sets. And it has no way to display pop-up error messages. Messages that are more likely to be popped up when the application complains about improper configuration due to no valid user. Ten-to-one says that's your problem. Typically you'll see (if you check the task manager) you did fire up an instance of MapPoint, but you don't seem to be able to talk to it. Let's ignore the fact that the license (buried under a "Works" folder!) says no server applications are allowed. Follow the advice in the KB article and see if that fixes your problem!

Here's the other potential CreateObject problems... Notice my code does two things in the CreateObject call. It gets the MapPoint object AND opens a map. Obviously, if your map file is broken, you'll have problems. Also, I've found problems if you have a previous instance of MapPoint running... Like, ummm... Maybe when you tested your script last time it crashed and never unloaded the MapPoint object or closed the map? Kill MapPoint with the task manager!



Ugly as it is (And cheap too! I've seen it for 25 bucks on EBay.), let's finish off with MapPoint 2000.

First thing we have to do is get MapPoint off the CD! Open REGEDIT and navigate to "HKEY_CURRENT_USER\Software\Microsoft\MapPoint\1.0\BRS". You'll need to make sure "DataPath", "CDTemplate", and "InstallTo" don't point to your CDROM. Likewise, copy any files that are in directories on your CDROM in whatever directory these registry entries do point to onto your hard drive. That's all it takes to get 2000 off the CD and on to your hard drive.

MapPoint 2000 has a bottleneck in getting the graphic out. MapPoint 2000 only has a way to copy a map into the clipboard, but no way to save a map as a graphic. You have to manipulate the clipboard to get the image out, and the only way out is as a BMP file. Then you have to convert the BMP to a GIF. What's worse, MapPoint 2000 had very few automation methods, and I'm sorry to say that in order to get anything out of it you'll have to resort to using SendKeys. That means the program will run visibly and you must stay off they keyboard when it does. I lived with this code for a year until I got MapPoint 2001! You can use my VB5 code below either as part of a compiled CGI or as an ASP helper program. I've removed all the error-checking code and hard-coded the file names just to reduce the code size here:

Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess&, ByVal bInheritHandle&, ByVal dwProcessId&) As Long
Declare Function CloseHandle Lib "kernel32" (ByVal hObject&) As Long
Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle&, ByVal dwMilliseconds&) As Long

Function Ptm2Gif(strPtmFileName$) As String
'Returns the file name of a GIF file representation of a PTM map
Dim objMap As MapPoint.Map
Dim strBmpFileName As String
Dim strGifFileName As String
Dim hndProgram As Long
Dim tidProgram As Long
Const SYNCHRONIZE = &H100000
Const INFINITE = &HFFFFFFFF
    'Get a reference to a MapPoint map
    Set objMap = CreateObject("MapPoint.Application").OpenMap(strPtmFileName)
    'MapPoint 2000 object model requires sendkeys to update linked sets and zoom to data!
    AppActivate "Microsoft MapPoint "
    Wait 3
    AppActivate "Microsoft MapPoint "
    SendKeys "%TU", True 'Update linked sets
    Wait 15
    AppActivate "Microsoft MapPoint "
    SendKeys "%VZD", True 'Zoom to data
    Wait 8
    AppActivate "Microsoft MapPoint "
    SendKeys "% X", True 'Maximize
    Wait 5
    'Put the map into the clipboard
    objMap.CopyMap
    'Quit method not needed under MapPoint 2001
    objMap.Parent.Quit
    Set objMap = Nothing
    'Save the copied map in the clipboard as a bmp
    strBmpFileName = "C:\Windows\Temp\mp.bmp"
    SavePicture Clipboard.GetData(), "C:\Windows\Temp\mp.bmp"
    'Convert BMP to GIF (CONVERT is part of ImageMagick from http://www.imagemagick.org/)
    strGifFileName = "C:\Windows\Temp\mp.gif"
    tidProgram = Shell("convert.exe C:\Windows\Temp\mp.bm C:\Windows\Temp\mp.gif", vbHide)
    hndProgram = OpenProcess(SYNCHRONIZE, 0, tidProgram)
    Call WaitForSingleObject(hndProgram, INFINITE)
    Call CloseHandle(hndProgram)
    Kill "C:\Windows\Temp\mp.bmp"
    Ptm2Gif = "C:\Windows\Temp\mp.gif"
End Function
 

 

Lost? Look at the site map.

Bad links? Questions? Send me mail.

Google
Yahoo
Ask Jeeves