Windows Form中使用GoogleMap
儘管GoogleMap在Web上的應用已經很廣泛了,甚至現在都已經開始支援Flash了,但是在桌面應用程式的應用還是很少見,這幾天在網路上Google了一下發現網路上有個免費的元件GMap.NET可以讓我們很輕鬆的開發GoogleMap的桌面應用程式,GMap.NET不但支援NET,而且還是開放原始碼提供人家下載,在這裡講了這個多的GMap.NET的好處並不是要教大家使用GMap.NET,因為小弟不才,與其要看他們的原始碼(太複雜了,看完我頭髮也白了),不如我自己寫。
由於GoogleMap開放的API並沒有特地給NET使用的,因此唯一的方向就是使用WebBrowser嵌入到Windwos程式當中,但是這樣一來又有幾個方向要思考了。
本機端的方式,如果資料庫在遠端,那麼就使用WebService來呼叫,資料庫在本機端的話那就好辦了,下面文章中我會說明如何在Windows AP嵌入WebBrowser並且互相傳値。
接下來我要開始說明本文標題的程式說明,下面的程式並無對資料庫進行儲取,但是相信大家看完以下程式後,你就可以寫出資料庫的應用了。
1. 先寫一個HTML檔,並將此檔案屬性調整為內嵌資源,這樣等等才可以讀取的到該檔案,這個檔案主要的目的是要嵌入WebBrowser當中顯示用的,語法如下。
2. 接下來就是要將HTML嵌入WebBrowser當中,語法如下。
3. 在Winform當中撰寫出要給javascript呼叫的Method和要呼叫javascript呼叫的Function
4. 看起來似乎大功告成了,但是執行下去卻出現JavaScript的錯誤訊息(下圖),window.external的功用是用來控制視窗的操作,但就錯誤訊息看來,JavaScript似乎跟它不熟。因此只好網路上找答案了。
MSDN當中說到 WebBrowser.ObjectForScripting 屬性主要的功能是【取得或設定指令碼可存取的物件,這個指令碼包含在 WebBrowser 控制項中所顯示的 Web 網頁內。】
您可以將這個屬性設為任意 COM-Visible 物件,以讓指令碼可以使用這個物件的公用屬性和方法。 您可以使用 ComVisibleAttribute 標記類別,以讓該類別 COM-Visible。
若要從用戶端應用程式程式碼呼叫 Web 網頁中所定義的函式,請使用可從 Document 屬性中擷取之 HtmlDocument 物件的 HtmlDocument.InvokeScript 方法。
這句話的意思就是要我們在Class上面加上[System.Runtime.InteropServices.ComVisibleAttribute(true)],但是除了這個以外我們還要在Class上面加上[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]和webBrowser1.ObjectForScripting = this;這樣這個功能才可正常Work。
最後產生的結果如下圖所示。
WinFormGoogleMap.zip,2017.06.01將檔案搬移到Github上,請到此處下載範例檔案。
由於GoogleMap開放的API並沒有特地給NET使用的,因此唯一的方向就是使用WebBrowser嵌入到Windwos程式當中,但是這樣一來又有幾個方向要思考了。
1. 首先要考慮到的是這支AP的功能性為何?個人版的還是網路版的。
2. 是不是要進行資料庫儲取?如果有的話,那資料庫是遠端的還是本機的?
2. 是不是要進行資料庫儲取?如果有的話,那資料庫是遠端的還是本機的?
就先拿遠端來說明,一開始我在考慮遠端的時候就直接先聯想到直接採用Web的開發方式,先做出一個WebSite,在來將這個WebSite嵌入到WebBrowser當中就好了。但是這個方式在我實際進行測試後發現可行性不太高(會有許多問題產生,首先要面對的第一個問題就是showdialog會另外開啟一個IE瀏覽器的視窗,這可不是我們樂見的,會有其他問題的產生),因此這種方式我就放棄了,因此只剩下另外一種方法,使用WebService來讓Windows AP呼叫,那們這個解決方案就要合併下面本機來執行了。
本機端的方式,如果資料庫在遠端,那麼就使用WebService來呼叫,資料庫在本機端的話那就好辦了,下面文章中我會說明如何在Windows AP嵌入WebBrowser並且互相傳値。
接下來我要開始說明本文標題的程式說明,下面的程式並無對資料庫進行儲取,但是相信大家看完以下程式後,你就可以寫出資料庫的應用了。
1. 先寫一個HTML檔,並將此檔案屬性調整為內嵌資源,這樣等等才可以讀取的到該檔案,這個檔案主要的目的是要嵌入WebBrowser當中顯示用的,語法如下。
<!DOCTYPE html> <html> <head> <style type="text/css"> body { font-family: %u5FAE%u8EDF%u6B63%u9ED1%u9AD4,Arial Unicode MS; font-size: 12px; } </style> <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script> </head> <body onload="initialize()"> <table style="width: 100%"> <tr> <td style="width: 100%; height: 450px;"> <div id="map_canvas" style="width: 100%; height: 450px;"> </div> </td> </tr> <tr> <td> WebBrowser %u547C%u53EB Windows Form Methods :<br /> <input type="text" id="input_name" value="Lawrence" /> <input type="button" value="Hello" onclick="Hello()" /> </td> </tr> </table> </body> <script type="text/javascript"> var map; function initialize() { var myLatlng = new google.maps.LatLng(-34.397, 150.644); var myOptions = { zoom: 8, center: myLatlng, mapTypeId: google.maps.MapTypeId.ROADMAP } map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); google.maps.event.addListener(map, 'click', function(event) { //呼叫Windows AP的Method window.external.SetPoint(event.latLng.lat(), event.latLng.lng()); }); } function Hello() { //呼叫Windows AP的Method window.external.CallMessageBox(document.getElementById('input_name').value); } //提供Windows AP呼叫的Funtion function AddMarker(lat, lng) { var marker = new google.maps.Marker({ position: new google.maps.LatLng(lat, lng), map: map, title: "Hello World!" }); } </script> </html>
2. 接下來就是要將HTML嵌入WebBrowser當中,語法如下。
private void Form2_Load(object sender, EventArgs e) { //WinForm.Resource1.test =>為HTML檔的本機資源 webBrowser1.DocumentText = WinForm.Resource1.test; }
3. 在Winform當中撰寫出要給javascript呼叫的Method和要呼叫javascript呼叫的Function
//javascript呼叫的Method public void CallMessageBox(string message) { MessageBox.Show(message); } //javascript呼叫的Method public void SetPoint(string lat, string lng) { this.textBox_Lat.Text = lat; this.textBox_Lng.Text = lng; } //javascript呼叫的Function private void button_CallWebBrowser_Click(object sender, EventArgs e) { if (!string.IsNullOrEmpty(this.textBox_Lat.Text.Trim()) && !string.IsNullOrEmpty(this.textBox_Lng.Text.Trim())) this.webBrowser1.Navigate("javascript:AddMarker('" + this.textBox_Lat.Text.Trim() + "','" + this.textBox_Lng.Text.Trim() + "');void(0);"); else MessageBox.Show("Lat && Lng 不得為空!!"); }
4. 看起來似乎大功告成了,但是執行下去卻出現JavaScript的錯誤訊息(下圖),window.external的功用是用來控制視窗的操作,但就錯誤訊息看來,JavaScript似乎跟它不熟。因此只好網路上找答案了。
MSDN當中說到 WebBrowser.ObjectForScripting 屬性主要的功能是【取得或設定指令碼可存取的物件,這個指令碼包含在 WebBrowser 控制項中所顯示的 Web 網頁內。】
使用這個屬性,可啟用 WebBrowser 控制項所裝載之 Web 網頁與包含 WebBrowser 控制項之應用程式間的通訊。 這個屬性可讓您整合動態超文字標記語言 (DHTML) 程式碼與用戶端應用程式程式碼。 指定給這個屬性的物件可讓 Web 網頁指令碼做為 window.external 物件,這個物件是為了存取主應用程式而提供的內建 DOM 物件。
您可以將這個屬性設為任意 COM-Visible 物件,以讓指令碼可以使用這個物件的公用屬性和方法。 您可以使用 ComVisibleAttribute 標記類別,以讓該類別 COM-Visible。
若要從用戶端應用程式程式碼呼叫 Web 網頁中所定義的函式,請使用可從 Document 屬性中擷取之 HtmlDocument 物件的 HtmlDocument.InvokeScript 方法。
這句話的意思就是要我們在Class上面加上[System.Runtime.InteropServices.ComVisibleAttribute(true)],但是除了這個以外我們還要在Class上面加上[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]和webBrowser1.ObjectForScripting = this;這樣這個功能才可正常Work。
最後產生的結果如下圖所示。
本文附件 :
留言
張貼留言
您好,我是 Lawrence,這裡是我的開發筆記的網誌,如果你對我的文章有任何疑問或者有錯誤的話,歡迎留言讓我知道。