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

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
Planen, patchen, prüfen mit Kimi - Kimi K3 – das Modell hinter dem Agenten, Teil 3
Ein starkes Modell allein schreibt noch keinen verlässlichen Code. Erst im Repository zeigt sich, ob aus künstlicher Intelligenz ein brauchbarer Entwicklungspartner entsteht oder aber ein Risiko mit Shell-Zugriff.
5 Minuten
Haben wir nichts gelernt? - Verständnis statt Fertiglösung – auch beim Umgang mit KI
Ein KI-Experiment des Autors schlug hohe Wellen – die Reaktionen offenbaren jedoch einen alten Fehler der Softwareentwicklung: die Suche nach der Abkürzung.
7 Minuten
26. Aug 2026

Das könnte Dich auch interessieren

Elektronische Schaltkreise im Browser simulieren - Simulation
Statt mit Steckfeld oder Lötkolben kann man auf dieser Website Schaltungen per Drag and Drop zusammenstellen und deren Verhalten testen.
2 Minuten
26. Jul 2018
DDC hakt nach: Steiniger Weg von WPF zu Avalonia?
WPF hat ausgedient? Wer ein modernes User Interface über alle Plattformen hinweg entwickeln will, kommt an Avalonia UI kaum vorbei. Doch was taugt Avalonia im Vergleich zu MAUI oder Blazor? Dieses Interview räumt mit Mythen auf – und zeigt, worauf sich Entwickler:innen einstellen müssen.
5 Minuten
13. Okt 2025
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
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige