从TWebBrowser的GoogleMaps获取纬度经度
我将地址传递给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框为空白。我是否将错误的变量传递给他们?
为了获得您的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;
我添加了你的建议,但是我把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
对不起,DOM节点id在大多数浏览器中都区分大小写。改变所有的经纬度为小写..“lat”,“lng” –
返回“function(){return a}”的相同结果这里是我添加到HTML的地方: 'constructor TViewMaps.create(AOwner: TComponent; AAddress:string); 开始 继承创建(AOwner); fAddress:= AAddress; // fAddress现在存储为变量 end; 常量 HTMLStr:AnsiString类型= ' '+ '
' + “'+ ''+ ''+ ''+ ''+' – Hackbrew
您可以使用google.maps.Marker#getPosition
从标记中返回LatLng对象。
然后,您可以使用LatLng#lat
和LatLng#lng
从google.maps.LatLng
对象中检索坐标。
这并不能解决在OP的Delphi代码中获取值 –
@约翰伊斯利 - 得到它的工作,我不得不添加()在geometry.location.lat结束,但我只在我的OnShow事件中的HtmlElement:=之后添加类似ShowMessage('Hello')的消息行时才得到结果。否则结果是空的。为什么? – Hackbrew