2016-05-13 128 views
2

我將地址傳遞給Google地圖,我可以顯示地圖並在TWebBrowser中放置一個標記,但我也想將緯度和經度座標返回給我Delphi Win32應用程序。我需要添加什麼?從TWebBrowser的GoogleMaps獲取緯度經度

private 
    { Private declarations } 
    HTMLWindow2: IHTMLWindow2; 
    fAddress: String; 
    public 
    { Public declarations } 
    constructor create(AOwner: TComponent; AAddress: string); reintroduce; 
    end; 

var 
    ViewMaps      : TViewMaps; 
    Flags      : OLEVariant; 
    address, MapType    : string; 
    Title, Lat, Lng    : AnsiString; 

implementation 

Uses ShredMain, ActiveX, MaintForm_u, NewSchedule; 

{$R *.dfm} 

constructor TViewMaps.create(AOwner: TComponent; AAddress: string); 
begin 
    inherited create(AOwner); 
    fAddress := AAddress; // fAddress is now stored to form variable 
end; 

const 
HTMLStr: AnsiString = 
'<html> '+ 
'<head> '+ 
'<meta name="viewport" content="initial-scale=1.0, user-scalable=yes" /> '+ 
//'<meta http-equiv="X-UA-Compatible" content="IE=edge" />'+ 
'<input type="hidden" id="lat" value="" />'+ 
'<input type="hidden" id="lng" value="" />'+ 
''+ 
'<script type="text/javascript" src="http://maps.google.com/maps/api/js?v=3.22"></script> '+ 
'<script type="text/javascript"> '+ 
''+ 
''+ 
' var geocoder; '+ 
' var map; '+ 
' var trafficLayer;'+ 
' var bikeLayer;'+ 
' var markersArray = [];'+ 
''+ 
''+ 
' function initialize() { '+ 
' geocoder = new google.maps.Geocoder();'+ 
' var latlng = new google.maps.LatLng(40.714776,-74.019213); '+ 
' var myOptions = { '+ 
'  zoom: 11, '+ 
'  center: latlng, '+ 
'  mapTypeId: google.maps.MapTypeId.ROADMAP '+ 
' }; '+ 
' map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); '+ 
' trafficLayer = new google.maps.TrafficLayer();'+ 
' bikeLayer = new google.maps.BicyclingLayer();'+ 
' map.set("streetViewControl", false);'+ 
' } '+ 
''+ 
''+ 
' function codeAddress(address) { '+ 
' if (geocoder) {'+ 
'  geocoder.geocode({ address: address}, function(results, status) { '+ 
'  if (status == google.maps.GeocoderStatus.OK) {'+ 
'   map.setCenter(results[0].geometry.location);'+ 
'   PutMarker(results[0].geometry.location.lat(), results[0].geometry.location.lng(), results[0].geometry.location.lat()+","+results[0].geometry.location.lng());'+ 
'   document.getElementById("lat").value = results[0].geometry.location.lat;'+ 
'   document.getElementById("lng").value = results[0].geometry.location.lng;'+ 
'  } else {'+ 
'   alert("Geocode was not successful for the following reason: " + status);'+ 
'  }'+ 
'  });'+ 
' }'+ 
' }'+ 
''+ 
''+ 
' function GotoLatLng(Lat, Lang) { '+ 
' var latlng = new google.maps.LatLng(Lat,Lang);'+ 
' map.setCenter(latlng);'+ 
' PutMarker(Lat, Lang, Lat+","+Lang);'+ 
' }'+ 
''+ 
''+ 
'function ClearMarkers() { '+ 
' if (markersArray) {  '+ 
' for (i in markersArray) { '+ 
'  markersArray[i].setMap(null); '+ 
' } '+ 
' } '+ 
'} '+ 
''+ 
' function PutMarker(Lat, Lang, Msg) { '+ 
' var latlng = new google.maps.LatLng(Lat,Lang);'+ 
' var marker = new google.maps.Marker({'+ 
'  position: latlng, '+ 
'  map: map,'+ 
'  title: Msg+" ("+Lat+","+Lang+")"'+ 
' });'+ 
' markersArray.push(marker); '+ 
' }'+ 
''+ 
''+ 
' function TrafficOn() { trafficLayer.setMap(map); }'+ 
''+ 
' function TrafficOff() { trafficLayer.setMap(null); }'+ 
''+''+ 
' function BicyclingOn() { bikeLayer.setMap(map); }'+ 
''+ 
' function BicyclingOff(){ bikeLayer.setMap(null);}'+ 
''+ 
' function StreetViewOn() { map.set("streetViewControl", true); }'+ 
''+ 
' function StreetViewOff() { map.set("streetViewControl", false); }'+ 
''+ 
''+'</script> '+ 
'</head> '+ 
'<body onload="initialize()"> '+ 
' <div id="map_canvas" style="width:100%; height:100%"></div> '+ 
'</body> '+ 
'</html> '; 

procedure TViewMaps.OnShow(Sender: TObject); 
var 
    aStream: TMemoryStream; 
    HtmlElement: IHtmlElement; 
    sLat, sLng: string; 

begin 
    WebBrowser1.Navigate('about:blank'); 
    MemoAddress.Lines.Text := NewServiceForm.MapAddress; 
    if Assigned(WebBrowser1.Document) then 
    begin 
    aStream := TMemoryStream.Create; 
    try 
     aStream.WriteBuffer(Pointer(HTMLStr)^, Length(HTMLStr)); 
     aStream.Seek(0, soFromBeginning); 
     (WebBrowser1.Document as IPersistStreamInit).Load(TStreamAdapter.Create(aStream)); 
    finally 
     aStream.Free; 
    end; 
    HTMLWindow2 := (WebBrowser1.Document as IHTMLDocument2).parentWindow; 
    end; 

    while WebBrowser1.ReadyState <> READYSTATE_COMPLETE do // wait for google 
    begin 
    sleep(0); 
    application.processmessages; 
    end; 
    // 05/11/2016 - Show the address on the map 
    fAddress := StringReplace(StringReplace(Trim(fAddress), #13, ' ', [rfReplaceAll]), #10, ' ', [rfReplaceAll]); 

    HTMLWindow2.execScript(Format('codeAddress(%s)',[QuotedStr(fAddress)]), 'JavaScript'); 

    HtmlElement := (WebBrowser1.document as IHTMLDocument3).getElementById('lat'); 
    sLat := HtmlElement.getAttribute('value', 0); 
    HtmlElement := (WebBrowser1.document as IHTMLDocument3).getElementById('lng'); 
    sLng := HtmlElement.getAttribute('value', 0); 

    LatitudeEdit.Text := sLat; 
    LongitudeEdit.Text := sLng; 

end; 

我有緯度和LNG定義爲AnsiString類型,但板條和SLNG在我的OnShow中的事件局部定義爲String。經度和緯度的兩個Tedit框爲空白。我是否將錯誤的變量傳遞給他們?

+0

@約翰伊斯利 - 得到它的工作,我不得不添加()在geometry.location.lat結束,但我只在我的OnShow事件中的HtmlElement:=之後添加類似ShowMessage('Hello')的消息行時纔得到結果。否則結果是空的。爲什麼? – Hackbrew

回答

2

爲了獲得您的Delphi代碼中的座標,您需要將值存儲在html(DOM)中,然後從Delphi代碼中提取它們。首先,您可以創建隱藏字段的JavaScript值存儲在身體標記之間的HTML:

<input type="hidden" id="lat" value="0" /> 
    <input type="hidden" id="lng" value="0" /> 

然後在您的JavaScript函數,設置隱藏值:

document.getElementById("lat").value = results[0].geometry.location.lat; 
document.getElementById("lng").value = results[0].geometry.location.lng; 

即可獲得價值在你的Delphi應用程序中,使用類似於:

var 
    lat, lng: string; 
    HtmlElement: IHtmlElement; 
begin 
    HtmlElement := (Webbrowser1.document as IHTMLDocument3).getElementById('lat'); 
    lat := HtmlElement.getAttribute('value', 0); 
    HtmlElement := (Webbrowser1.document as IHTMLDocument3).getElementById('lng'); 
    lng := HtmlElement.getAttribute('value', 0); 
end; 

在這裏,我已經重寫了你的整個單元。請特別注意對HTMLStr常量的更改,特別是codeAddress函數,它使用標記來獲取緯度/經度值。

unit fmViewMaps; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs,OleCtrls, MSHTML, SHDocVw, StdCtrls; 

type 

    TLocation = Record 
    Lat: String; 
    Lng: String; 
    Result: string; 
    end; 

    TFrmViewMaps = class(TForm) 
    WebBrowser1: TWebBrowser; 
    LatitudeEdit: TEdit; 
    LongitudeEdit: TEdit; 
    procedure FormShow(Sender: TObject); 
    private 
    { Private declarations } 
    fAddress: string; 
    HTMLWindow2: IHTMLWindow2; 
    procedure LoadGoogleApi; 
    function GoogleApiReady: boolean; 
    procedure ExecuteScript(AScript: string); 
    function GetElementByID(AElementID: string): IHTMLElement; 
    function GetElementValue(ElementID: string): string; 
    function GetGeocode(Address: string): TLocation; 
    public 
    { Public declarations } 
    constructor create(AOwner: TComponent; AAddress: string); reintroduce; 
    end; 

var 
    FrmViewMaps: TFrmViewMaps; 

implementation 

uses ActiveX; 

{$R *.dfm} 

const 
HTMLStr: AnsiString = 
'<html> '+ 
'<head> '+ 
'<meta name="viewport" content="initial-scale=1.0, user-scalable=yes" /> '+ 
''+ 
'<script type="text/javascript" src="http://maps.google.com/maps/api/js? v=3.22"></script> '+ 
'<script type="text/javascript"> '+ 
''+ 
''+ 
' var geocoder; '+ 
' var map; '+ 
' var trafficLayer;'+ 
' var bikeLayer;'+ 
' var markersArray = [];'+ 
''+ 
''+ 
' function initialize() { '+ 
' geocoder = new google.maps.Geocoder();'+ 
' var latlng = new google.maps.LatLng(40.714776,-74.019213); '+ 
' var myOptions = { '+ 
'  zoom: 11, '+ 
'  center: latlng, '+ 
'  mapTypeId: google.maps.MapTypeId.ROADMAP '+ 
' }; '+ 
' map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); '+ 
' trafficLayer = new google.maps.TrafficLayer();'+ 
' bikeLayer = new google.maps.BicyclingLayer();'+ 
' map.set("streetViewControl", false);'+ 
' } '+ 
''+ 
''+ 
' function codeAddress(address) { '+ 
' if (geocoder) {'+ 
'  geocoder.geocode({ address: address}, function(results, status) { '+ 
'  if (status == google.maps.GeocoderStatus.OK) {'+ 
'   map.setCenter(results[0].geometry.location);'+ 
'   var myLatlng = new google.maps.LatLng(results[0].geometry.location.lat(), results[0].geometry.location.lng()); '+ 
'   var marker = new google.maps.Marker({ '+ 
'   position: myLatlng, '+ 
'   title: "", '+ 
'   map: map '+ 
'   }); '+ 
'  markersArray.push(marker); '+ 
'  document.getElementById("hiddenlat").value = myLatlng.lat(); '+ 
'  document.getElementById("hiddenlng").value = myLatlng.lng(); '+ 
' '+ 
'  } else {'+ 
'   document.getElementById("hiddenlat").value = "error"; '+ 
'   document.getElementById("hiddenlng").value = "error"; '+ 
'   alert("Geocode was not successful for the following reason: " + status);'+ 
'  }'+ 
'  });'+ 
' }'+ 
' }'+ 
''+ 
''+ 
''+ 
' function GotoLatLng(Lat, Lang) { '+ 
' var latlng = new google.maps.LatLng(Lat,Lang);'+ 
' map.setCenter(latlng);'+ 
' PutMarker(Lat, Lang, Lat+","+Lang);'+ 
' }'+ 
''+ 
''+ 
'function ClearMarkers() { '+ 
' if (markersArray) {  '+ 
' for (i in markersArray) { '+ 
'  markersArray[i].setMap(null); '+ 
' } '+ 
' } '+ 
'} '+ 
''+ 
' function PutMarker(Lat, Lang, Msg) { '+ 
' var latlng = new google.maps.LatLng(Lat,Lang);'+ 
' var marker = new google.maps.Marker({'+ 
'  position: latlng, '+ 
'  map: map,'+ 
'  title: Msg+" ("+Lat+","+Lang+")"'+ 
' });'+ 
' markersArray.push(marker); '+ 
' }'+ 
''+ 
''+ 
' function TrafficOn() { trafficLayer.setMap(map); }'+ 
''+ 
' function TrafficOff() { trafficLayer.setMap(null); }'+ 
''+''+ 
' function BicyclingOn() { bikeLayer.setMap(map); }'+ 
''+ 
' function BicyclingOff(){ bikeLayer.setMap(null);}'+ 
''+ 
' function StreetViewOn() { map.set("streetViewControl", true); }'+ 
''+ 
' function StreetViewOff() { map.set("streetViewControl", false); }'+ 
''+ 
''+'</script> '+ 
'</head> '+ 
'<body onload="initialize()"> '+ 
' <div id="map_canvas" style="width:100%; height:100%"></div> '+ 
'<input type="hidden" id="hiddenlat" value="0" />'+ 
'<input type="hidden" id="hiddenlng" value="0" />'+ 
'</body> '+ 
'</html> '; 


constructor TFrmViewMaps.create(AOwner: TComponent; AAddress: string); 
begin 
    inherited create(AOwner); 
    fAddress := AAddress; 
end; 

procedure TFrmViewMaps.LoadGoogleApi; 
var 
    aStream: TMemoryStream; 
begin 
    WebBrowser1.Navigate('about:blank'); //Set the location to an empty page 

    if Assigned(WebBrowser1.Document) then 
    begin 
    aStream := TMemoryStream.Create; //create a TStream to load the Page from the string 
    try 
     aStream.WriteBuffer(Pointer(HTMLStr)^, Length(HTMLStr)); 
     aStream.Seek(0, soFromBeginning); 
     (WebBrowser1.Document as IPersistStreamInit).Load(TStreamAdapter.Create(aStream)); 
    finally 
     aStream.Free; 
    end; 
    HTMLWindow2 := (WebBrowser1.Document as IHTMLDocument2).parentWindow; 
    end; 

    while WebBrowser1.ReadyState <> READYSTATE_COMPLETE do // wait for google 
    begin 
    sleep(0); 
    application.processmessages; 
    end; 

end; 

function TFrmViewMaps.GoogleApiReady: boolean; 
begin 
    result := (HTMLWindow2 <> nil); 
end; 

procedure TFrmViewMaps.ExecuteScript(AScript: string); 
begin 
    HTMLWindow2.execScript(AScript, 'JavaScript'); 
end; 

function TFrmViewMaps.GetElementByID(AElementID: string): IHTMLElement; 
begin 
    result := (WebBrowser1.Document as IHTMLDocument3).getElementByID(AElementID); 
end; 

function TFrmViewMaps.GetElementValue(ElementID: string): string; 
var 
    HtmlElement: IHTMLElement; 
begin 
    HtmlElement := GetElementByID(ElementID); 
    result := HtmlElement.getAttribute('value', 0); 
end; 

procedure RemoveInvalidGeoLookupChars(var AString: string); 
begin 
    AString := StringReplace(StringReplace(Trim(AString), #13, ' ', [rfReplaceAll]), #10, ' ', [rfReplaceAll]); 
    // remove invalid chars 
    AString := StringReplace(AString, #39, #32, [rfReplaceAll]); // single quotes 
    AString := StringReplace(AString, #34, #32, [rfReplaceAll]); // double quotes 
end; 

function TFrmViewMaps.GetGeocode(Address: string): TLocation; 
var 
    i: integer; 
begin 
    result.Lat := '0'; 
    result.Lng := '0'; 
    LatitudeEdit.text := '0'; 
    LongitudeEdit.text := '0'; 
    result.Result := 'OK'; 
    application.processmessages; 
    RemoveInvalidGeoLookupChars(address); 
    application.processmessages; 
    ExecuteScript(Format('codeAddress(%s)',[QuotedStr(address)])); 

    while (GetElementValue('hiddenlat') = '0') do 
    application.processmessages; 

    result.Lat := GetElementValue('hiddenlat'); 
    result.lng := GetElementValue('hiddenlng'); 
end; 

procedure TFrmViewMaps.FormShow(Sender: TObject); 
var 
    Location: TLocation; 
begin 
    LoadGoogleApi; 
    Location := GetGeoCode(fAddress); 
    LatitudeEdit.Text := Location.Lat; 
    LongitudeEdit.Text := Location.Lng; 
end; 

end. 

從另一種形式的地理編碼地址,使用的語法如下:

frmViewMaps:= TFrmViewMaps.create(self, 'One Microsoft Way, Redmond, WA 98052'); 
try 
    frmViewMaps.showmodal; 
finally 
    frmViewMaps.destroy; 
end; 
+0

我添加了你的建議,但是我把getElementByID改成了getElementById和document.getElementByID(「Lat」)。value = results [0 ] .geometry.location.lng;'to'document.getElementByID(「Lng」).value = results [0] .geometry.location.lng;'。 不是返回Lat和Lng值,而是給我「function(){return a}」給Lat,和「function(){return b}」給Lng。 – Hackbrew

+0

對不起,DOM節點id在大多數瀏覽器中都區分大小寫。改變所有的經緯度爲小寫..「lat」,「lng」 –

+0

返回「function(){return a}」的相同結果這裏是我添加到HTML的地方: 'constructor TViewMaps.create(AOwner: TComponent; AAddress:string); 開始 繼承創建(AOwner); fAddress:= AAddress; // fAddress現在存儲爲變量 end; 常量 HTMLStr:AnsiString類型= ' '+ ' ' + 「'+ ''+ ''+ ''+ ''+' – Hackbrew

1

您可以使用google.maps.Marker#getPosition從標記中返回LatLng對象。

然後,您可以使用LatLng#latLatLng#lnggoogle.maps.LatLng對象中檢索座標。

+0

這並不能解決在OP的Delphi代碼中獲取值 –