1

I noticed some strange behaviour when creating markers using the Google Map API for Delphi. I can easily reproduce the problem but have no explanation.

In the code below you will see a CreatePoint method, which I call in the OnClick event of a TButton. The marker is created as it should.

But then I call the SAME createpoint method with the same parameters in the OnCommandGet event of a IdHTTPServer. I then trigger the event by using Curl. But then the marker is not created and I get the message : "Access violation at address 5548985C in module 'mshtml.dll'. Read of address 00000144"

I don't understand why this could give a different result. Any idea ?

I'm using Delphi XE, so I create the TWebBrowser at runtime (because it's not in the Tool Palette in XE).

Code below, the sample project can be downloaded here.

    unit main;

    interface

    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, IdBaseComponent, IdComponent, IdCustomTCPServer, IdCustomHTTPServer,
      IdHTTPServer, GMClasses, GMMap, GMMapVCL, ExtCtrls,
      OleCtrls, SHDocVw, StdCtrls, GMLinkedComponents, GMMarker, GMMarkerVCL,
      GMConstants, IdContext;

    type
      DeviceRange = 0..15;

      TModWallyForm = class(TForm)
        Panel1: TPanel;
        GMMap1: TGMMap;
        IdHTTPServer1: TIdHTTPServer;
        GMMarker1: TGMMarker;
        Button4: TButton;
        procedure FormCreate(Sender: TObject);
        procedure GMMap1AfterPageLoaded(Sender: TObject; First: Boolean);
        procedure Button4Click(Sender: TObject);
        procedure IdHTTPServer1CommandGet(AContext: TIdContext;
          ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
      private
        { Private declarations }
        WebBrowser1 : TWebBrowser;
        Marker : TGMMarker;
        procedure CreatePoint(DeviceID : String; Longitude, Latitude : Real);
      public
        { Public declarations }
      end;

    var
      ModWallyForm: TModWallyForm;

    implementation

    {$R *.dfm}

    procedure TModWallyForm.FormCreate(Sender: TObject);
    var
      i : Integer;
    begin
      WebBrowser1 := TWebBrowser.Create(Panel1);
      TControl(WebBrowser1).Parent := Panel1;
      WebBrowser1.Align := alClient;
      GMMap1.WebBrowser := WebBrowser1;
      // Instantiate Markers
      Marker := TGMMarker.Create(nil);
      Marker.Map := GMMap1;
      IdHTTPServer1.Active := True;
    end;

    procedure TModWallyForm.GMMap1AfterPageLoaded(Sender: TObject; First: Boolean);
    begin
      if First then
      begin
        GMMap1.DoMap;
      end;
    end;

    procedure TModWallyForm.Button4Click(Sender: TObject);
    begin
      CreatePoint('15',4.77,50.55900);
    end;

    procedure TModWallyForm.IdHTTPServer1CommandGet(AContext: TIdContext;
      ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
    begin
      CreatePoint('15',4.77,50.55900);
    end;

    procedure TModWallyForm.CreatePoint(DeviceID: string; Longitude: Real; Latitude: Real);
    begin
      with Marker.Add(Latitude, Longitude) do
        begin
          MarkerType := mtColored;
          InfoWindow.HTMLContent := DeviceID;
          ColoredMarker.Width := 48+(Index*20);
          ColoredMarker.Height := 48;
          ColoredMarker.PrimaryColor := clBlack;
          ColoredMarker.StrokeColor := clBlack;
          Title := '';  // Avoid showing the title when the mouse hovers over the marker
        end;
      GMMap1.RequiredProp.Center.Lat := Latitude;
      GMMap1.RequiredProp.Center.Lng := Longitude;
      GMMap1.RequiredProp.Zoom := 8;
    end;

    end.
Soitjes
  • 11
  • 4

2 Answers2

0

Make sure your constructor (TModWallyForm.FormCreate) was called before the OnCommandGet otherwise your "Marker" is nil

angelodiego
  • 245
  • 1
  • 16
  • You wouldn't even see the map, or anything else on the form if the constructor weren't called. – TLama Nov 27 '13 at 11:34
  • The map displays fine. The application is working as long as I use the TButton to create the marker. – Soitjes Nov 27 '13 at 15:40
0

I have do some test and I see that the AV is raised when try to execute a JavaScript function from the HTML page loaded. The code of components is this

function TGMMap.ExecuteScript(NameFunct, Params: string): Boolean;
var
  Doc2: IHTMLDocument2;
  Win2: IHTMLWindow2;
begin
  Result := Check;

  if not (FWebBrowser is TWebBrowser) then Exit;

  if not Result then Exit;

  Doc2 := TWebBrowser(FWebBrowser).Document as IHTMLDocument2;
  Win2 := Doc2.parentWindow;  // <==== FAIL ON THIS LINE

  Win2.execScript(NameFunct + '(' + Params + ')', 'JavaScript');

  if MapIsNull then
    raise Exception.Create(GetTranslateText('El mapa todavía no ha sido creado',     Language));
end;

I did too a test without any GMLib component, only a TWebBrowser (yes, it exist in XE ;-) ), a button to "do map" and a IdHTTPServer to create the marker with the same result.

For that, I deduce that the problem is not into the GMLib components. You can download the demo from here.

cadetill
  • 1,552
  • 16
  • 24
  • Effectively ! It still gives me no clue on why this happens, and if there is a workaround. A bug in TWebBrowser maybe ? – Soitjes Nov 28 '13 at 18:53
  • As for the TWebBrowser in the tool palette : I have to correct my statement as I'm using Delphi XE Starter, which does not have the TWebBrowser in the tool palette. – Soitjes Nov 28 '13 at 18:55
  • I suppose I have to post a new question rephrasing the issue ? Because it's not related to the GMLib components. – Soitjes Nov 28 '13 at 18:59