Forget Google Maps for Embedding Simple Maps in an AutoHotkey Graphical User Interface (GUI)—OpenStreetMap Supports iFrame Embedding…and It’s Free!
If you only want a simple reference map for your AutoHotkey GUI, then Google has just made that impossible. Google Maps no longer supports embedding maps in an HTML iFrame. (I wish Google had taken this action before I wrote my last two blogs.) Now, to do anything with Google Maps you must get the API (credit card number required) for even the simplest of things. For many professionals needing the extra features, the API may be worth it. (Google credits $200 each month to low quantity users…at least for now.) But why even bother when OpenStreetMap.org, a public source, offers map embedding free under an open license. Plus, it’s likely to remain free forever.
Last week, I wrote about how to embed a Google map into an AutoHotkey GUI, “Embedding Google Maps in the IPFind.ahk GUI.” Within a day or two, Google blocked all iFrame HTML embedding. (Go figure! I don’t think I’m the only one who might be a little disappointed.) However, that action prompted me to take a closer look at OpenStreetMap.org.
To my delight, I discovered that in my earlier perusal I had overlooked the same type of HTML iFrame embedding that Google once offered (only a week ago)—plus, I found other features that eliminated all of my earlier misgivings about OpenStreetMap.org. Since I had already written the code for adding maps to the IPFind.ahk script using Google, I quickly modified it to use the alternate resource.
While the IPFindGoogleMap.ahk script won’t load any maps, the techniques I introduced in my blogs remain valid. (I plan to leave those blogs intact for future reference.) In this blog, I talk about how to alter the Google Maps IPFind.ahk script to support OpenStreetMap.org.
Note: The IPFind.ahk script works (CTRl+ALT+I) by using Regular Expressions (RegEx) to identify and extract IP addresses from text selected (highlighted) in any document or Web page, looking up each at an IP location Web page, then retrieving (again using Regular Expressions) basic location data including the latitude and longitude of the Internet Service Provider (ISP).
The main sticking point for the script rewrite came in the form of the map scale. Google used a single number to set the initial map scale while OpenStreetMap.org uses a box bound by two sets of longitude and latitude.
On the downside, I did not immediately find a method for loading maps based upon city, state, and country—although, with a little digging around, you might find one. That means I must limit the script to using latitude and longitude to load the interactive maps. This does not present a problem since the IPFind.ahk script already returns all of those parameters.
Embedding OpenStreetMap.org Maps in an AutoHotkey GUI
Upon closer inspection, it turns out that the share button on the OpenStreetMap.org site offers three types of sharing features:
- A link for directly accessing the site from any browser.
- A convenient shortened link for accessing that same map page.
- The HTML code for embedding the map into an iFrame.
The third option gives us what we need to write a local file for embedding the iFrame HTML code. (See last week’s blog for more details about writing local files, “Embedding Google Maps in the IPFind.ahk GUI,” plus, “Embed Google Maps in an AutoHotkey GUI” for more information about embedding maps in an AutoHotkey GUI.) The following shows a sample HTML iFrame taken from the share button at OpenStreetMap.org:
<iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="https://www.openstreetmap.org/export/embed.html?bbox=-118.7065887451172%2C33.93737857715181%2C-118.13323974609376%2C34.18226973974575&layer=cyclemap&marker=34.0599126088544%2C-118.41991424560547" style="border: 1px solid black"></iframe>
You’ll find the key parameters required for embedding an iFrame map in that OpenStreetMap.org URL:
- The
bbox=
parameters use two sets of longitude (in pink) and latitude (in pale blue) to enclose a map area. AutoHotkey must calculate those numbers based upon the latitude and longitude pulled from the original IP location site. - To add a location marker, the
marker=
parameters (in green) use the original latitude and longitude directly. - The Cycle Map layer (
layer=cyclemap
) includes English labels in the map along with the local language. This resolved one of my previous concerns.
After saving the two unchanging portions for the code to the variables HTML1 and HTML2 in the auto-execute section at the top of the script:
HTML1 := "<div style='width: 100%'><iframe width='100%' height='225' frameborder='0' scrolling='no' marginheight='0' marginwidth='0' src='https://www.openstreetmap.org/export/embed.html?bbox="
HTML2 := "&layer=cyclemap' style='border: 1px solid black'></iframe></div>"
AutoHotkey quickly constructs the entire HTML code-set on the fly by saving it to the variable MapEmbed:
MapEmbed := HTML1 . WhereIs[4]-2 . "," . WhereIs[3]-3 . "," . WhereIs[4]+2 . "," . WhereIs[3]+3 . "&marker=" . WhereIs[3] . "," . WhereIs[4] . HTML2
Note: The %2C
appearing in the original code translates to a comma in the URL address. The Web address can use either interchangeably. Since the % sign has special meaning in AutoHotkey, I’ve opted to replace the %2C
symbols with commas in the above expression.
Building the Map Box
The parameters of bbox
(longitude1, latitude1, longitude2, latitude2) outline the area of the map embedded in the GUI ActiveX control. The larger the box, the greater the scale. You should calculate values that give you an initial view suitable for your application.
One minute of latitude equals one nautical mile. One degree of latitude equals 60 miles. However, the distance for one degree of longitude varies depending upon the latitude. The farther north (or south) of the equator, the shorter the longitudinal distance. Since I merely subtract or add two degrees to or from the original longitude (regardless of latitude) to create the boundaries, the size of the captured area (and therefore the scale) may vary. But, for the purposes here, it doesn’t make much difference.
If you want a more detailed image, then use shorter distances (longitude and latitude) for the boundaries. Do the reverse for larger-scale views.
Note: The boundaries of bbox
, the iFrame parameters and the ActiveX control options all affect the look of the map embedded in the GUI. Play with these options to determine the best look for your application. For example, the OpenStreetMap.org map includes special links at the bottom of each embedded map. By using a smaller ActiveX control, those links remain out of view—unless I pull down the scrollbar on the right. (I’ve included the copyright as a link outside of the ActiveX control.)
The values for the WhereIs[]
array come from the data returned by the GetLocation(IPFind) function:
Return [Location,MapLink,Map1,Map2]
Location or WhereIs[1]
contains the IP location text. MapLink or WhereIs[2]
holds the URL for the OpenStreetMap.org site. Map1 or WhereIs[3]
saves the parsed latitude and Map2 or WhereIs[4]
the longitude. See “Use ActiveX Control to Embed World Maps in AutoHotkey GUI” for more information on building links in the GetLocation(IPFind) function.
Map Operation
Once loaded, the OpenStreetMap.org interactive map operates intuitively. Scroll the mouse wheel in or out while hovering the mouse cursor over the map to zoom in or out, respectively. Hold down the left mouse button and drag to reposition the map.
Tip: Remember to make the Windows Registry IE compatibility change discussed in “Embed Google Maps in an AutoHotkey GUI (No API Required!).” The script includes code (the AutoHotkey commands RegRead and RegWrite) making the change automatic, but it only needs to run once. After that first load, you can delete or comment-out the code—although leaving it in doesn’t hurt.
The IPFindOpenStreetMap.ahk script:
RegRead,KeyValue,HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION,AutoHotkey.exe
If ErrorLevel
RegWrite, REG_DWORD,HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION,AutoHotkey.exe,11001
HTML1 := "<div style='width: 100%'><iframe width='100%' height='225' frameborder='0' scrolling='no' marginheight='0' marginwidth='0' src='https://www.openstreetmap.org/export/embed.html?bbox="
HTML2 := "&layer=cyclemap' style='border: 1px solid black'></iframe></div>"
Return
^!i::
OldClipboard:= ClipboardAll
Clipboard:= ""
Send, ^c ;copies selected text
ClipWait 0
If ErrorLevel
{
MsgBox, No Text Selected!
Return
}
CountIP := 1
Next := 1
Loop
{
FoundPos := RegExMatch(Clipboard, "\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b" , ipaddress%CountIP%, Next)
Next := FoundPos + StrLen(ipaddress%CountIP%)
If FoundPos = 0
Break
CountIP++
}
Gui, +AlwaysOnTop
If IPAddress1
{
CountIP--
Loop, %CountIP%
{
CheckIP := ipaddress%A_Index%
WhereIs := GetLocation(CheckIP)
; For latitude, longitude map
MapEmbed := HTML1 . WhereIs[4]-2 . "," . WhereIs[3]-3 . "," . WhereIs[4]+2 . "," . WhereIs[3]+3 . "&marker=" . WhereIs[3] . "," . WhereIs[4] . HTML2
FileDelete, %A_ScriptDir%\OpenStreetMapEmbed.html
FileAppend , %MapEmbed%, %A_ScriptDir%\OpenStreetMapEmbed.html
WhereIs[1] := StrReplace(WhereIs[1],"Postal code","`rPostal code:`t")
WhereIs[1] := StrReplace(WhereIs[1],"Region","`rRegion/State:")
WhereIs[1] := StrReplace(WhereIs[1],"Country","`rCountry:`t`t")
WhereIs[1] := StrReplace(WhereIs[1],"State:","State:`t")
WhereIs[1] := StrReplace(WhereIs[1],"Continent","`rContinent:`t")
WhereIs[1] := StrReplace(WhereIs[1],"Metro code","`rMetro code:`t")
WhereIs[1] := StrReplace(WhereIs[1],"City","`rCity:`t`t")
WhereIs[1] := StrReplace(WhereIs[1],"Coordinates","`rCordinates:`t")
Gui, Add, Text, xm section, % CheckIP . WhereIs[1]
Gui Add, ActiveX, ys x250 w225 h175 vWB%A_Index%, Shell.Explorer
FilePathName := A_ScriptDir . "\OpenStreetMapEmbed.html"
WB%A_Index%.Navigate(FilePathName)
Gui, Add , Link, xs yp+120, % "<a href=""https://tools.keycdn.com/geo?host=" . CheckIp . """>IP Data" . "</a>"
; For latitude, longitude map link
Gui, Add, Link, yp+15, % WhereIs[2]
Gui, Add, Link, yp+15, <a href="https://www.openstreetmap.org/copyright">© OpenStreetMap contributors</a>
}
}
Else
WhereIs := "No IPs Found!"
Clipboard := OldClipboard
Gui, Add, Button,xm section, Close
Gui, Show,,IP Locations OpenStreetMap (Scroll to zoom)
Return
GetLocation(findip)
{
UrlDownloadToFile, % "https://tools.keycdn.com/geo?host=" . findip, iplocate
IPsearch := "https://tools.keycdn.com/geo?host=" . findip
whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
whr.Open("GET", IPsearch)
whr.Send()
sleep 100
version := whr.ResponseText
RegExMatch(version, "s)Location</p>(.*?)Time</dt>", Location)
FileRead, version2, iplocate
RegExMatch(version, "Coordinates</dt><dd class=""col-8 text-monospace"">(.*?) \(lat\) / (.*?)\(long\)", Map)
Map := Map1 . "," . Map2
; For OpenStreetMap
MapLink := "<a href=""https://www.openstreetmap.org/?mlat=" . map1 . "&mlon=" . map2 . "#map=5/" . Map . "&layers=C"">Go to larger map" . "</a>"
; MapGet := "https://www.openstreetmap.org/?mlat=" . map1 . "&mlon=" . map2 . "#map=5/" . Map1 . "/" . Map2
; Strip out HTML tags
Location := RegExReplace(Location1,"<.+?>")
; For OpenStreetMap
Return [Location,MapLink,Map1,Map2]
}
ButtonClose:
WinClose
Return
GuiClose:
Gui, Destroy
Return
Click the Follow button at the top of the sidebar on the right of this page for e-mail notification of new blogs. (If you’re reading this on a tablet or your phone, then you must scroll all the way to the end of the blog—pass any comments—to find the Follow button.)

This post was proofread by Grammarly
(Any other mistakes are all mine.)
(Full disclosure: If you sign up for a free Grammarly account, I get 20¢. I use the spelling/grammar checking service all the time, but, then again, I write a lot more than most people. I recommend Grammarly because it works and it’s free.)
Find my AutoHotkey books at ComputorEdge E-Books!
Find quick-start AutoHotkey classes at “Robotic Desktop Automation with AutoHotkey“!
[…] by Google again (see my “Switched IPFind.ahk to OpenStreetMap.org for Reliable AutoHotkey GUI Map Embedding” blog), I wanted to find an alternative source for the same […]
LikeLike