Inhaltsverzeichnis:

Eingebetteter Fenstermanager - Gunook
Eingebetteter Fenstermanager - Gunook

Video: Eingebetteter Fenstermanager - Gunook

Video: Eingebetteter Fenstermanager - Gunook
Video: Archicad23 Library Part Maker Fenster herstellen 2024, Juli
Anonim
Eingebetteter Fenstermanager
Eingebetteter Fenstermanager
Eingebetteter Fenstermanager
Eingebetteter Fenstermanager
Eingebetteter Fenstermanager
Eingebetteter Fenstermanager
Eingebetteter Fenstermanager
Eingebetteter Fenstermanager

Dieses Projekt zeigt, wie ein Fenstermanager mit beweglichen überlappenden Fenstern auf einem eingebetteten Mikrocontroller mit einem LCD-Panel und einem Touchscreen implementiert wird. Dafür gibt es im Handel erhältliche Softwarepakete, die jedoch Geld kosten und Closed Source sind. Dieser namens MiniWin ist kostenlos und quelloffen. Es ist in vollständig konformem C99 geschrieben und kann in einer C- oder C++-Anwendung verwendet werden. Die Ziele von MiniWin sind einfach zu bedienen, leicht zu modifizieren, erweiterbar, portabel auf eine breite Palette von Hardware und nicht zu ressourcenhungrig.

Neben dem Code zur Verwaltung Ihrer Fenster bietet MiniWin eine Sammlung von Bedienelementen für die Benutzeroberfläche - Schaltflächen, Schieberegler, Fortschrittsbalken, Bäume usw. Sie können mehrere Fenster unterschiedlichen Typs oder mehrere Instanzen desselben Typs haben. Fenster können verschoben, in der Größe geändert, maximiert, minimiert, geschlossen werden - all das, was Sie mit Fenstern in größeren Fenstermanagern tun. TrueType-Schriftarten mit Kerning und Anti-Aliasing (lässt Text glatt aussehen) werden ebenfalls für eine ansprechende Textdarstellung unterstützt.

In jedem Fenster haben Sie einen Kundenbereich (Ihr Platz innerhalb des Rahmens und unterhalb der oberen Leiste). Auf diesem können Sie Steuerelemente hinzufügen, um einen Dialog zu erstellen, oder Sie können die integrierte Grafikbibliothek verwenden, um zu zeichnen, was Sie möchten. Alle Funktionen der Grafikbibliothek sind fensterorientiert. Sie müssen sich keine Gedanken darüber machen, wo sich Ihr Fenster befindet, was es überlappt oder ob es minimiert ist.

Neben dem Erstellen eigener Fenster sind auch einige Standarddialoge enthalten, die sehr einfach zu instanziieren sind - zum Beispiel Bestätigungsdialoge (nur ein OK- oder Ja/Nein-Button), Zeit-/Datums-Setter, Dateiauswahl, Farbauswahl usw.

MiniWin verwendet ein standardmäßiges Windows-Manager-Design-Nachrichtenwarteschlangensystem. Windows können untereinander und mit dem Fenstermanager über Nachrichten interagieren. Sie rufen keine Funktionen auf, um Dinge direkt zu erledigen, Sie fügen der Warteschlange eine Nachricht hinzu und der Fenstermanager wird sie für Sie ausführen.

MiniWin wurde auf Standard-Entwicklungsboards mit Touchscreen-Displays der Mikrocontroller-Hersteller ST, NXP und Renesas portiert. Für all diese Geräte gibt es Hardwaretreiber und Beispielprojekte. Darüber hinaus kann MiniWin für Windows oder Linux erstellt werden, sodass Sie Ihren Benutzeroberflächencode simulieren können, bevor Sie Ihre eingebettete Hardware erhalten.

MiniWin verfügt über einen Codegenerator. Sie können Ihre Fenster und Steuerelemente in einer einfach zu erstellenden, für Menschen lesbaren JSON-Datei angeben, und der Codegenerator analysiert die Datei und erstellt den Code für Sie (es folgen viele Beispiele). Es erstellt vollständige Windows- oder Linux-Simulatoranwendungen, die einfach erstellt werden können, und Ihr simuliertes LCD-Display mit Ihren MiniWin-Fenstern funktioniert. Sie können genau den gleichen generierten Code nehmen und ihn in ein eingebettetes Projekt einfügen und den gleichen Code wenige Augenblicke später mit den gleichen Fenstern und Steuerelementen auf Ihrer eingebetteten Hardware anzeigen.

MiniWin benötigt keine Betriebsunterstützung auf dem eingebetteten Gerät. Es läuft alles in einem einzigen Thread. MiniWin kann in ein RTOS integriert werden, das auf einem eingebetteten Prozessor läuft, und es gibt Beispiele, die MiniWin mit FreeRTOS integrieren.

Dieses anweisbare zeigt, wie man MiniWin auf einem STM32 M4-Prozessor mit dem billigen STM32F429 Discovery-Board, das mit einem bereits angebrachten QVGA-Touchscreen-Display geliefert wird, zum Laufen bringt. Diese sind bei Ihrem Elektronikkomponenten-Lieferanten leicht erhältlich.

MiniWin läuft auf Midrange-Mikrocontrollern und höher.

Lieferungen

STM32F429I-DISC1-Entwicklungsplatine und ein Micro-USB-Kabel

STM32CubeIDE herunterladen, das kostenlos ist.

Schritt 1: Code erhalten

Den Code erhalten
Den Code erhalten

Zunächst muss STM32CubeIDE installiert sein. Sie erhalten das von der Website von ST. Sie müssen sich registrieren und es dauert eine Weile, es herunterzuladen und zu installieren. Es ist alles kostenlos.

Laden Sie während der Installation die MiniWin-Quelle herunter und entpacken Sie sie. Es ist groß, aber Sie werden nur einen kleinen Teil davon verwenden. Klicken Sie hier auf die grüne Schaltfläche "Klonen oder Herunterladen" …

github.com/miniwinwm/miniwinwm

Wählen Sie dann Zip herunterladen. Entpacken Sie den Inhalt.

Schritt 2: Erstellen eines Beispielprojekts

Erstellen eines Beispielprojekts
Erstellen eines Beispielprojekts
Erstellen eines Beispielprojekts
Erstellen eines Beispielprojekts

Lassen Sie uns zunächst eines der Beispielprojekte erstellen. Eine gute heißt MiniWinSimple. Starten Sie STM32CubeIDE und gehen Sie dann wie folgt vor:

  1. Wählen Sie Datei|Importieren…
  2. Öffnen Sie Allgemein und wählen Sie Vorhandenes Projekt in Arbeitsbereich. Nächste.
  3. Klicken Sie auf Durchsuchen und navigieren Sie zu dem Ort, an dem Sie MiniWin entpackt haben. Gehen Sie dann zum Ordner STM32CubeIDE\MiniWinSimple\STM32F429. Klicken Sie auf Ordner auswählen.
  4. Im Projekt: Aktivieren Sie MiniWinSimple_STM32F429 und klicken Sie dann auf Fertig stellen.
  5. Das MiniWinSimple_STM32F429-Projekt wird in Ihrem Projekt-Explorer angezeigt. Wählen Sie es aus und erstellen Sie es mit Project|Build Project.
  6. Schließen Sie nun Ihr USB-Kabel an das Board und Ihren Computer an und führen Sie es mit Run|Debug aus und wenn es heruntergeladen ist, wählen Sie Run|Resume. Sie erhalten beim ersten Mal eine Bildschirmkalibrierungsanzeige, berühren Sie also die Mitte der 3 Kreuze auf dem LCD-Display. Sie können jetzt mit dem Fenster auf dem Display interagieren.

Um ein Fenster zu verschieben, ziehen Sie es an seiner Titelleiste. Um die Größe eines Fensters zu ändern, verwenden Sie das weiße Dreiecksymbol links in der Titelleiste. MiniWin-Fenster können nicht durch Ziehen der Ränder in der Größe geändert werden, da die Displays, auf denen MiniWin verwendet wird, zu klein sind. Um ein Fenster zu minimieren, zu maximieren oder zu schließen, verwenden Sie die Symbole am rechten Ende der Titelleiste (das Schließen ist möglicherweise deaktiviert). Wenn ein Fenster minimiert ist, können Sie die minimierten Symbole nicht verschieben. Sie bauen sich von links unten nach rechts auf.

Schritt 3: Ausführen des Codegenerators

Ausführen des Codegenerators
Ausführen des Codegenerators

Jetzt ändern wir das Beispielprojekt, indem wir einige eigene Fenster generieren und den neuen Code einfügen. Dazu führen wir den Codegenerator aus.

  1. Öffnen Sie eine Eingabeaufforderung und gehen Sie zu dem Ordner, in den Sie MiniWin entpackt haben, und dann zum Ordner Tools\CodeGen.
  2. Die ausführbare Datei für Windows CodeGen.exe ist bereits verfügbar. Für Linux müssen Sie es erstellen, indem Sie make eingeben. (Sie können es auch aus dem Quellcode für Windows erstellen, wenn Sie befürchten, eine heruntergeladene ausführbare Datei auszuführen, der Compiler und die Entwicklungsumgebung jedoch installiert sein müssen. Weitere Informationen finden Sie in der MiniWin-Dokumentation im Ordner docs).
  3. In diesem Ordner befinden sich einige JSON-Beispieldateien. Wir verwenden example_empty.json. Sie müssen es zuerst bearbeiten, um es für Windows oder Linux einzurichten. Öffnen Sie es in einem Editor und ändern Sie oben, wo Sie "TargetType" finden, den Wert "Linux" oder "Windows" auf den Wert, auf dem Sie den Codegenerator ausführen.
  4. Geben Sie nun codegen example_empty.json in die Eingabeaufforderung ein.
  5. Gehen Sie zu Ihrem Projekt in STM32CubeIDE und öffnen Sie den Ordner MiniWinSimple_Common. Löschen Sie alle Dateien darin.
  6. Wir haben den "TargetName" in der JSON-Datei als Standard bei "MiniWinGen" belassen, so dass der Name unseres Ordners mit generiertem Code ist. Gehen Sie in den Ordner, in den Sie MiniWin entpackt haben, und dann in den Ordner MiniWinGen_Common. Wählen Sie nun alle diese Dateien aus und ziehen Sie sie per Drag & Drop in STM32CubeIDE im MiniWinSimple_Common-Ordner Ihres Projekts.
  7. Erstellen Sie nun das Projekt in STM32CubeIDE neu und führen Sie es erneut aus, und Ihr neues Designfenster wird angezeigt. Die Schaltfläche im Fenster ist weg, weil example_empty.json keine definiert.

Schritt 4: Hinzufügen eines Fensters

Fenster hinzufügen
Fenster hinzufügen

Wir fügen nun der JSON-Konfigurationsdatei ein zweites Fenster hinzu und generieren den Code neu.

1. Öffnen Sie example_empty.json in einem Texteditor.

2. Unter dem Abschnitt "Windows" gibt es ein Array von Fensterdefinitionen, das derzeit nur ein Fenster hat. Kopieren Sie das alles…

{

"Name": "W1", "Title": "Window 1", "X": 10, "Y": 15, "Breite": 200, "Height": 180, "Border": true, "TitleBar": true, "Sichtbar": true, "Minimiert": false }

und fügen Sie es erneut mit einem Komma ein, das die beiden Definitionen trennt.

3. Ändern Sie "W1" in "W2" und "Fenster 1" in "Fenster 2". Ändern Sie "X", "Y", "Breite" und "Höhe" auf verschiedene Werte und beachten Sie, dass die Bildschirmauflösung 240 breit und 320 hoch ist.

4. Speichern Sie die Datei und führen Sie den Codegenerator erneut aus.

5. Kopieren Sie die Dateien wie im vorherigen Schritt, erstellen Sie sie neu und führen Sie sie erneut aus. Sie haben jetzt 2 Fenster auf Ihrem Display.

Schritt 5: Hinzufügen eines Steuerelements

Hinzufügen eines Steuerelements
Hinzufügen eines Steuerelements

Jetzt fügen wir Ihrem neuen Fenster einige Steuerelemente hinzu. Bearbeiten Sie dieselbe Datei wie im vorherigen Schritt.

1. Fügen Sie in der Spezifikation für Fenster W1 ein Komma nach der letzten Einstellung ("Minimiert": false) hinzu und fügen Sie dann diesen Text hinzu

"Menüleiste": wahr, "MenuBarEnabled": true, "MenuItems": ["Fred", "Bert", "Pete", "Alf", "Ian"], "Buttons": [{ "Name": "B1", "Label": "Button1", "X": 10, "Y": 10, "Enabled": true, "Visible": true }]

Dieser Abschnitt fügt eine Menüleiste mit 5 Elementen hinzu und aktiviert sie (Menüleisten können global deaktiviert werden, probieren Sie es aus). Es fügt auch eine Schaltfläche hinzu, die aktiviert und sichtbar ist (sie können unsichtbar erstellt und später im Code sichtbar gemacht werden).

2. Generieren Sie den Code neu, kopieren Sie ihn, erstellen Sie ihn neu, führen Sie alles wie zuvor aus.

Schritt 6: Die Kontrollen etwas tun lassen

Die Steuerung etwas tun lassen
Die Steuerung etwas tun lassen

Jetzt haben wir die grundlegende Benutzeroberfläche, die wir brauchen, um etwas zu tun. In diesem Beispiel werden wir einen Farbauswahldialog öffnen, wenn die Schaltfläche in Fenster 1 gedrückt wird.

Gehen Sie zu Ihrem Projekt in STM32CubeIDE und öffnen Sie den Ordner MiniWinSimple_Common und öffnen Sie dann die Datei W1.c (der Name dieser Datei entspricht dem Feld "Name" des Fensters in der JSON-Datei, als der Code generiert wurde).

In dieser Datei finden Sie die Funktion window_W1_message_function(). Es sieht aus wie das:

void window_W1_message_function(const mw_message_t *message){ MW_ASSERT(message != (void*)0, "Null-Pointer-Parameter"); /* Nächste Zeile stoppt Compiler-Warnungen, da Variable derzeit nicht verwendet wird */ (void)window_W1_data; switch (message->message_id) { case MW_WINDOW_CREATED_MESSAGE: /* Füge hier einen beliebigen Fensterinitialisierungscode hinzu */ break; case MW_MENU_BAR_ITEM_PRESSED_MESSAGE: /* Hier den Code für die Handhabung des Fenstermenüs hinzufügen */ break; case MW_BUTTON_PRESSED_MESSAGE: if (message->sender_handle == button_B1_handle) { /* Geben Sie hier Ihren Handler-Code für dieses Steuerelement ein */ } break; Standard: /* MISRA bei Laune halten */ break; } }

Dies wird vom Window-Manager für dieses Fenster aufgerufen, wenn der Window-Manager dem Fenster mitteilen muss, dass etwas passiert ist. In diesem Fall interessiert uns, dass die einzige Schaltfläche des Fensters gedrückt wurde. In der switch-Anweisung für Nachrichtentypen sehen Sie einen Fall für MW_BUTTON_PRESSED_MESSAGE. Dieser Code wird ausgeführt, wenn die Schaltfläche gedrückt wurde. Es gibt nur eine Schaltfläche in diesem Fenster, aber es könnten mehr sein, daher wird überprüft, um welche Schaltfläche es sich handelt. In diesem Fall könnte es nur Button B1 sein (Name entspricht wieder dem Namen für den Button in der JSON-Datei).

Fügen Sie also nach dieser Fallbeschriftung den Code hinzu, um einen Farbauswahldialog zu öffnen, der wie folgt lautet:

mw_create_window_dialog_colour_chooser(10, 10, "Farbe", MW_HAL_LCD_RED, false, message->recipient_handle);

Die Parameter sind wie folgt:

  • 10, 10 ist die Position auf dem Bildschirm des Dialogs
  • "Farbe" ist der Titel des Dialogs
  • MW_HAL_LCD_RED ist die Standardfarbe, mit der der Dialog beginnt
  • false bedeutet, dass keine große Größe angezeigt wird (versuchen Sie, es auf true zu setzen und den Unterschied zu sehen)
  • message->recipient handle ist der Besitzer dieses Dialogs, in diesem Fall dieses Fenster. Das Handle eines Fensters befindet sich im Message-Parameter der Funktion. Dies ist das Fenster, an das die Dialogantwort gesendet wird.

Um den Wert der Farbe herauszufinden, die der Benutzer gewählt hat, sendet der Fenstermanager unserem Fenster eine Nachricht mit der gewählten Farbe, wenn der Benutzer im Dialog auf die Schaltfläche OK drückt. Daher müssen wir diese Nachricht auch mit einem anderen Fall in der switch-Anweisung abfangen, der so aussieht:

Fall MW_DIALOG_COLOUR_CHOOSER_OK_MESSAGE:

{ mw_hal_lcd_colour_t selected_colour = message->message_data; (void)chosen_colour; } brechen;

Wir machen noch nichts mit der gewählten Farbe, also wandeln wir sie einfach in void um, um eine Compiler-Warnung zu verhindern. Der endgültige Code dieser Funktion sieht nun so aus:

void window_W1_message_function(const mw_message_t *message)

{ MW_ASSERT(Nachricht != (void*)0, "Nullzeigerparameter"); /* Nächste Zeile stoppt Compiler-Warnungen, da Variable derzeit nicht verwendet wird */ (void)window_W1_data; switch (message->message_id) { case MW_WINDOW_CREATED_MESSAGE: /* Füge hier einen beliebigen Fensterinitialisierungscode hinzu */ break; case MW_MENU_BAR_ITEM_PRESSED_MESSAGE: /* Hier den Code für die Handhabung des Fenstermenüs hinzufügen */ break; case MW_BUTTON_PRESSED_MESSAGE: if (message->sender_handle == button_B1_handle) { /* Geben Sie hier Ihren Handler-Code für dieses Control ein */ mw_create_window_dialog_colour_chooser(10, 10, "Colour", MW_HAL_LCD_RED, false, message->recipient_handle); } brechen; Fall MW_DIALOG_COLOUR_CHOOSER_OK_MESSAGE: { mw_hal_lcd_colour_t selected_colour = message->message_data; (void)chosen_colour; } brechen; Standard: /* MISRA bei Laune halten */ break; } }

Das Ausführen des Codes wird in der Abbildung oben gezeigt. Möglicherweise stellen Sie fest, dass Sie, wenn ein Dialogfeld angezeigt wird, darauf reagieren und es schließen müssen, bevor Sie etwas anderes tun. Dies wird als modales Verhalten bezeichnet. Dialoge in MiniWin und alle sind immer global modal und Sie können immer nur eine Anzeige gleichzeitig haben. Hier gibt es weitere Erklärungen…

en.wikipedia.org/wiki/Modal_window

Schritt 7: Zeichnen im Fenster

Zeichnen im Fenster
Zeichnen im Fenster

Bisher haben wir nur Steuerelemente verwendet, und sie zeichnen sich selbst. Es ist Zeit, einige benutzerdefinierte Zeichnungen an unserem Fenster zu machen. Der Teil, auf den Sie zeichnen können, befindet sich innerhalb der Ränder (falls vorhanden, sind sie optional), innerhalb der Bildlaufleisten (falls definiert, auch optional) und unterhalb der Titelleiste (falls vorhanden, ist auch dies optional). In der Windows-Terminologie wird er als Client-Bereich bezeichnet.

In MiniWin gibt es eine Bibliothek mit Grafikbefehlen, die Sie verwenden können. Sie alle sind fensterbewusst. Das bedeutet, dass Sie sich keine Gedanken darüber machen müssen, ob das Fenster sichtbar ist, teilweise von anderen Fenstern verdeckt, auf, teilweise aus oder vollständig vom Bildschirm entfernt ist oder ob sich die Koordinaten der Zeichnungsposition im Kundenbereich oder darüber hinaus befinden. Es ist alles für Sie erledigt. Sie können nicht außerhalb Ihres Kundenbereichs zeichnen.

Das Zeichnen auf Client-Bereichen wird in der Windows-Terminologie als Malen bezeichnet und jedes Fenster hat eine Malfunktion, in der Sie Ihre Zeichnung erstellen. Sie rufen Ihre Paint-Funktion nicht auf, der Window-Manager erledigt dies bei Bedarf für Sie. Es wird benötigt, wenn ein Fenster verschoben wird oder ein anderes Fenster darüber seine Position oder Sichtbarkeit ändert. Wenn Sie Ihr Fenster neu zeichnen müssen, weil sich einige der Daten geändert haben, von denen der Inhalt des Fensters abhängt (dh Sie wissen, dass ein Neuzeichnen erforderlich ist, anstatt dass der Fenstermanager es weiß), dann teilen Sie dem Fenstermanager mit, dass ein Neulackieren erforderlich ist, und er ruft Ihre Lackierfunktion. Du nennst es nicht selbst. (Dies wird alles im nächsten Abschnitt demonstriert).

Zuerst müssen Sie Ihre Malfunktion finden. Der Codegenerator erstellt es für Sie und befindet sich direkt über der im vorherigen Abschnitt modifizierten Message-Handler-Funktion. Gehen Sie zu Ihrem Projekt und öffnen Sie die Datei W1.c erneut.

In dieser Datei finden Sie die Funktion window_W1_paint_function(). Es sieht aus wie das:

void window_W1_paint_function(mw_handle_t window_handle, const mw_gl_draw_info_t *draw_info)

{ MW_ASSERT(draw_info != (void*)0, "Nullzeigerparameter"); /* Client-Bereich des Fensters mit durchgehendem Weiß füllen */ mw_gl_set_fill(MW_GL_FILL); mw_gl_set_solid_fill_colour(MW_HAL_LCD_WHITE); mw_gl_set_border(MW_GL_BORDER_OFF); mw_gl_clear_pattern(); mw_gl_rectangle(draw_info, 0, 0, mw_get_window_client_rect(window_handle).width, mw_get_window_client_rect(window_handle).height); /* Fügen Sie hier Ihren Fenster-Malcode hinzu */ }

Dies ist der nackte, wie generierte Code und alles, was er tut, ist, den Client-Bereich mit durchgehendem Weiß zu füllen. Lassen Sie uns einen gelb gefüllten Kreis im Kundenbereich zeichnen. Zuerst müssen wir das Konzept eines Grafikkontexts (eine andere Windows-Sache) verstehen. Wir legen Zeichenparameter im Grafikkontext fest und rufen dann eine generische Kreiszeichenroutine auf. In diesem Beispiel müssen wir einstellen, ob der Kreis einen Rahmen hat, einen Rahmenlinienstil, eine Rahmenfarbe, ob der Kreis gefüllt ist, eine Füllfarbe und ein Füllmuster. Sie können den obigen Code sehen, der etwas Ähnliches zum Füllen des Clientbereichs mit einem randlosen, ausgefüllten weißen Rechteck macht. Die Werte im Grafikkontext werden nicht zwischen jedem Aufruf der Paint-Funktion gespeichert, sodass Sie die Werte jedes Mal neu einrichten müssen (sie werden jedoch mit der Paint-Funktion gespeichert).

Im obigen Code sehen Sie, dass die Füllung aktiviert und das Füllmuster deaktiviert ist, sodass wir diese nicht erneut festlegen müssen. Wir müssen den Rahmen aktivieren, den Rahmenlinienstil auf Vollton setzen, die Vordergrundfarbe des Rahmens auf Schwarz und die Füllfarbe auf Gelb wie folgt setzen:

mw_gl_set_fg_colour(MW_HAL_LCD_BLACK);

mw_gl_set_solid_fill_colour(MW_HAL_LCD_YELLOW); mw_gl_set_line(MW_GL_SOLID_LINE); mw_gl_set_border(MW_GL_BORDER_ON); mw_gl_circle(draw_info, window_simple_data.circle_x, window_simple_data.circle_y, 25);

Fügen Sie diesen Code im Kommentar in dieser Funktion hinzu, wo es heißt, Ihren Code hinzuzufügen. Als nächstes müssen wir einen Kreis zeichnen, der so gemacht wird:

mw_gl_circle(draw_info, 30, 30, 15);

Dies zeichnet einen Kreis an den Koordinaten 30, 30 mit Radius 15. Erstellen Sie den Code neu und führen Sie ihn erneut aus und Sie sehen einen Kreis im Fenster wie oben gezeigt. Sie werden feststellen, dass sich der Kreis und die Schaltfläche überlappen, die Schaltfläche jedoch oben liegt. Dies ist beabsichtigt. Steuerelemente befinden sich immer über allem, was Sie im Kundenbereich zeichnen.

Schritt 8: Fensterdaten

Fensterdaten
Fensterdaten

Bisher haben wir unseren eigenen Code in die Message-Funktion von Window 1 (um eingehende Nachrichten zu verarbeiten) und seine Paint-Funktion (um auf den Client-Bereich des Fensters zu zeichnen) implementiert. Jetzt ist es an der Zeit, die beiden zu verknüpfen. Lassen Sie uns den in der Malfunktion gezeichneten Kreis mit der Farbe füllen, die der Benutzer beim Drücken der Schaltfläche mit dem Farbwähler auswählt. Denken Sie daran, dass wir nicht die Paint-Funktion aufrufen, sondern der Window-Manager, sodass unsere Message-Funktion (die die gewählte Farbe kennt) die Paint-Funktion selbst nicht direkt aufrufen kann. Stattdessen müssen wir die Daten zwischenspeichern und dem Fenstermanager mitteilen, dass ein Repaint erforderlich ist. Der Windowmanager ruft dann die Paint-Funktion auf, die die zwischengespeicherten Daten verwenden kann.

Oben in W1.c sehen Sie eine leere Datenstruktur und ein Objekt dieses Typs, das vom Codegenerator wie folgt deklariert wurde:

typedef-Struktur

{ /* Fügen Sie hier Ihre Datenelemente hinzu */ char dummy; /* Einige Compiler beschweren sich über leere Strukturen; entfernen Sie dies, wenn Sie Ihre Mitglieder hinzufügen */ } window_W1_data_t; statisches Fenster_W1_Daten_t Fenster_W1_Daten;

Hier speichern wir unsere Daten, damit sie über Aufrufe hinweg erhalten bleiben und als Fensterdaten bezeichnet werden. Wir müssen hier nur die gewählte Farbe wie folgt speichern:

typedef-Struktur

{ /* Fügen Sie hier Ihre Datenelemente hinzu */ mw_hal_lcd_colour_t selected_colour; } window_W1_data_t; statisches window_W1_data_t window_W1_data = { MW_HAL_LCD_YELLOW };

Wir geben ihm eine Startfarbe von Gelb. Jetzt ändern wir in der Nachrichtenfunktion den Code leicht, um die gewählte Farbe hier wie folgt zu speichern:

Fall MW_DIALOG_COLOUR_CHOOSER_OK_MESSAGE:

{ window_W1_data.chosen_colour = message->message_data; } brechen;

Dann ändern wir die Paint-Funktion, um diesen Wert zu verwenden, wenn der Kreis wie folgt gezeichnet wird:

mw_gl_set_solid_fill_colour(window_W1_data.chosen_colour);

Jetzt haben wir die Daten geändert, von denen der Inhalt des Fensters abhängt, also müssen wir dem Fenstermanager mitteilen, dass das Fenster neu gezeichnet werden muss. Wir tun dies in der Nachrichtenfunktion, wenn der Dialog OK-Nachricht empfangen wird, wie folgt:

mw_paint_window_client(message->recipient_handle);

Dies führt nicht dazu, dass das Fenster direkt lackiert wird. Es ist eine Dienstprogrammfunktion, die eine Nachricht an den Fenstermanager sendet, dass ein Fenster neu gezeichnet werden muss (wenn Sie hineingehen, können Sie sehen, wie dies geschieht). Das Fenster, das in diesem Fall neu gezeichnet werden muss, ist es selbst, und das Handle für das Fenster befindet sich im Message-Parameter der Message-Handler-Funktion.

Die gesamte Datei sieht jetzt so aus, wenn Sie sich nicht sicher sind, wohin einige der obigen Codeschnipsel gehen:

#enthalten

#include "miniwin.h" #include "miniwin_user.h" #include "W1.h" typedef struct { /* Fügen Sie hier Ihre Datenelemente hinzu */ mw_hal_lcd_colour_t selected_colour; } window_W1_data_t; statisches window_W1_data_t window_W1_data = { MW_HAL_LCD_YELLOW }; void window_W1_paint_function(mw_handle_t window_handle, const mw_gl_draw_info_t *draw_info) { MW_ASSERT(draw_info != (void*)0, "Nullzeigerparameter"); /* Client-Bereich des Fensters mit durchgehendem Weiß füllen */ mw_gl_set_fill(MW_GL_FILL); mw_gl_set_solid_fill_colour(MW_HAL_LCD_WHITE); mw_gl_set_border(MW_GL_BORDER_OFF); mw_gl_clear_pattern(); mw_gl_rectangle(draw_info, 0, 0, mw_get_window_client_rect(window_handle).width, mw_get_window_client_rect(window_handle).height); /* Fügen Sie hier Ihren Window Painting Code hinzu */ mw_gl_set_fg_colour(MW_HAL_LCD_BLACK); mw_gl_set_solid_fill_colour(window_W1_data.chosen_colour); mw_gl_set_line(MW_GL_SOLID_LINE); mw_gl_set_border(MW_GL_BORDER_ON); mw_gl_circle(draw_info, 30, 30, 15); } void window_W1_message_function(const mw_message_t *message) { MW_ASSERT(message!= (void*)0, "Null-Zeigerparameter"); /* Nächste Zeile stoppt Compiler-Warnungen, da Variable derzeit nicht verwendet wird */ (void)window_W1_data; switch (message->message_id) { case MW_WINDOW_CREATED_MESSAGE: /* Füge hier einen beliebigen Fensterinitialisierungscode hinzu */ break; case MW_MENU_BAR_ITEM_PRESSED_MESSAGE: /* Hier den Code für die Handhabung des Fenstermenüs hinzufügen */ break; case MW_BUTTON_PRESSED_MESSAGE: if (message->sender_handle == button_B1_handle) { /* Geben Sie hier Ihren Handler-Code für dieses Control ein */ mw_create_window_dialog_colour_chooser(10, 10, "Colour", MW_HAL_LCD_RED, false, message->recipient_handle); } brechen; Fall MW_DIALOG_COLOUR_CHOOSER_OK_MESSAGE: { window_W1_data.chosen_colour = message->message_data; mw_paint_window_client(message->recipient_handle); } brechen; Standard: /* MISRA bei Laune halten */ break; } }

Erstellen und erneut ausführen und Sie sollten in der Lage sein, die Füllfarbe des Kreises einzustellen.

Dieses Beispiel für Fensterdaten verwendet Daten, die in einer statischen Datenstruktur oben in der Quelldatei gespeichert sind. Dies ist in Ordnung, wenn Sie nur eine Instanz des Fensters haben, wie in diesem Beispiel, aber wenn Sie mehr als eine Instanz haben, teilen sich alle dieselbe Datenstruktur. Es ist möglich, pro Instanz Daten zu haben, sodass mehrere Instanzen desselben Fenstertyps ihre eigenen Daten haben. Dies wird in der MiniWin-Dokumentation im docs-Verzeichnis erklärt. Das Dateibeispiel verwendet es, um mehrere Bilder im gleichen Fenstertyp anzuzeigen (wie im Hauptbild ganz oben in dieser Anleitung zu sehen).

Schritt 9: Etwas letzter Schriftspaß

Etwas letzter Schriftspaß
Etwas letzter Schriftspaß

MiniWin unterstützt das Rendern von TrueType-Schriftarten. Wenn es eine Sache gibt, die Ihre Benutzeroberfläche gut aussehen lässt, dann sind es attraktive Schriftarten. Dieser letzte Schritt zeigt, wie Sie eine TrueType-Schriftart in einem MiniWin-Fenster rendern.

Es gibt zwei Möglichkeiten zum Rendern von TrueType-Schriftarten. Eine besteht darin, sie direkt in Ihren Kundenbereich zu zeichnen, wie es zuvor für den Kreis getan wurde, die andere besteht darin, ein Textfeld-Steuerelement in Ihr Fenster einzufügen. Wir machen letzteres, da es einfacher ist.

Jetzt fügen wir unserer JSON-Konfigurationsdatei ein Textfeld-Steuerelement hinzu. Fügen Sie es der Definition von Window 2 hinzu, sodass es wie folgt aussieht:

so was:

{

"Name": "W2", "Title": "Window 2", "X": 50, "Y": 65, "Width": 100, "Height": 80, "Border": true, "TitleBar": true, "Visible": true, "Minimized": false, "TextBoxes": [{ "Name": "TB1", "X": 0, "Y": 0, "Width": 115, "Height": 50, "Justification": "Centre", "BackgroundColour": "MW_HAL_LCD_YELLOW", "ForegroundColour": "MW_HAL_LCD_BLACK", "Font": "mf_rlefont_BLKCHCRY16", "Enabled": true, "Visible": true }] }

Ein kurzes Wort zu TrueType-Schriftarten in MiniWin. Schriftarten kommen in.ttf-Dateien. In Fenstermanagern auf größeren Computern werden diese bei Bedarf auf Ihrem Bildschirm gerendert. Dies erfordert viel Rechenleistung und Speicher und ist nicht für kleine Geräte geeignet. In MiniWin werden sie zu Bitmaps vorverarbeitet und zur Kompilierzeit mit einer festen Schriftgröße und einem festen Stil (fett, kursiv usw.) verknüpft, d. Dies wurde für Sie für zwei Beispielschriftarten in der heruntergeladenen MiniWin-ZIP-Datei durchgeführt. Wenn Sie andere Schriftarten in anderen Größen und Stilen verwenden möchten, lesen Sie die MiniWin-Dokumentation im Ordner docs. In MiniWin für Windows und Linux gibt es Tools zum Vorverarbeiten von.ttf-Dateien in Quellcodedateien, die Sie in Ihr Projekt einfügen können.

Und noch ein kurzes Wort: Die meisten Schriftarten sind urheberrechtlich geschützt, einschließlich derjenigen, die Sie in Microsoft Windows finden. Verwenden Sie sie nach Belieben für den persönlichen Gebrauch, aber alles, was Sie veröffentlichen, müssen Sie sicherstellen, dass die Lizenz, mit der die Schriftarten veröffentlicht werden, dies zulässt, wie dies bei den beiden in MiniWin enthaltenen Schriftarten der Fall ist, jedoch nicht bei den Schriftarten von Microsoft!

Zurück zum Code! Generieren Sie Dateien, legen Sie sie ab, erstellen Sie sie und führen Sie sie erneut aus wie zuvor, und Sie werden sehen, dass Windows 2 jetzt einen Standardtext auf gelbem Hintergrund in einer verrückten Schriftart hat. Lassen Sie uns den Text ändern, indem wir die Quelldatei W2.c von Window 2 bearbeiten.

Wir müssen mit dem gerade erstellten Textfeld kommunizieren, und Sie tun dies wie bei jeder Kommunikation in MiniWin, indem Sie ihm eine Nachricht senden. Wir möchten den Text im Steuerelement festlegen, wenn das Fenster erstellt wird, aber bevor es angezeigt wird, daher fügen wir Code im Nachrichtenhandler im Fall MW_WINDOW_CREATED_MESSAGE hinzu. Diese wird vom Fenstercode kurz vor der Anzeige des Fensters empfangen und ist für solche Initialisierungen gedacht. Der Codegenerator hat einen Platzhalter erstellt, der in der Message-Handler-Funktion wie folgt aussieht:

Fall MW_WINDOW_CREATED_MESSAGE:

/* Fügen Sie hier einen beliebigen Fensterinitialisierungscode hinzu */ break;

Hier werden wir eine Nachricht an das Textfeld-Steuerelement senden, die ihm mitteilt, welchen Text es anzeigen soll, indem wir die Funktion mw_post_message wie folgt verwenden:

Fall MW_WINDOW_CREATED_MESSAGE:

/* Fügen Sie hier einen beliebigen Fensterinitialisierungscode hinzu */ mw_post_message(MW_TEXT_BOX_SET_TEXT_MESSAGE, message->recipient_handle, text_box_TB1_handle, 0UL, "Es war eine dunkle und stürmische Nacht…", MW_CONTROL_MESSAGE); brechen;

Dies sind die Parameter:

  • MW_TEXT_BOX_SET_TEXT_MESSAGE - Dies ist der Nachrichtentyp, den wir an die Steuerung senden. Sie sind in miniwin.h aufgelistet und in der Dokumentation dokumentiert.
  • message->recipient_handle - Dies ist, von wem die Nachricht stammt - dieses Fenster - dessen Handle im Message-Parameter steht, der an die Message-Handler-Funktion übergeben wird.
  • text_box_TB1_handle – An wen wir die Nachricht senden – das Handle des Textfeld-Steuerelements. Diese sind in der generierten Datei miniwin_user.h aufgelistet.
  • 0UL - Datenwert, in diesem Fall nichts.
  • "Es war eine dunkle und stürmische Nacht…" - Zeigerwert - der neue Text.
  • MW_CONTROL_MESSAGE - Empfängertyp, der ein Steuerelement ist.

Das ist es. Erstellen Sie wie gewohnt neu und führen Sie sie erneut aus, und Sie erhalten das Textfeld, das wie im Bild oben angezeigt wird.

Das Posten von Nachrichten ist für MiniWin (wie für alle Fenstermanager) von grundlegender Bedeutung. Weitere Beispiele finden Sie in den Beispielprojekten in der ZIP-Datei und für eine umfassende Erklärung lesen Sie den Abschnitt zu MiniWin-Meldungen in der Dokumentation.

Schritt 10: Weiter gehen

Image
Image

Das war's für diese grundlegende Einführung in MiniWin. MiniWin kann viel mehr, als hier gezeigt wurde. Zum Beispiel ist der Bildschirm auf der Platine, der in dieser Anleitung verwendet wird, klein und die Bedienelemente sind klein und müssen mit einem Dibber verwendet werden. Andere Beispiele und Hardware verwenden jedoch größere Bedienelemente (es gibt 2 Größen) auf größeren Displays und diese können mit dem Finger bedient werden.

Es gibt viele andere Arten der Kontrolle als die hier gezeigten. Für weitere Kontrollen schauen Sie sich die verschiedenen JSON-Beispieldateien im Codegenerator-Ordner an. Alle Steuerungstypen werden in diesen Beispielen behandelt.

Windows bietet viele Möglichkeiten. Der Rahmen, die Titelleiste und die Symbole sind alle konfigurierbar. Sie können Bildlaufleisten und Bildlauffenster-Clientbereiche haben, mehrere Instanzen des gleichen Fenstertyps und Fenster können nackt sein (nur ein Clientbereich, kein Rahmen oder Titelleiste), was bedeutet, dass sie zur Kompilierzeit auf dem Display fixiert sind (sehen Sie das Bild in diesem Abschnitt mit großen Symbolen - dies sind tatsächlich 6 nackte Fenster).

MiniWin verwendet keinen dynamischen Speicher. Dies macht es für kleine eingeschränkte Geräte geeignet und ist eine Voraussetzung für einige eingebettete Projekte. MiniWin und der von ihm generierte Code sind auch vollständig MISRA 2012-kompatibel auf dem "erforderlichen" Niveau.

Weitere Informationen finden Sie im docs-Ordner für die Dokumentation und auch die anderen Beispiel-Apps in der Zip-Datei. Hier finden Sie Beispiele, die zeigen, wie Sie alle Funktionen von MiniWin verwenden und wie Sie MiniWin mit FatFS und FreeRTOS integrieren.