Delphi-PRAXiS
Seite 41 von 55   « Erste     31394041 424351     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Software-Projekte der Mitglieder (https://www.delphipraxis.net/26-software-projekte-der-mitglieder/)
-   -   Google Maps über COM (Component Object Model) (https://www.delphipraxis.net/157004-google-maps-ueber-com-component-object-model.html)

mischo22 19. Jun 2013 08:23

AW: Google Maps über COM (Component Object Model)
 
Ich habe mal eine kurze Frage:
Wie kann ich mehrere Maps in einer Anwendung verwenden.

Im Moment habe ich das so probiert:

Code:
type
  TForm1 = class(TForm)
    ...
    WebBrowser1: TWebBrowser;
    WebBrowser2: TWebBrowser;
    ...
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    MapScript1: TScript;
    MapScript2: TScript;
    procedure InitMap(Sender: TObject);
end;


procedure TForm1.FormShow(Sender: TObject);
begin
    // Einmalig die Maps initialisieren
    if MapScript1=nil then
        TScript.Create(WebBrowser1).LoadAPIAsync(InitMap);

    if MapScript2=nil then
        TScript.Create(WebBrowser2).LoadAPIAsync(InitMap);
end;



procedure TForm1.InitMap(Sender: TObject);
var
   MapOptions: TMapOptions;
   MarkerOptions: TMarkerOptions;
begin
    with TScript(Sender) do
    begin
        MapOptions:=TMapOptions.Create;
        with MapOptions do
        begin
            DisableDefaultUI:=true;        //alle Kontrollelemente ausschalten
            DisableDoubleClickZoom:=true;  //kein Zoom per Doppelklick
            Draggable:=false;              //Karte nicht verschiebbar
            ScrollWheel:=false;            //kein Zoom über Mausrad
            KeyboardShortcuts:=false;      //keine Tastenkürzel
            MapTypeID:=Google.Maps.MapTypeId.Roadmap; //Kartentyp (roadmap oder satellite)

            Zoom:=1;                       //Zoom
            Center:=Google.Maps.LatLng(0,0); //Kartenzentrum
        end;
        New(Google.Maps.Map(MapOptions));

        // Marker Zeichnen
        MarkerOptions:=TMarkerOptions.Create;
        MarkerOptions.Map:=Google.Maps.Map(MapOptions);
        MarkerOptions.Position:=Google.Maps.LatLng(53,8);
        MarkerOptions.Title:='Letzte Position';
        New(Google.Maps.Marker(MarkerOptions));
    end;
end;

Wenn ich aber später die Parameter ändern möchte, schmiert das Programm mit einer Schutzverletzung ab:

Code:
MapScript1.Maps[0].Zoom:=17;
MapScript1.Maps[0].Center:=MapScript_T1.Google.Maps.LatLng(50,10); //Kartenzentrum
MapScript1.Maps[0].MapTypeID:=MapScript_T1.Google.Maps.MapTypeId.SATELLITE;
Was mache ich falsch?

Thom 19. Jun 2013 12:08

AW: Google Maps über COM (Component Object Model)
 
Hallo mischo22,

Du speicherst die Script-Objekte nicht in den Variablen:
Delphi-Quellcode:
procedure TForm1.FormShow(Sender: TObject);
begin
  // Einmalig die Maps initialisieren
  if MapScript1=nil then
      TScript.Create(WebBrowser1).LoadAPIAsync(InitMap); //<- Script wird erstellt, aber nicht in MapScript1 gespeichert

  if MapScript2=nil then
    TScript.Create(WebBrowser2).LoadAPIAsync(InitMap); //<- selbe Problem
end;
Die Lösung sollte sein:
Delphi-Quellcode:
procedure TForm1.FormShow(Sender: TObject);
begin
  // Einmalig die Maps initialisieren
  if MapScript1=nil then
  begin
    MapScript1:=TScript.Create(WebBrowser1);
    MapScript1.LoadAPIAsync(InitMap);
  end;
  if MapScript2=nil then
  begin
    MapScript2:=TScript.Create(WebBrowser2);
    MapScript2.LoadAPIAsync(InitMap);
  end;
end;
Allerdings kannst Du Dir auch das Speichern der Script-Objekte sparen - das erfolgt schon frameworkintern:
Delphi-Quellcode:
procedure TForm1.FormShow(Sender: TObject);
begin
  // Einmalig die Maps initialisieren
  if Script(WebBrowser1)=nil then
    with TScript.Create(WebBrowser1) do
      LoadAPIAsync(InitMap);
  if Script(WebBrowser2)=nil then
    with TScript.Create(WebBrowser2) do
      LoadAPIAsync(InitMap);
end;
Um später auf das Objekt zugreifen zu können, reicht
Delphi-Quellcode:
  with Script(WebBrowser1) do
  begin
    Maps[0].Zoom:=17;
    Maps[0].Center:=New(Google.Maps.LatLng(50,10)); //<- New-Funktion verwenden
    Maps[0].MapTypeID:=Google.Maps.MapTypeId.SATELLITE;
  end;
Wer Angst vor dem angeblich bösen "with" hat, macht es so:
Delphi-Quellcode:
  Script(WebBrowser1).Maps[0].Zoom:=17;
  Script(WebBrowser1).Maps[0].Center:=New(Script(WebBrowser1).Google.Maps.LatLng(50,10)); //<- New-Funktion verwenden
  Script(WebBrowser1).Maps[0].MapTypeID:=Script(WebBrowser1).Google.Maps.MapTypeId.SATELLITE;
Allerdings mußt Du bei der Erstellung von Hilfsobjekten momentan noch beachten, daß dabei ebenfalls das Script-Objekt als Parameter angegeben wird:
Delphi-Quellcode:
procedure TForm1.InitMap(Sender: TObject);
var
  Map: TMap;
  MapOptions: TMapOptions;
  MarkerOptions: TMarkerOptions;
begin
  with Sender as TScript do //<- hier eventuell schon einmal den harten Cast für Version 3 vermeiden (das geht nicht gut mit Interfaces)
  begin
    MapOptions:=TMapOptions.Create(Sender as TScript); //<- hier das Script-Objekt als Parameter angeben
    with MapOptions do
    begin
      DisableDefaultUI:=true;      
      DisableDoubleClickZoom:=true;
      Draggable:=false;            
      ScrollWheel:=false;          
      KeyboardShortcuts:=false;    
      MapTypeID:=Google.Maps.MapTypeId.Roadmap;
      Zoom:=1;                      
      Center:=New(Google.Maps.LatLng(0,0)); //<- New-Funktion verwenden
    end;
    Map:=New(Google.Maps.Map(MapOptions)); //<- Karte für den Marker merken

    // Marker Zeichnen
    MarkerOptions:=TMarkerOptions.Create(Sender as TScript); //<- hier ebenfalls das Script-Objekt angeben
    MarkerOptions.Map:=Map; //<- hier die Variable Map verwenden - sonst wird noch eine weitere Karte angelegt
    MarkerOptions.Position:=New(Google.Maps.LatLng(53,8)); //<- New-Funktion verwenden
    MarkerOptions.Title:='Letzte Position';
    New(Google.Maps.Marker(MarkerOptions));
  end;
end;
In der Version 3 wird es für diese Hilfsobjekte ebenfalls eine passende New-Funktion geben, so daß dann die Sache noch etwas einfacher wird:
Delphi-Quellcode:
  with Sender as IScript do
  begin
    MapOptions:=New(Google.Maps.MapOptions);
    [...]
  end;

mischo22 19. Jun 2013 18:46

AW: Google Maps über COM (Component Object Model)
 
Hallo Thom,

Ich habe nun den OnShow bereich entsprechend angepasst und meine eigenen Script-Variablen entfernt.

Dies sieht nun so aus:

Code:
procedure TForm1.FormShow(Sender: TObject);
begin
    // Einmalig die Maps initialisieren
    if Script(WebBrowser_T1)=nil then
         with TScript.Create(WebBrowser_T1) do
            LoadAPIAsync(InitMap);

    if Script(WebBrowser_T2)=nil then
         with TScript.Create(WebBrowser_T2) do
            LoadAPIAsync(InitMap);

    if Script(WebBrowser_T3)=nil then
         with TScript.Create(WebBrowser_T3) do
            LoadAPIAsync(InitMap);

    if Script(WebBrowser_T4)=nil then
         with TScript.Create(WebBrowser_T4) do
            LoadAPIAsync(InitMap);
end;
Leider kann ich mittels der Zeilen
Code:
// Map aktualisieren
            with Script(WebBrowser_T1) do
            begin
                Maps[0].Zoom:=17;
                ...
            end;
Nicht auf die Map nachträglich zugreifen. Es kommt beim Compilieren die Fehlermeldung: "Undeklarierter Bezeichner: Maps"

Thom 19. Jun 2013 19:02

AW: Google Maps über COM (Component Object Model)
 
Auf welche Funktion/Unit kommst Du, wenn Du mit Strg auf die Funktion Script klickst?

mischo22 19. Jun 2013 19:18

AW: Google Maps über COM (Component Object Model)
 
Ich komme auf die datei BrowserTools.pas

Code:
function Script(WebBrowser: TOleControl): IDispatch;

Thom 19. Jun 2013 19:24

AW: Google Maps über COM (Component Object Model)
 
Hatte ich schon vermutet. Ändere mal bitte die Reihenfolge der Units in der uses-Anweisung: gmAPI muß nach (!) BrowserTools kommen.

mischo22 19. Jun 2013 20:08

AW: Google Maps über COM (Component Object Model)
 
Ok, das war schon mal der Fehler.
Perfekt ist es aber noch immer nicht.
Map1 (Webbrowser_T1) scheint alle Befehle aus dem Init-Map korrekt zu verarbeiten.
Bei den Maps 2-4 werden die festgelegten Center-Koordinaten nicht korrekt angewendet.
Die Karten liegen nicht bei LatLng(0,0) sondern bei LatLng(-90,0).

Irgend eine Idee?

Thom 19. Jun 2013 20:24

AW: Google Maps über COM (Component Object Model)
 
Zitat:

Zitat von mischo22 (Beitrag 1219119)
Irgend eine Idee?

:gruebel::wiejetzt::glaskugel: Nö...

Lade mal bitte ein kompilierbares Projekt hoch, damit ich mir das Problem im Debugger anschauen kann.

mischo22 20. Jun 2013 16:49

AW: Google Maps über COM (Component Object Model)
 
Habs per Mail gesendet.

Thom 20. Jun 2013 18:23

AW: Google Maps über COM (Component Object Model)
 
Hallo Michael,

ist angekommen und auch schon angeschaut.

Das Problem liegt bei der VCL bzw. dem TWebBrowser: Solange dieser nicht sichtbar ist, hat er eine Größe von 0x0 (oder 1x1) Pixeln. Damit liegt das Kartenzentrum (in Deinem Fall (0,0)) in der linken oberen Ecke.
Mein Vorschlag wäre, nur die Karte zu laden, die am Anfang sichtbar ist und alle anderen erst dann, wenn die entsprechende Seite angeklickt wird:
Delphi-Quellcode:
procedure TForm1.PageControl1Change(Sender: TObject);
  procedure InitMap(WebBrowser: TWebBrowser);
  begin
    if Script(WebBrowser)=nil then
      with TScript.Create(WebBrowser) do
        LoadAPIAsync(Self.InitMap);
  end;
begin
  if PageControl1.ActivePage=TabSheet1 then InitMap(WebBrowser_T1);
  if PageControl1.ActivePage=TabSheet2 then InitMap(WebBrowser_T2); //bzw. Tracker2, da Du das umbenannt hattest
  if PageControl1.ActivePage=TabSheet3 then InitMap(WebBrowser_T3);
  if PageControl1.ActivePage=TabSheet4 then InitMap(WebBrowser_T4);
  if PageControl1.ActivePage=TabSheet5 then InitMap(WebBrowser_T5);
end;
Das würde auch die Startzeit des Programmes spürbar verkürzen, da jetzt nicht mehr alle Karten im OnShow-Ereignis geladen werden müssen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:07 Uhr.
Seite 41 von 55   « Erste     31394041 424351     Letzte »    

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz