Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Lesedauer 5 Min.

CartoType: Einsatz mit Windows Forms

Der Big-Tech-freie Kartendienst CartoType kann dazu beitragen, Anwendungen mit Maps-Diensten unabhängiger von Google, Apple und Co. zu machen. In diesem Beitrag soll das System in einer Windows-Forms-Applikation ins Leben gerufen werden.
© EMGenie

Am Beginn des Weges zu unserer eigenen Big-Tech-freien Kartenanwendung steht der Download des CartoType Windows SDK. Extrahieren Sie die ZIP-Datei danach in einen bequem zugänglichen Ort im Dateisystem, um das Projekt CartoTypeDemo\CartoTypeDemo.sln zu öffnen.

In manchen Fällen erweisen sich die Sicherheit-Konfigurationsrichtlinien von Windows an dieser Stelle als hinderlich. Falls der in Visual Studio enthaltene Dialog nicht ausreicht, bietet es sich an, die integrierte Entwicklungsumgebung zu schließen und ein Windows-Terminal zu öffnen. Führen Sie dort in der PowerShell folgenden Befehl im Projekt-Stammverzeichnis aus:

 

PS C:\...\NMGCartoType\Online - Classic .net\CartoTypeDemo> Unblock-File *

 

Daraufhin startet die aus dem Leitartikel zu CartoType [1] bekannte Demo-Anwendung. Sie kann danach mehr oder weniger beliebige CTM1-Dateien laden, auf den Bildschirm bringen und als Grundlage für die Navigation heranziehen.

Willkommen in Windows Forms

Ältere Versionen von Visual Studio kommen mit Windows-Forms-Anwendungen im Allgemeinen besser zurecht. Dennoch werden wir in den folgenden Schritten mit Version 2022 der IDE arbeiten. Als erster Schritt bietet sich wie immer das Öffnen der Datei MainForm.cs an – da das Beispiel allerdings eine klassische MDI-Applikation realisiert, ist dort eigentlich nur die für das Laden von Dateien notwendige Methode interessant. Ihr Korpus präsentiert sich folgendermaßen:

 

private void openMenuItem_Click(object sender, EventArgs e){
  ...
  if (open_file_dialog.ShowDialog() == DialogResult.OK){
    var map_form = new MapForm();
    map_form.MdiParent = this;
    ...
    if (map_form.Construct(open_file_dialog.FileName, ""))
      map_form.Show();

 

Die Aufrufe nach dem Schema map_form.Show() haben dabei die Aufgabe, eine neue Instanz von MapForm ins Leben zu rufen. In ihr beziehungsweise in der für die Realisierung zuständigen Dateiengruppe findet sich die eigentliche Intelligenz der Applikation.

Die Codierungsrichtlinien im Hause CartoType sind insofern eigenwillig, als die Member-Deklarationen in der Regel am Ende der Datei stehen. Wir scrollen deshalb in der Datei zunächst nach unten, wo die folgende Member-Deklaration von Relevanz ist:

 

private CartoType.Framework m_framework;
private CartoType.MapRenderer m_map_renderer;
private CartoType.Point m_map_drag_anchor = new();

 

Am wichtigsten ist dabei die Klasse CartoType.Framework. Sie gilt als Dreh und- Angelpunkt für alle in CartoType vorgesehenen beziehungsweise auszuführenden Operationen und ist auch für das Vorhalten des Zustands und für die Steuerung verantwortlich.

Von Interesse sind außerdem die Klassen vom Typ CartoType.MapRenderer, die einen Darstellungspunkt abbilden, der auf die Framework-Klasse bezogen ist.

Das Laden der Kartendaten erfolgt dann in der Methode Construct, die im Fall der vorliegenden Beispiel-Applikation wie nachfolgend gezeigt aufgebaut ist. Angemerkt sei, dass so gut wie alle in diesem Artikel abgedruckten Snippets im Interesse der Kompaktheit stark gekürzt sind – der vollständige Quellcode findet sich, wie weiter oben beschrieben, im frei herunterladbaren SDK.

 

var param = new CartoType.FrameworkParam();
param.MapFileName = aFileName;
param.Key = aKey;
param.StyleSheetFileName = style;
param.FontFileName = font;
param.ViewWidth = ClientSize.Width;
param.ViewHeight = ClientSize.Height;
m_framework = new CartoType.Framework(param)!;

 

Von besonderem Interesse ist die Nutzung eines Objekts vom Typ CartoType.FrameworkParam. Es dient als Einlaufstelle für alle Parameter, die danach zur Belebung der Framework-Klasseninstanzen herangezogen werden.

Die Erzeugung des Renderers erfolgt weiter unten gemäß nachfolgendem Schema:

 

private void MapForm_Load(object sender, EventArgs e) {
...
  m_map_renderer = new CartoType.MapRenderer(m_framework, Handle);

 

Die Verwendung des Eventhandlers MapForm_Load ist erforderlich, weil die Initialisierung der Klasse auf das Formular zugreifen muss. In Handle findet sich dabei ein Verweis auf den GDI-Frame, in dem die Rendering-Instanz die durchzuführenden Zeichen-Operationen erledigen wird.

Interessant ist in diesem Zusammenhang, dass die Verarbeitung von Mausereignissen in der Framework-Klasse erfolgt. Mausbewegungen werden beispielsweise gemäß folgendem Schema in Richtung des Systems weitergereicht:

 

private void MapForm_MouseMove(object sender, MouseEventArgs e) {
  if (e.Button == MouseButtons.Left) {
    m_framework.Pan(m_map_drag_anchor.X, m_map_drag_anchor.Y, CartoType.CoordType.Map,
      e.Location.X, e.Location.Y, CartoType.CoordType.Display);
    m_map_drag_anchor = new CartoType.Point(e.Location.X, e.Location.Y);
    m_framework.ConvertPoint(m_map_drag_anchor, CartoType.CoordType.Display, CartoType.CoordType.Map);
  }
}

 

Der vom Entwickler anzulegende Code beschränkt sich dabei darauf, Bewegungs-Distanzen und ähnliche Werte zu berechnen. Der Gutteil der Arbeit, beispielsweise im Bereich der Aktualisierung des Displays, wird vom Framework transparent und automatisch erledigt.

Ähnliches findet sich in der Methode MapForm_MouseWheel, die den Zoom-Faktor der angezeigten Karte in Reaktion auf das Drehen des Mausrades erhöht oder reduziert:

 

private void MapForm_MouseWheel(object sender, MouseEventArgs e) {
  var pos = e.Location;
    int zoom_count = e.Delta / 120;
    double zoom = Math.Sqrt(2);
    if (zoom_count == 0)
      zoom_count = e.Delta >= 0 ? 1 : -1;
    zoom = Math.Pow(zoom, zoom_count);
    if (ClientRectangle.Contains(pos))
      m_framework.ZoomAt(zoom, pos.X, pos.Y, CartoType.CoordType.Screen);
    ...
}

 

Zu guter Letzt sei noch darauf hingewiesen, dass das Neu-Zeichnen der vom Renderer vorgehaltenen Ansicht naturgemäß nur als Reaktion auf ein Betriebssystemereignis erfolgen kann. Die nach dem folgenden Schema erfolgende Weiterreichung des Events fällt dabei in die alleinige Verantwortung des Entwicklers:

 

private void MapForm_Paint(object sender, PaintEventArgs e)
{
  m_map_renderer.Draw();
}

Value-Added-Features des Frameworks

Die als Dreh- und Angelpunkt dienende Klasse stellt Nutzern des Frameworks verschiedene Hilfsfunktionen zur Verfügung. Interessant ist beispielsweise das Exportieren in eine PNG-Datei.

Der Gutteil des zur Verfügung gestellten Codes ist dabei für die Auswertung der SaveFileDialog-Klasse verantwortlich, die von der Beispielapplikation zur Ermittlung des Dateinamens herangezogen wird:

 

private void saveImageAsPNGFileMenuItem_Click(object sender, EventArgs e) {
  var save_file_dialog = new SaveFileDialog();
  ...
  if (save_file_dialog.ShowDialog() == DialogResult.OK) {
    var error = m_framework.WriteMapImage(save_file_dialog.FileName, CartoType.FileType.Png, true);
    ...
  }
}

 

Das eigentliche Herausschreiben der PNG-Datei erfolgt dann lediglich durch Aufrufen der Methode WriteMapImage.

Fazit

Das Windows-Forms- beziehungsweise .NET-API von CartoType ist ein durchaus durchdachtes Programmiersystem. Wer ein wenig Zeit in das Verstehen der Architektur investiert, kann danach schnell und mit geringem Aufwand ansehnliche und Big-Tech-freie Kartenapplikationen zaubern.

[1] Tam Hanna, Mapping, Marke Eigenbau, dotnetpro 4/2026, Seite 122 ff.

Neueste Beiträge

Vom Sub-Agenten zum Schwarm - Kimi K3 – das Modell hinter dem Agenten, Teil 5
Mehr Agenten versprechen mehr Tempo, vervielfachen aber auch Abstimmung und Risiko. Ob aus paralleler Aktivität tatsächlich Fortschritt entsteht, entscheidet sich dort, wo spektakuläre Schwarmdemos meist enden.
5 Minuten
Wenn aus jeder Cloud-Ressource nur ein weiteres Kubernetes-Objekt wird - Interview
STACKIT baut eine europäische Cloud-Alternative zu AWS, GCP und Azure. Tech Lead Patrick Koss erklärt, warum Crossplane statt klassischem Cloud-API der Schlüssel zur Selbstverwaltung ist.
9. Sep 2026
Sichtkontakt: Coding-Driven Design - Kimi K3 – das Modell hinter dem Agenten, Teil 4
Zwischen fehlerfrei kompiliert und überzeugend gestaltet liegt eine Lücke, die reine Codeanalyse kaum erfasst. Sobald ein Agent seine eigene Oberfläche betrachtet, beginnt eine andere Art der Entwicklung mit neuen Möglichkeiten, aber auch neuen Maßstäben.
5 Minuten

Das könnte Dich auch interessieren

CartoType: Karte nach Maß - Mapping mit CartoType, Teil 1
Mit CartoType gibt es ein System, das Google Maps und Co. ersetzen kann und dabei das kompakte Dateiformat CTM1 nutzt. Mit durchaus vertretbarem Aufwand lassen sich solche CTM1-Kartendateien auch nach eigenen Bedürfnissen selbst erstellen.
5 Minuten
31. Aug 2026
C#-.NET-Apps mit WinUI 3 - Komponentenbasierte Apps mit Fluent/FAST, Teil 3
Microsoft macht mit WinUI 3 ein natives User-Experience-Framework für Windows verfügbar, dessen Komponenten auf dem Microsoft-eigenen Design-System Fluent 2 basieren.
23 Minuten
13. Mai 2024
UIs für Linux - Bedienoberflächen entwickeln mithilfe von C#, .NET und Avalonia
Es gibt viele UI-Frameworks für .NET, doch nur sehr wenige davon unterstützen Linux. Avalonia schafft als etabliertes Open-Source-Projekt Abhilfe.
16 Minuten
16. Jun 2025
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige