Displaying a map without installing TMapViewer

See the original version for the introduction and screenshot. See the previous page for download details of the MapViewer zip file and synapse40.zip. Extract both sets of source files to your application directory for the demonstration.

This version, using different code to populate combo boxes, will compile in older versions of Lazarus.

The Pascal Code (Unit1.pas)

unit Unit1;
// Developed from the example at https://code.google.com/p/mapviewer/source/browse/example/Unit1.pas
interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, ComCtrls, kcMapViewer, kcMapViewerGLGeoNames
  {$IFDEF WIN32}, kcMapViewerDEWin32{$ELSE}, kcMapViewerDESynapse{$ENDIF WIN32};

type
  TForm1 = class(TForm)
    Button1, Button2: TButton;
    CheckBox1, CheckBox2, CheckBox3: TCheckBox;
    ComboBox1, cboLocations, cboLocs2: TComboBox;
    Edit1, edtLong, edtLat: TEdit;
    GroupBox1, GroupBox2, GroupBox3: TGroupBox;
    Label1, Label2, Label3, Label4, Label5, Label6, Label7, Label8, Label9, Label10: TLabel;
    mv: TMapViewer;
    MVGLGeoNames1: TMVGLGeoNames;
    Panel1: TPanel;
    TrackBar1: TTrackBar;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure cboLocationsSelect(Sender: TObject);
    procedure cboLocs2Select(Sender: TObject);
    procedure CheckBox1Change(Sender: TObject);
    procedure CheckBox2Change(Sender: TObject);
    procedure CheckBox3Change(Sender: TObject);
    procedure ComboBox1Change(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    procedure FormDblClick(Sender: TObject);
    procedure TrackBar1Change(Sender: TObject);
  private
    FDownloader: TCustomDownloadEngine;
    procedure DoBeforeDownload(Url: string; str: TStream; var CanHandle: Boolean);
    procedure DoAfterDownload(Url: string; str: TStream);
    procedure ShowMap(Loc: string);
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}
uses
  md5;
var
  Locs: array[0..16] of string = ('Aberdeen', 'Basingstoke', 'Birmingham', 'Brighton',
                                  'Derby', 'Exeter', 'Leeds', 'London',
                                  'Loughborough', 'Manchester', 'Northampton', 'Preston',
                                  'Sheffield', 'Shrewsbury', 'Wakefield', 'Watford',
                                  'Winchester');
  Locs2: array[0..22] of string = ('Bandung', 'Berlin', 'Bangkok', 'Belgrade', 'Bratislava',
                                   'Brussels', 'Hong Kong', 'Houston', 'Islamabad', 'Karachi',
                                   'Lahore', 'Montreal', 'Moscow', 'Mumbai', 'New Delhi',
                                   'New York',  'Paris', 'Poznan', 'Saint Petersburg',
                                   'Sao Paulo', 'Stockholm', 'Warsaw', 'Zurich');
  Lat, Long: real;
  Error: integer;

procedure TForm1.ShowMap(Loc: string);
var
  Centre: TRealPoint;
  Start: TDateTime;
  DownloadTime: real;
begin
  Start := Now;
  mv.BeginUpdate;
  MVGLGeoNames1.LocationName := Loc;
  mv.Zoom := 12;
  TrackBar1.Position := mv.Zoom;
  mv.Geolocate;
  mv.EndUpdate;
  DownloadTime := (Now - Start) * 24 * 60 * 60;
  Label10.Caption := Format('Delay: %.2f seconds', [DownloadTime]);
  Centre := mv.CenterLongLat;

  Label6.Caption := Format('Longitude: %.5f', [Centre.X]);
  Label7.Caption := Format('Latitude: %.5f', [Centre.Y]);
  edtLong.Text := Format('%.3f', [Centre.X]);
  edtLat.Text := Format('%.3f', [Centre.Y]);
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  Pixel, MouseTile: TIntPoint;
  Centre, Mouse: TRealPoint;
begin
  Pixel := mv.GetMouseMapPixel(X, Y);
  Label2.Caption := Format('Pixel: %d:%d', [Pixel.X, Pixel.Y]);
  MouseTile := mv.GetMouseMapTile(X, Y);
  Label3.Caption := Format('Tile: %d:%d', [MouseTile.X, MouseTile.Y]);
  Mouse := mv.GetMouseMapLongLat(X, Y);
  Label4.Caption := Format('Long: %.5f', [Mouse.X]);
  Label5.Caption := Format('Lat: %.5f', [Mouse.Y]);

  Centre := mv.CenterLongLat;
  Label6.Caption := Format('Long: %.5f', [Centre.X]);
  Label7.Caption := Format('Lat: %.5f', [Centre.Y]);
end;

procedure TForm1.FormDblClick(Sender: TObject);
begin
  TrackBar1.Position := mv.Zoom;
end;

procedure TForm1.TrackBar1Change(Sender: TObject);
begin
  if Sender = TrackBar1 then
    mv.Zoom := TrackBar1.Position;
end;

procedure TForm1.DoBeforeDownload(Url: string; str: TStream;
  var CanHandle: Boolean);
var
  x: string;
  f: TFileStream;
begin
  x := 'cache\'+MDPrint(MD5String(Url));
  if FileExists(x) then
    begin
      f := TFileStream.Create(x, fmOpenRead);
      try
        str.Position := 0;
        str.CopyFrom(f, f.Size);
        str.Position := 0;
        CanHandle := True;
      finally
        f.Free;
      end;
    end
  else
    CanHandle := False;
end;

procedure TForm1.DoAfterDownload(Url: string; str: TStream);
var
  x: string;
  f: TFileStream;
begin
  if not DirectoryExists('cache') then
    ForceDirectories('cache');
  x := 'cache\'+MDPrint(MD5String(Url));
  if (not FileExists(x)) and (not (str.Size = 0)) then
    begin
      f := TFileStream.Create(x, fmCreate);
      try
        str.Position := 0;
        f.CopyFrom(str, str.Size);
      finally
        f.Free;
      end;
    end;
end;

procedure TForm1.ComboBox1Change(Sender: TObject);
begin
  mv.Source := TMapSource(ComboBox1.ItemIndex);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  i: integer;
begin
  mv := TMapViewer.Create(Self);
  mv.Parent := Self;
  MVGLGeoNames1 := TMVGLGeoNames.Create(mv);

  with mv do
    begin
      Left:= 0;
      Top := 0;
      Height := 537;
      Width := 624;
      AutoZoom := True;
      Zoom := 0;
      Debug := False;
      UseThreads := False;
      GeolocationEngine := MVGLGeoNames1;
      DoubleBuffering := False;
      Align := alClient;
    end;

  {$IFDEF WIN32}
  FDownloader := TMVDEWin32.Create(Self);
  {$ELSE}
  FDownloader := TMVDESynapse.Create(Self);
  {$ENDIF WIN32}

  FDownloader.OnAfterDownload := @DoAfterDownload;
  FDownloader.OnBeforeDownload := @DoBeforeDownload;
  mv.DownloadEngine := FDownloader;
  for i := 0 to 16 do
    cboLocations.Items.Add(Locs[i]);
  cboLocations.ItemIndex := 0;
  for i:= 0 to 22 do
    cboLocs2.Items.Add(Locs2[i]);
  cboLocs2.ItemIndex := 0;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FDownloader.Free
end;

procedure TForm1.cboLocationsSelect(Sender: TObject);
begin
  ShowMap(cboLocations.Items[cboLocations.ItemIndex]);
end;

procedure TForm1.cboLocs2Select(Sender: TObject);
begin
  ShowMap(cboLocs2.Items[cboLocs2.ItemIndex]);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Centre: TRealPoint;
  Start: TDateTime;
  DownloadTime: real;
begin
  val(edtLong.Text, Long, Error);
  if Error = 0 then
    begin
      Centre.X := Long;
      val(edtLat.Text, Lat, Error);
      if Error = 0 then
        begin
          Centre.Y := Lat;
          Start := Now;
          mv.BeginUpdate;
          mv.Zoom := 12;
          TrackBar1.Position := mv.Zoom;
          mv.CenterLongLat := Centre;
          mv.EndUpdate;
          DownloadTime := (Now - Start) * 24 * 60 * 60;
          Label10.Caption := Format('Delay: %.2f seconds', [DownloadTime]);
          Label6.Caption := 'Longitude := ' + edtLong.Text;
          Label7.Caption := 'Latitude := ' + edtLat.Text;
        end
      else
        ShowMessage('Please enter a number for the latitude.');
    end
  else
    ShowMessage('Please enter a number for the longitude.');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  ShowMap(Edit1.Text);
end;

procedure TForm1.CheckBox1Change(Sender: TObject);
begin
  mv.Debug := CheckBox1.Checked;
end;

procedure TForm1.CheckBox2Change(Sender: TObject);
begin
  mv.UseThreads := CheckBox2.Checked;
end;

procedure TForm1.CheckBox3Change(Sender: TObject);
begin
  mv.DoubleBuffering := CheckBox3.Checked;
end;

end.

Code of Form (Unit1.lfm)

object Form1: TForm1
  Left = 354
  Height = 537
  Top = 121
  Width = 893
  Caption = 'Map Selector'
  ClientHeight = 537
  ClientWidth = 893
  Color = clBtnFace
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  OnMouseMove = FormMouseMove
  LCLVersion = '1.2.4.0'
  object Panel1: TPanel
    Left = 624
    Height = 537
    Top = 0
    Width = 269
    Align = alRight
    ClientHeight = 537
    ClientWidth = 269
    TabOrder = 1
    object ComboBox1: TComboBox
      Left = 72
      Height = 21
      Top = 8
      Width = 192
      ItemHeight = 13
      ItemIndex = 1
      Items.Strings = (
        'None'
        'Google - Normal'
        'Google - Satellite'
        'Google - Hybrid'
        'Google - Physical'
        'Google - Physical Hybrid'
        'OpenStreetMap - Mapnik'
        'OpenStreetMap - Osmarender'
        'OpenCycleMap'
        'VE - Normal'
        'VE - Road'
        'VE - Aero'
        'VE - Hybrid'
        'Yahoo - Normal'
        'Yahoo - Satellite'
        'Yahoo - Hybrid'
        'Ovi - Normal'
        'Ovi - Satellite'
        'Ovi - Hybrid'
        'Ovi - Physical'
      )
      OnChange = ComboBox1Change
      Style = csDropDownList
      TabOrder = 0
      Text = 'Google - Normal'
    end
    object Label1: TLabel
      Left = 8
      Height = 13
      Top = 12
      Width = 45
      Caption = 'Map type'
      ParentColor = False
    end
    object CheckBox1: TCheckBox
      Left = 8
      Height = 19
      Top = 32
      Width = 51
      Caption = 'Debug'
      OnChange = CheckBox1Change
      TabOrder = 1
    end
    object TrackBar1: TTrackBar
      Left = 9
      Height = 40
      Top = 56
      Width = 148
      Max = 17
      Position = 0
      TickMarks = tmBoth
      OnClick = TrackBar1Change
      TabOrder = 2
    end
    object GroupBox1: TGroupBox
      Left = 8
      Height = 72
      Top = 264
      Width = 256
      Caption = 'Centre'
      ClientHeight = 54
      ClientWidth = 252
      TabOrder = 3
      object Label6: TLabel
        Left = 14
        Height = 13
        Top = 8
        Width = 31
        Caption = 'Label2'
        ParentColor = False
      end
      object Label7: TLabel
        Left = 14
        Height = 13
        Top = 32
        Width = 31
        Caption = 'Label2'
        ParentColor = False
      end
    end
    object GroupBox2: TGroupBox
      Left = 8
      Height = 73
      Top = 104
      Width = 257
      Caption = 'Screen'
      ClientHeight = 55
      ClientWidth = 253
      TabOrder = 4
      object Label2: TLabel
        Left = 14
        Height = 13
        Top = 8
        Width = 31
        Caption = 'Label2'
        ParentColor = False
      end
      object Label3: TLabel
        Left = 14
        Height = 13
        Top = 32
        Width = 31
        Caption = 'Label2'
        ParentColor = False
      end
    end
    object GroupBox3: TGroupBox
      Left = 8
      Height = 73
      Top = 184
      Width = 256
      Caption = 'Mouse Position'
      ClientHeight = 55
      ClientWidth = 252
      TabOrder = 5
      object Label4: TLabel
        Left = 14
        Height = 13
        Top = 8
        Width = 31
        Caption = 'Label2'
        ParentColor = False
      end
      object Label5: TLabel
        Left = 14
        Height = 13
        Top = 32
        Width = 31
        Caption = 'Label2'
        ParentColor = False
      end
    end
    object CheckBox2: TCheckBox
      Left = 98
      Height = 19
      Top = 32
      Width = 59
      Caption = 'Threads'
      OnChange = CheckBox2Change
      TabOrder = 6
    end
    object CheckBox3: TCheckBox
      Left = 184
      Height = 19
      Top = 32
      Width = 79
      Caption = 'DblBuffering'
      OnChange = CheckBox3Change
      TabOrder = 7
    end
    object Button2: TButton
      Left = 176
      Height = 21
      Top = 344
      Width = 75
      Caption = 'Search'
      OnClick = Button2Click
      TabOrder = 8
    end
    object Edit1: TEdit
      Left = 8
      Height = 21
      Top = 344
      Width = 160
      TabOrder = 9
      Text = 'Kolkata'
    end
    object edtLat: TEdit
      Left = 99
      Height = 21
      Top = 442
      Width = 80
      TabOrder = 10
    end
    object edtLong: TEdit
      Left = 4
      Height = 21
      Top = 442
      Width = 80
      TabOrder = 11
    end
    object Label8: TLabel
      Left = 3
      Height = 13
      Top = 421
      Width = 64
      Caption = 'Longitude (X)'
      ParentColor = False
    end
    object Label9: TLabel
      Left = 99
      Height = 13
      Top = 421
      Width = 56
      Caption = 'Latitude (Y)'
      ParentColor = False
    end
    object Button1: TButton
      Left = 189
      Height = 21
      Top = 441
      Width = 75
      Caption = 'GoToXY'
      OnClick = Button1Click
      TabOrder = 12
    end
    object cboLocations: TComboBox
      Left = 8
      Height = 21
      Top = 376
      Width = 100
      ItemHeight = 13
      OnSelect = cboLocationsSelect
      Style = csDropDownList
      TabOrder = 13
    end
    object Label10: TLabel
      Left = 9
      Height = 1
      Top = 496
      Width = 1
      ParentColor = False
    end
    object cboLocs2: TComboBox
      Left = 128
      Height = 21
      Top = 377
      Width = 100
      ItemHeight = 13
      OnSelect = cboLocs2Select
      Style = csDropDownList
      TabOrder = 14
    end
  end
end


Programming - a skill for life!

Lazarus demonstration of a map selector