【问题标题】:Getting Latitude Longitude from GoogleMaps in TWebBrowser在 TWebBrowser 中从 GoogleMaps 获取纬度经度
【发布时间】:2016-05-13 18:15:19
【问题描述】:

我正在将地址传递给 Google 地图,并且能够在 TWebBrowser 中显示地图并放置标记,但我还试图将纬度和经度坐标返回到我的 Delphi Win32 应用程序。我需要添加什么?

  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;

我将 Lat 和 Lng 定义为 AnsiString,但 sLat 和 sLng 在我的 OnShow 事件中本地定义为 String。我的两个经度和纬度 Tedit 框是空白的。我是否将错误的变量传递给他们?

【问题讨论】:

  • @John Easley - 为了让它工作,我必须在geometry.location.lat 的末尾添加 (),但只有当我添加像 ShowMessage('Hello ') 在我的 OnShow 事件中的 HtmlElement := 之后。否则结果为空。为什么?

标签: javascript google-maps delphi


【解决方案1】:

为了在您的 Delphi 代码中获得可用的坐标,您需要将值存储在 html (DOM) 中,然后从您的 Delphi 代码中提取它们。首先,您可以创建隐藏字段以将 JavaScript 值存储在 HTML 中的 Body 标记之间:

  <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 函数,它使用标记来获取 lat/lng 值。

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; 更改为document.getElementByID("Lng").value = results[0].geometry.location.lng;。它不是返回 Lat 和 Lng 值,而是为 Lat 提供“function(){return a}”,为 Lng 提供“function(){return b}”。
  • 抱歉,DOM 节点 ID 在大多数浏览器中都区分大小写。将所有 lat/lng id 更改为小写.."lat", "lng"
  • 返回“function(){return a}”的结果相同...这是我添加到 HTML 的地方:constructor TViewMaps.create(AOwner: TComponent; AAddress: string); begin inherited create(AOwner); fAddress := AAddress; // fAddress is now stored to form variable end; const HTMLStr: AnsiString = '&lt;html&gt; '+ '&lt;head&gt; '+ '&lt;meta name="viewport" content="initial-scale=1.0, user-scalable=yes" /&gt; '+ '&lt;input type="hidden" id="lat" value="" /&gt;'+ '&lt;input type="hidden" id="lng" value="" /&gt;'+ ''+ '&lt;script type="text/javascript" src="http://maps.google.com/maps/api/js?v=3.22"&gt;&lt;/script&gt; '+
  • 这是我的 Javascript 在函数 codeAddress 中的一部分:... ' 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...
  • 这是我的 Delphi 代码的一部分:fAddress := StringReplace(StringReplace(Trim(fAddress), #13, ' ', [rfReplaceAll]), #10, ' ', [rfReplaceAll]); HTMLWindow2.execScript(Format('codeAddress(%s)',[QuotedStr(fAddress)]), 'JavaScript'); HtmlElement := (WebBrowser1.document as IHTMLDocument3).getElementById('lat'); lat := HtmlElement.getAttribute('value', 0); HtmlElement := (WebBrowser1.document as IHTMLDocument3).getElementById('lng'); lng := HtmlElement.getAttribute('value', 0); LatitudeEdit.Text := lat; LongitudeEdit.Text := lng;
【解决方案2】:

您可以使用 google.maps.Marker#getPosition 从标记返回 LatLng 对象。

然后您可以使用LatLng#latLatLng#lnggoogle.maps.LatLng 对象中检索坐标。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-07
    • 2010-12-02
    • 2019-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多