可能的编码问题在TWebBrowser中将字符串传递给Javascript
导言 这是我加载到TWebBrowser中用于访问Google maps API的HTML页面:可能的编码问题在TWebBrowser中将字符串传递给Javascript,javascript,delphi,encoding,twebbrowser,delphi-10-seattle,Javascript,Delphi,Encoding,Twebbrowser,Delphi 10 Seattle,导言 这是我加载到TWebBrowser中用于访问Google maps API的HTML页面: <html> <head> </head> <body> <script async defer src="https://maps.googleapis.com/maps/api/js?key=%GMAPSAPIKEY%&callback=initMap"></script> <div id="editMap"
<html>
<head>
</head>
<body>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=%GMAPSAPIKEY%&callback=initMap"></script>
<div id="editMap" style="width:600px; height:500px; margin:0; margin-bottom:0; background-color:#F9F9F9; border-right:1px solid #999; float:left;"></div>
<input type='hidden' id='DelphiVan' value='' />
<input type='hidden' id='DelphiNaar' value='' />
<input type='hidden' id='DelphiDistance' value='' />
<input type='hidden' id='DelphiPolyLine' value='' />
<script type="text/javascript">
function initMap() {
ttMapHelper.InitMap('editMap')
}
var ttMapHelper = (function () {
var map;
var directionsService, directionsDisplay;
var polyLine;
var markerA;
var markerB;
var routeChangedCallback;
var routeOrigin;
var routeDestination;
var encodedLine;
var totalDistance;
var totalDistanceText;
function getDirections(origin, destination, display) {
directionsService.route({
origin: origin,
destination: destination,
avoidTolls: true,
travelMode: google.maps.TravelMode.DRIVING, //getTravelMode($('#travelMode').val()),
unitSystem: google.maps.UnitSystem.METRIC //google.maps.UnitSystem.IMPERIAL
}, function (response, status) {
if (status === google.maps.DirectionsStatus.OK) {
if (display)
directionsDisplay.setDirections(response);
else
processDirections(response);
}
else {
alert('Could not display directions due to: ' + status);
}
});
}
function getTravelMode(mode) {
switch (mode) {
case "DRIVING":
return google.maps.TravelMode.DRIVING;
case "BICYCLING":
return google.maps.TravelMode.BICYCLING;
case "WALKING":
return google.maps.TravelMode.WALKING;
}
}
function processDirections(result) {
var route = result.routes[0];
var leg = route.legs[0];
routeOrigin = leg.start_address
routeDestination = leg.end_address
totalDistance = leg.distance.value;
totalDistanceText = leg.distance.text;
encodedLine = route.overview_polyline;
if (routeChangedCallback)
routeChangedCallback();
}
function displayPolyLine(encodedLine) {
if (polyLine) {
polyLine.setMap(null);
markerA.setMap(null);
markerB.setMap(null);
polyLine = undefined;
markerA = undefined;
markerB = undefined;
}
var coordinates = google.maps.geometry.encoding.decodePath(encodedLine);
polyLine = new google.maps.Polyline({
path: coordinates,
strokeColor: '#0000FF',
strokeOpacity: 1.0,
strokeWeight: 2
});
polyLine.setMap(map);
markerA = new google.maps.Marker({
position: coordinates[0],
label: 'A',
map: map
});
markerB = new google.maps.Marker({
position: coordinates[coordinates.length - 1],
label: 'B',
map: map
});
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < coordinates.length; i++) {
bounds.extend(coordinates[i]);
}
map.fitBounds(bounds);
}
var initMap = function (mapId) {
map = new google.maps.Map(document.getElementById(mapId), {
zoom: 7,
center: { lat: 52.2169918, lng: 5.6460789 },
mapTypeId: google.maps.MapTypeId.ROADMAP
});
directionsService = new google.maps.DirectionsService;
directionsDisplay = new google.maps.DirectionsRenderer({
draggable: false,
suppressBicyclingLayer: true,
map: map
});
directionsDisplay.addListener('directions_changed', function () {
processDirections(directionsDisplay.getDirections());
});
}
var calculateRoute = function (origin, destination, callback) {
routeChangedCallback = callback;
routeOrigin = origin;
routeDestination = destination;
getDirections(origin, destination);
}
var editRoute = function (origin, destination, callback) {
routeChangedCallback = callback;
routeOrigin = origin;
routeDestination = destination;
directionsDisplay.setOptions({ draggable: true });
getDirections(origin, destination, true);
}
var showRoute = function (encodedLine) {
displayPolyLine(encodedLine);
}
var getOrigin = function () { return routeOrigin; }
var getDestination = function () { return routeDestination; }
var getDistance = function () { return totalDistance; }
var getDistanceText = function () { return totalDistanceText; }
var getEncodedLine = function () { return encodedLine; }
return {
InitMap: initMap,
CalculateRoute: calculateRoute,
EditRoute: editRoute,
ShowRoute: showRoute,
GetOrigin: getOrigin,
GetDestination: getDestination,
GetDistance: getDistance,
GetDistanceText: getDistanceText,
GetEncodedLine: getEncodedLine
}
})();
function PrepareDelphiVars() {
document.getElementById('DelphiVan').value = ttMapHelper.GetOrigin();
document.getElementById('DelphiNaar').value = ttMapHelper.GetDestination();
document.getElementById('DelphiDistance').value = ttMapHelper.GetDistance();
document.getElementById('DelphiPolyLine').value = ttMapHelper.GetEncodedLine();
};
</script>
</body>
</html>
PrepareDelphiVars
将生成的数据放在隐藏的输入字段中,我使用
lElement := WebBrowser.OleObject.Document.getElementById('DelphiVan');
if not VarIsNull(lElement) then
FVan := lElement.getAttribute('value');
我检索的内容之一是生成的多段线。它的形式是
i|r~Hi{y\kAqDh@wIBcEGcELcCNoHOoFDwDLqE`@mBl@sBx@g@NE]kCg@{BsFoG[eAC[b@w@`@o@pBwApCsAdWyM~^{QvDgBlKoFnOeIzEgJhEgIxAcCtB_Cf@e@Tk@Hw@e@uIm@wHIiDJ}....
如果我将这个字符串从TMemo复制/粘贴到谷歌的,我就得到了从鹿特丹到阿姆斯特丹的正确路线:
问题
我想在下次再次启动TWebBrowser时显示生成的多段线(注意:它位于每次运行时创建的表单上)。因此,我现在从
WebBrowserDocumentComplete
调用:
procedure TFrmGoogleMaps.ToonPolyLine;
begin
FHTMLWindow.execScript('ttMapHelper.ShowRoute("' + FPolyLine + '")', 'JavaScript')
end;
使用与TMemo完全相同的字符串我现在在德国结束了(我在https://maps.googleapis.com/maps-api-v3/api/js/24/10/intl/nl_ALL/onion.js
移动鼠标几秒钟后):
这看起来像是一个编码问题,但我还没有找到解决方案。这就是我尝试过的:
- 在HTML中指定编码:
或
或
这表明当我查询(WebBrowser.Document作为IHTMLDocument2.charset)时,编码存在于
,但不能解决问题WebBrowserDocumentComplete
- 强制TWebBrowser在
- 用
或它的兄弟姐妹包装TidURI.ParamsEncode
,有时我会在加纳阿克拉以南300公里的几内亚湾结束;-)李>FPolyLine
- 在HTML中指定utf-8和使用
UTF8Encode(FPolyLine)
procedure TFrmGoogleMaps.FormCreate(Sender: TObject);
var
lMemStream : TMemoryStream;
lFileStream: TFileStream;
lData : ANSIString;
lFileName : String;
p,l : Integer;
begin
lFileName := ExtractFilePath(ParamStr(0)) + cMapsHTMLFile;
lFileStream := TFileStream.Create(lFileName,fmOpenRead);
SetLength(lData, lFileStream.Size);
lFileStream.ReadBuffer(Pointer(lData)^, Length(lData));
lFileStream.Free;
// Replace the API key marker with the actual key:
p := System.AnsiStrings.PosEx(cAPIKeyMarker,lData);
l := Length(cAPIKeyMarker);
Delete(lData,p,l);
Insert(cGoogleMapsAPIKey,lData,p);
WebBrowser.Navigate('about:blank'); // Nodig voor initialisatie
if Assigned(WebBrowser.Document) then
begin
lMemStream := TMemoryStream.Create;
try
lMemStream.WriteBuffer(Pointer(lData)^, Length(lData));
lMemStream.Seek(0, soFromBeginning);
(WebBrowser.Document as IPersistStreamInit).Load(TStreamAdapter.Create(lMemStream));
finally
lMemStream.Free;
end;
FHTMLWindow := (WebBrowser.Document as IHTMLDocument2).parentWindow;
end;
end;
问题出在这一行:
FHTMLWindow.execScript('ttMapHelper.ShowRoute("' + FPolyLine + '")', 'JavaScript')
与此非常相似:如果FPolyLine
是JavaScript格式,则默认为该值,而不是JavaScript格式。一个简单的解决方法可能是使用
StringReplace(StringReplace(FPolyLine'\','\\',[rfReplaceAll]),'"','\"',[rfReplaceAll])
但是更好的解决方法是使用额外的
将字符串发送到JavaScript,因此我希望使用JavaScript字符串编码函数,而不是URL参数编码函数。谢谢!“我们现在觉得自己很愚蠢,”我的同事web developer说;-)与此同时,我们实际上已经考虑过您的替代方案,现在将实施该方案。
StringReplace(StringReplace(FPolyLine'\','\\',[rfReplaceAll]),'"','\"',[rfReplaceAll])