可能的编码问题在TWebBrowser中将字符串传递给Javascript

可能的编码问题在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"

导言

这是我加载到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" 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
    或它的兄弟姐妹包装
    FPolyLine
    ,有时我会在加纳阿克拉以南300公里的几内亚湾结束;-)
  • 在HTML中指定utf-8和使用
    UTF8Encode(FPolyLine)
注:我的标题是“可能”。这是因为TMemo内容和JavaScript alert()之间的比较似乎表明,除了子字符串出现一个小的显示问题外,字符串之间没有任何差异:

此外,Javascript代码是从运行良好的云解决方案复制而来的

这里会出现什么问题,解决方案是什么?

(Delphi 10升级版1)

FWIW,这是我如何将文件的HTML加载到TWebBrowser中的:

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])