Introduction
My Article GMaps v1.1.12 - Google Maps/Routing/StreetView All-in-1 was written in Dec.2014, and worked well. Moreover, the community has awarded it as "Best VB.NET Article of December 2014 (First Prize)". Thanks.
But since Dec.2015, Google Maps JavaScript API applications require authentication, and the program stopped working properly (in "Route" Views, Directions blue line and Text Directions Panel are not shown), because the HTML/JavaScript file runs under the control of the Visual Studio's WebBrowser, which is, by default, Internet Explorer version 7, and that's not enough for the requirements.
Something had to be done. Initially, for my own applications, I got an API Key and proceeded to manual changes in the Registry, etc.
But it was necessary to automate the processes in the aforecited Article's Component, and first I thought to replace the WebBrowser by solutions like Gecko or Awesomium.
In both cases, the implementation of the Engine would cause a much heavier program, and code conversion would be a huge task. So I chose to emulate the WebBrowser to a IE higher version. This involves:
- Writing a Value to the Registry Key
HKEY_CURRENT_USER
\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION
Instead of HKEY_CURRENT_USER
, HKEY_
LOCAL_MACHINE could also be used, but that requires high permissions. HKCU is enough.
The Value is:
- Ensure that the Value is written at the beginning of the Application and deleted when the Application ends (don't fill the Registry with trash).
The best solution is to use the Startup and Shutdown events of My.Application
class, however this cannot be done in a Class Library like the UserControl DLL of the aforementioned article, it's allowed just at WinForms Application level.
Then, and because the DLL Component is written in VB, for any VB Application, instead of using the DLL Component, it's better to insert only one file, GMapsVB.vb (with four classes, including the Component) in the WinForms Project. After rebuilding, the Component will be available in the Toolbox. Hence the reason to write a new Article and not just an Update to the original article.
And for those using other languages (including VB), I also made available a UserControl DLL Project (GMapsX). However, with one limitation: the My.Application Startup and Shutdown events become Methods of the DLL Component and will have to be manually called by the Startup Form events, respectively, Load
and [ FormClosing
(VB.NET) or OnFormClosing
(C#) ].
Prerequisites
- Visual Studio 2012 or later.
- To use the new VB Class file or the DLL, the Projects must target to .NET Framework 4 (Client Profile).
- Internet Explorer 10 or 11 must be installed. In Windows 7, prior to install last IE version, update it to Service Pack 1 (SP1).
- To acquire full information on the UserControl, see the article GMaps v1.1.12 - Google Maps/Routing/StreetView All-in-1, where you can also download the Documentation. In the present article we will only deal with the differences introduced and the new code.
- The minimum screen resolution is 1360x768
The Google Maps API Key
The file in which the key has to be placed, which should be present in the executable's Folder, is located in:
...\GMaps_VB\GMapsVB_Demo\GMapsVB_Demo\bin\Release\GMaps1.html , or,
...\GMaps_X\GMapsX_Demo\GMapsX_Demo\bin\Release\GMaps1.html
I don't know the true mechanisms behind the Google Maps API Key, its authentication, its interaction with the Operating System, etc., since the documentation I found, so far, is not very helpful. But the truth is that in most of the machines where I experienced the programs generated by these Projects, everything worked fine with the provided file GMaps1.html, as-is, i.e., without API Key.
"Work fine" means showing Directions blue line and Text Directions Panel in "Route" Views.
Therefore, to start, try running the chosen Project as-is. Works fine? Great!
But if not:
Using the code
1) For GMapsVB, in a new or existing VB Project:
- In Solution Explorer -> Application tab -> change the Target framework to .NET Framework 4 (Client Profile is lighter)
- Insert the file GMapsVB.vb: Visual Studio Menu PROJECT -> Add Existing Item... -> GMapsVB.vb (select from ...\GMaps_VB\GMapsVB_Demo\GMapsVB_Demo\GMapsVB.vb). By selecting this one, two more files will be transferred: GMapsVB.Designer.vb and GMapsVB.resx
- Copy the file GMaps1.html to your Project Startup Folder (...\...\bin\Debug or ...\...\bin\Release, depending on Configuration Manager settings)
- Build (or Rebuild) the Project. A new
GMapsVB
icon will appear in the Toolbox.
GMapsVB.vb contains four Classes:
1) Class GMapsVB - Is the UserControl and therefor must be the first Class.
The only differences to the original v1.1.12 GMaps is that: a) The assembly is not COM-visible, and b) GMaps.html file has changed to GMaps1.html. So the lines
WBrowser.ObjectForScripting = Me
WBrowser.Navigate(Application.StartupPath & "\GMaps.html")
have changed to
WBrowser.Navigate(Application.StartupPath & "\GMaps1.html")
2) Class MyApplication - Defined within Namespace My
Controls the Startup and Shutdown events, which are raised when the Application starts and ends. Also, contains all the code needed to perform the Emulation operations - Get information, Write and Delete the Registry Key Value. Also calls the _InfoBox Form (defined in the next Class).
- The CONFIGURATION VARIABLES can be modified, but it is advisable to keep them with the default values until everything works fine.
_Process_My_Events
- Keep True while Emulation is required (who knows, one day Microsoft can change the WebBrowser defaults...).
_Default_Emul_Version
- Keep 0, unless there is some advantage in using a previous version.
_Verbose_Mode
- Change it to False only when everything is OK, i.e., "Route" Views shows the Directions blue line and the Text Directions Panel.
Namespace My
Partial Friend Class MyApplication
Public _Process_My_Events As Boolean = True Public _Default_Emul_Version As Byte = 0 Public _Verbose_Mode As Boolean = True
Internal variables. Don't change. Meaning of the _InfoBox message's BackColor:
- Lime: OK. The WebBrowser was emulated for the latest version available.
- Yellow: Warning. The WebBrowser was emulated for a working version, but not the latest available.
- Orange: Danger. The WebBrowser was emulated for a (predictably) inadequate version.
- Red: Error. The WebBrowser was not emulated.
Public OS_64bit As Boolean
Public App_64bit As Boolean
Public RegistryBase As String
Public RegistrySubKey As String
Public ProgName As String
Public IE_Version As String = ""
Public IE_MajorVersion As Byte = 0
Public Emulation As Byte = 0
Public Error_Color As Byte = 3 Public StartupEvent As Boolean
If Startup event has to be processed:
GetInfo()
collects some info and sets up the internal variables.
- If no errors are detected, the Registry Key Value is written. Variable
Emulation
contains a Major Version (i.e., 11, 10,..) and is multiplied by 1000...
- And (if applicable) the Form _InfoBox is shown.
Private Sub MyApplication_Startup(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.StartupEventArgs) Handles Me.Startup
If _Process_My_Events Then
StartupEvent = True
GetInfo()
If Error_Color < 3 Then Registry.SetValue(RegistryBase & RegistrySubKey, _
ProgName, Emulation * 1000, RegistryValueKind.DWord)
End If
ShowInfoBox()
End If
End Sub
If Shutdown event has to be processed:
- If the Registry Key Value was written, it is deleted,
- And (if applicable) the Form _InfoBox is shown.
Private Sub MyApplication_Shutdown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shutdown
If _Process_My_Events Then
StartupEvent = False
If Error_Color < 3 Then Dim Key As RegistryKey = Registry.CurrentUser.OpenSubKey(RegistrySubKey, True)
Key.DeleteValue(ProgName)
End If
ShowInfoBox()
End If
End Sub
GetInfo()
gets installed IE version and sets some variables, including Emulation
(major version to emulate) and Error_Color
, which controls the quality of the Action to be taken.
Private Sub GetInfo()
OS_64bit = Environment.Is64BitOperatingSystem
App_64bit = Environment.Is64BitProcess
Dim FileIE As String = Environment.GetFolderPath(Environment.SpecialFolder.System) & "\ieframe.dll"
If File.Exists(FileIE) Then
Dim V = FileVersionInfo.GetVersionInfo(FileIE)
IE_Version = V.ProductVersion
IE_MajorVersion = V.FileMajorPart
Error_Color = 0
End If
RegistryBase = Registry.CurrentUser.Name & "\"
RegistrySubKey = "SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION"
ProgName = My.Application.Info.AssemblyName & If(Debugger.IsAttached, ".vshost", "") & ".exe"
If IE_MajorVersion > 0 Then If IE_MajorVersion <= 9 Then Error_Color = 2
End If
End If
If _Default_Emul_Version = 0 OrElse _Default_Emul_Version = IE_MajorVersion Then
Emulation = IE_MajorVersion
Else
If _Default_Emul_Version > IE_MajorVersion OrElse _Default_Emul_Version < 7 Then
Error_Color = 3
Else
Emulation = _Default_Emul_Version
Error_Color = If(_Default_Emul_Version < 10, 2, 1)
End If
End If
End Sub
Form _InfoBox is displayed, when requested, but also when an Error or Danger status was detected.
Private Sub ShowInfoBox()
If _Verbose_Mode OrElse Error_Color > 1 Then
Dim F1 As New _InfoBox
F1.ShowDialog()
F1.Dispose()
End If
End Sub
End Class
End Namespace
3) Class _InfoBox - Is a Form and has two main blocks: DESIGNER and CODE.
- DESIGNER is generated by the IDE. Nothing to say about this.
- CODE prepares the info to show, based on the Internal Variables defined in
Class MyApplication
, which, within this Class, is visible as Application
, of type Friend ReadOnly Property Application
, so the variables must be qualified with prefix My.Application
.
Variable .StartupEvent
indicates the calling Event: Startup (=True
) or Shutdown (=False
)
Private Tab_Colors() As Color = {Color.Lime, Color.Yellow, Color.Orange, Color.Red}
Private Sub _InfoBox_Load(sender As Object, e As EventArgs) Handles MyBase.Load
With My.Application
If .StartupEvent Then
A2.Text = "Startup"
End If
If .OS_64bit = False Then
B2.Text = "32 bits"
End If
If .App_64bit = False Then
C2.Text = "32 bits"
End If
D2.Text = .RegistryBase & .RegistrySubKey
E2.Text = .ProgName
If .IE_MajorVersion > 0 Then
F2.Text = .IE_MajorVersion.ToString
F3.Text = .IE_Version
End If
If ._Default_Emul_Version > 0 Then
G2.Text = ._Default_Emul_Version
End If
H2.BackColor = Tab_Colors(.Error_Color)
If .Error_Color = 3 Then
H2.ForeColor = Color.Yellow
If .IE_MajorVersion = 0 Then
H2.Text = "Internet Explorer not detected..."
Else
H2.Text = "Invalid Default version (" & _
._Default_Emul_Version.ToString & ")"
End If
Else
If .StartupEvent Then
H2.Text &= " " & .Emulation.ToString
Else
H2.BackColor = Tab_Colors(0)
H2.Text = "Registry Value deleted..."
End If
End If
End With
End Sub
Private Sub bClose_Click(sender As Object, e As EventArgs) Handles bClose.Click
Me.Close()
End Sub
Output examples:
4) Class _List - Is the List Form of the original GMaps UserControl and has two main blocks: DESIGNER and CODE.
- The only difference is that the Form's Property
FormBorderStyle
was changed from FixedToolWindow
to SizableToolWindow
.
Output looks like this:
2) For GMapsX - Other languages (VB inc.):
Project GMapsX produces an UserControl DLL (GMapsX.dll) which must be copied to your Application's Startup Folder and referenced by your WinForms Project.
The file GMaps1.html must also be copied to your Application's Startup Folder.
Compared to GMapsVB, GMapsX only differs in the implementation of Startup
and Shutdown
events, which can not be defined, as My.Application
events, in a Class Library Project. So, Class MyApplication
is supressed and the events are to be controlled by the UserControl in Class GMapsX
:
1) New Variables are added:
Public Shared _Process_My_Events As Boolean = True Public Shared _Default_Emul_Version As Byte = 0 Public Shared _Verbose_Mode As Boolean = True Public Shared OS_64bit As Boolean
Public Shared App_64bit As Boolean
Public Shared RegistryBase As String
Public Shared RegistrySubKey As String
Public Shared ProgName As String
Public Shared IE_Version As String = ""
Public Shared IE_MajorVersion As Byte = 0
Public Shared Emulation As Byte = 0
Public Shared Error_Color As Byte = 3 Public Shared StartupEvent As Boolean
2) New Properties are created, to allow the change of CONFIGURATION VARIABLES:
Public WriteOnly Property Process_My_Events As Boolean
Set(value As Boolean)
_Process_My_Events = value
End Set
End Property
Public WriteOnly Property Default_Emul_Version As Byte
Set(value As Byte)
_Default_Emul_Version = value
End Set
End Property
Public WriteOnly Property Verbose_Mode As Boolean
Set(value As Boolean)
_Verbose_Mode = value
End Set
End Property
3) And the Startup
and Shutdown
events become Methods (renamed Application_Startup
and Application_Shutdown
):
Public Sub Application_Startup()
If _Process_My_Events Then
StartupEvent = True
GetInfo()
If Error_Color < 3 Then Registry.SetValue(RegistryBase & RegistrySubKey, _
ProgName, Emulation * 1000, RegistryValueKind.DWord)
End If
ShowInfoBox()
End If
End Sub
Public Sub Application_Shutdown()
If _Process_My_Events Then
StartupEvent = False
If Error_Color < 3 Then Dim Key As RegistryKey = Registry.CurrentUser.OpenSubKey(RegistrySubKey, True)
Key.DeleteValue(ProgName)
End If
ShowInfoBox()
End If
End Sub
- Notice that above Methods must be called by the Startup Form events, respectively,
Load
and [ FormClosing
(VB.NET) or OnFormClosing
(C#) ]. See examples:
private void Form1_Load(object sender, EventArgs e)
{
GMapsX1.Process_My_Events = true; GMapsX1.Default_Emul_Version = 0; GMapsX1.Verbose_Mode = true; GMapsX1.Application_Startup(); }
protected override void OnFormClosing(FormClosingEventArgs e)
{
GMapsX1.Application_Shutdown(); }
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
GMapsX1.Process_My_Events = True GMapsX1.Default_Emul_Version = 0 GMapsX1.Verbose_Mode = True GMapsX1.Application_Startup() End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
GMapsX1.Application_Shutdown() End Sub
Placing the Component on the Toolbox
If you right-click the Toolbox -> Choose Items... -> Browse (...\...\GMapsX.dll) -> Open , and you receive a message [ There are no components in '...\...\GmapsX.dll' that can be placed on the toolbox. ], then,
- With File Explorer, Open the Folder where GMapsX.dll resides.
- Drag GMapsX.dll and Drop it into the tab (in Toolbox) where you want to place it.
History
04.Jul.2016 - First posted.