Sommario:

Gestore finestre integrato: 10 passaggi
Gestore finestre integrato: 10 passaggi

Video: Gestore finestre integrato: 10 passaggi

Video: Gestore finestre integrato: 10 passaggi
Video: WINDOWS 10/11 - Come formattare e gestire le partizioni di un disco 2024, Luglio
Anonim
Gestore finestre integrato
Gestore finestre integrato
Gestore finestre integrato
Gestore finestre integrato
Gestore finestre integrato
Gestore finestre integrato
Gestore finestre integrato
Gestore finestre integrato

Questo progetto mostra come implementare un gestore di finestre con finestre sovrapposte mobili su un microcontrollore incorporato con un pannello LCD e un touch screen. Esistono pacchetti software disponibili in commercio per farlo, ma costano denaro e sono closed source. Questo, chiamato MiniWin, è gratuito e open-source. È scritto in C99 completamente conforme e può essere utilizzato in un'applicazione C o C++. Gli obiettivi di MiniWin sono di essere facile da usare, facile da modificare, espandibile, portabile su un'ampia gamma di hardware e non troppo affamato di risorse.

Oltre a fornire il codice per gestire le tue finestre, MiniWin ha una raccolta di controlli dell'interfaccia utente: pulsanti, cursori, barre di avanzamento, alberi, ecc. Puoi avere più finestre di tipo diverso o più istanze dello stesso tipo. Le finestre possono essere spostate, ridimensionate, ingrandite, ridotte a icona, chiuse: tutte le solite cose che si fanno con le finestre in gestori di finestre più grandi. Sono supportati anche i caratteri TrueType con crenatura e anti-aliasing (rende il testo liscio) per un rendering del testo attraente.

In ogni finestra hai un'area client (il tuo spazio all'interno del bordo e sotto la barra in alto). Su questo puoi aggiungere controlli per creare una finestra di dialogo oppure puoi utilizzare la libreria grafica integrata per disegnare quello che vuoi. Tutte le funzioni della libreria grafica sono a conoscenza delle finestre. Non devi preoccuparti di dove si trova la tua finestra, di cosa si sovrappone o se è ridotta a icona.

Oltre a creare finestre personalizzate, sono incluse anche alcune finestre di dialogo standard che sono molto facili da istanziare, ad esempio finestre di dialogo di conferma (solo un pulsante OK o Sì/No), impostazioni di data e ora, opzioni di selezione file, opzioni di selezione colore, ecc.

MiniWin utilizza un sistema di code di messaggi di progettazione di Windows Manager standard. Le finestre possono interagire tra loro e con il gestore di finestre tramite messaggi. Non chiami funzioni per fare le cose direttamente, aggiungi un messaggio alla coda e il gestore di finestre lo eseguirà per te.

MiniWin è stato portato su schede di sviluppo standard con display touch screen dei fornitori di microcontrollori ST, NXP e Renesas. Ci sono driver hardware e progetti di esempio per tutti questi dispositivi. Inoltre MiniWin può essere creato per Windows o Linux in modo da poter simulare il codice dell'interfaccia utente prima di ottenere l'hardware integrato.

MiniWin ha un generatore di codice. Puoi specificare le finestre e i controlli in un file JSON leggibile dall'uomo semplice da creare e il generatore di codice analizza il file e crea il codice per te (ci sono molti esempi da seguire). Crea applicazioni di simulazione complete Windows o Linux che possono essere semplicemente costruite e c'è il tuo display LCD simulato con le tue finestre MiniWin funzionanti. Puoi prendere esattamente lo stesso codice generato e rilasciarlo in un progetto incorporato e avere lo stesso codice che mostra le stesse finestre e controlli pochi istanti dopo sul tuo hardware incorporato.

MiniWin non richiede alcun supporto operativo sul dispositivo embedded. Funziona tutto in un unico thread. MiniWin può essere integrato con un RTOS in esecuzione su un processore embedded e ci sono esempi di integrazione di MiniWin con FreeRTOS.

Questa istruzione mostra come far funzionare MiniWin su un processore STM32 M4 utilizzando la scheda Discovery STM32F429 economica che viene fornita con un display touch screen QVGA già collegato. Questi sono facilmente disponibili presso il fornitore di componenti elettronici.

MiniWin funziona su microcontrollori di fascia media e superiori.

Forniture

Scheda di sviluppo STM32F429I-DISC1 e un cavo micro USB

Scarica STM32CubeIDE che è gratuito.

Passaggio 1: ottenere il codice

Ottenere il codice
Ottenere il codice

Prima di tutto hai bisogno di STM32CubeIDE installato. Lo trovi dal sito web della ST. Devi registrarti e ci vuole un po' per scaricarlo e installarlo. È tutto gratis.

Durante l'installazione, scarica il sorgente MiniWin e decomprimilo. È grande, ma ne utilizzerai solo una piccola parte. Fai clic sul pulsante verde "Clona o scarica" qui…

github.com/miniwinwm/miniwinwm

quindi scegli Scarica Zip. Decomprimi il contenuto.

Passaggio 2: creazione di un progetto di esempio

Costruire un progetto di esempio
Costruire un progetto di esempio
Costruire un progetto di esempio
Costruire un progetto di esempio

Per prima cosa costruiamo uno dei progetti di esempio. Uno buono si chiama MiniWinSimple. Avvia STM32CubeIDE quindi fai questo:

  1. Scegli File|Importa…
  2. Apri Generale e scegli Progetto esistente nell'area di lavoro. Prossimo.
  3. Fai clic su Sfoglia e vai al punto in cui hai decompresso MiniWin. Quindi vai alla cartella STM32CubeIDE\MiniWinSimple\STM32F429. Fare clic su Seleziona cartella.
  4. In Project: selezionare MiniWinSimple_STM32F429 quindi fare clic su Fine.
  5. Il progetto MiniWinSimple_STM32F429 apparirà nel tuo Project Explorer. Selezionalo e poi costruiscilo con Project|Build Project.
  6. Ora collega il cavo USB alla scheda e al computer ed eseguilo utilizzando Esegui|Debug e quando viene scaricato scegli Esegui|Riprendi. La prima volta otterrai un display di calibrazione dello schermo, quindi tocca il centro delle 3 croci sul display LCD. Ora puoi interagire con la finestra sul display.

Per spostare una finestra trascinala vicino alla sua barra del titolo. Per ridimensionare una finestra, usa l'icona del triangolo bianco a sinistra della barra del titolo. Le finestre di MiniWin non possono essere ridimensionate trascinando i bordi poiché i display su cui viene utilizzato MiniWin sono troppo piccoli. Per ridurre a icona, ingrandire o chiudere una finestra, utilizzare le icone all'estremità destra della barra del titolo (la chiusura potrebbe essere disabilitata). Quando una finestra è ridotta a icona non è possibile spostare le icone ridotte a icona. Si accumulano dal basso da sinistra a destra.

Passaggio 3: eseguire il generatore di codice

Esecuzione del generatore di codice
Esecuzione del generatore di codice

Ora cambieremo il progetto di esempio generando alcune finestre nostre e inserendo il nuovo codice. Per farlo eseguiremo il generatore di codice.

  1. Apri un prompt dei comandi e vai alla cartella in cui hai decompresso MiniWin e poi alla cartella Tools\CodeGen.
  2. L'eseguibile per Windows CodeGen.exe è già disponibile. Per Linux devi compilarlo digitando make. (Puoi anche compilarlo dal sorgente per Windows se sei preoccupato di eseguire un eseguibile scaricato ma hai bisogno del compilatore e dell'ambiente di sviluppo installati. Consulta la documentazione di MiniWin nella cartella docs per i dettagli).
  3. In questa cartella ci sono alcuni file JSON di esempio. Useremo example_empty.json. Devi prima modificarlo per configurarlo per Windows o Linux. Aprilo in un editor e nella parte superiore dove troverai "TargetType" cambia il valore "Linux" o "Windows" su quello su cui stai eseguendo il generatore di codice.
  4. Ora digita codegen example_empty.json nel prompt dei comandi.
  5. Vai al tuo progetto in STM32CubeIDE e apri la cartella MiniWinSimple_Common. Elimina tutti i file lì dentro.
  6. Abbiamo lasciato il "TargetName" nel file JSON come predefinito su "MiniWinGen", quindi questo è il nome della nostra cartella di codice generato. Vai alla cartella in cui hai decompresso MiniWin e poi la cartella MiniWinGen_Common. Ora seleziona tutti questi file e trascinali in STM32CubeIDE nella cartella MiniWinSimple_Common del tuo progetto.
  7. Ora ricostruisci e riesegui il progetto in STM32CubeIDE e apparirà la tua nuova finestra di progettazione. Il pulsante nella finestra è sparito perché example_empty.json non ne definisce nessuno.

Passaggio 4: aggiunta di una finestra

Aggiunta di una finestra
Aggiunta di una finestra

Ora aggiungeremo una seconda finestra al file di configurazione JSON e rigenereremo il codice.

1. Aprire example_empty.json in un editor di testo.

2. Nella sezione "Windows" c'è una serie di definizioni di Windows che attualmente ha solo una finestra. Copia tutto questo…

{

"Nome": "W1", "Titolo": "Finestra 1", "X": 10, "Y": 15, "Larghezza": 200, "Altezza": 180, "Bordi": true, "TitleBar": vero, "Visibile": vero, "Ridotto a icona": falso }

e incollalo di nuovo con una virgola che separa le 2 definizioni.

3. Modificare "W1" in "W2" e "Finestra 1" in "Finestra 2". Cambia "X", "Y", "Larghezza" e "Altezza" con alcuni valori diversi tenendo presente che la risoluzione dello schermo è 240 di larghezza per 320 di altezza.

4. Salvare il file ed eseguire nuovamente il generatore di codice.

5. Copiare i file come nel passaggio precedente, ricostruire ed eseguire nuovamente. Ora avrai 2 finestre sul tuo display.

Passaggio 5: aggiunta di un controllo

Aggiunta di un controllo
Aggiunta di un controllo

Ora aggiungeremo alcuni controlli alla tua nuova finestra. Modifica lo stesso file del passaggio precedente.

1. Nella specifica per la finestra W1 aggiungi una virgola dopo l'ultima impostazione ("Ridotto a icona": false), quindi aggiungi questo testo

"MenuBar": vero, "MenuBarEnabled": true, "MenuItems": ["Fred", "Bert", "Pete", "Alf", "Ian"], "Buttons": [{ "Name": "B1", "Label": "Pulsante1", "X": 10, "Y": 10, "Abilitato": vero, "Visibile": vero }]

Questa sezione aggiunge una barra dei menu con 5 elementi e la abilita (le barre dei menu possono essere disabilitate globalmente, provalo). Aggiunge anche un pulsante che è abilitato e visibile (possono essere creati invisibili e quindi resi visibili nel codice in seguito).

2. Rigenera il codice, copialo, ricostruisci, riesegui tutto come prima.

Passaggio 6: fare in modo che i controlli facciano qualcosa

Fare in modo che i controlli facciano qualcosa
Fare in modo che i controlli facciano qualcosa

Ora abbiamo l'interfaccia utente di base di cui abbiamo bisogno per fargli fare qualcosa. Per questo esempio verrà visualizzata una finestra di dialogo per la scelta del colore quando viene premuto il pulsante nella Finestra 1.

Vai al tuo progetto in STM32CubeIDE e apri la cartella MiniWinSimple_Common e quindi apri il file W1.c (il nome di questo file corrisponde al campo "Nome" della finestra nel file JSON quando è stato generato il codice).

In questo file troverai la funzione window_W1_message_function(). Sembra così:

void window_W1_message_function(const mw_message_t *message){ MW_ASSERT(message != (void*)0, "Parametro puntatore nullo"); /* La riga successiva interrompe gli avvisi del compilatore poiché la variabile non è attualmente utilizzata */ (void)window_W1_data; switch (message->message_id) { case MW_WINDOW_CREATED_MESSAGE: /* Aggiungi qui qualsiasi codice di inizializzazione della finestra */ break; case MW_MENU_BAR_ITEM_PRESSED_MESSAGE: /* Aggiungi qui il codice di gestione del menu della finestra */ break; case MW_BUTTON_PRESSED_MESSAGE: if (message->sender_handle == button_B1_handle) { /* Aggiungi qui il tuo codice gestore per questo controllo */ } break; default: /* Mantieni felice MISRA */ break; } }

Questo viene chiamato dal window manager per questa finestra ogni volta che il window manager ha bisogno di far sapere alla finestra che è successo qualcosa. In questo caso ci interessa sapere che è stato premuto l'unico pulsante della finestra. Nell'istruzione switch per i tipi di messaggio vedrai un caso per MW_BUTTON_PRESSED_MESSAGE. Questo codice viene eseguito quando il pulsante è stato premuto. C'è solo un pulsante in questa finestra, ma potrebbero essercene di più, quindi viene effettuato un controllo su quale pulsante si trova. In questo caso potrebbe essere solo il pulsante B1 (il nome corrisponde di nuovo al nome del pulsante nel file JSON).

Quindi, dopo questa etichetta del caso, aggiungi il codice per far apparire una finestra di dialogo per la scelta del colore, che è questa:

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

I parametri sono i seguenti:

  • 10, 10 è la posizione sullo schermo della finestra di dialogo
  • "Colore" è il titolo della finestra di dialogo
  • MW_HAL_LCD_RED è il colore predefinito con cui inizierà la finestra di dialogo
  • false significa che non mostrano grandi dimensioni (prova a impostarlo su true e vedi la differenza)
  • messaggio->l'handle del destinatario è il proprietario di questa finestra di dialogo, in questo caso è questa finestra. L'handle di una finestra si trova nel parametro message della funzione. Questa è la finestra a cui verrà inviata la risposta della finestra di dialogo.

Per scoprire il valore del colore scelto dall'utente, il window manager invierà alla nostra finestra un messaggio con il colore scelto quando l'utente preme il pulsante OK nella finestra di dialogo. Pertanto dobbiamo intercettare anche questo messaggio con un altro caso nell'istruzione switch che assomiglia a questo:

caso MW_DIALOG_COLOUR_CHOOSER_OK_MESSAGE:

{ mw_hal_lcd_colour_t colore_scelto = messaggio->dati_messaggio; (vuoto)colore_scelto; } rottura;

Non stiamo ancora facendo nulla con il colore scelto, quindi basta lanciarlo su void per evitare un avviso del compilatore. Il codice finale di questa funzione ora assomiglia a questo:

void window_W1_message_function(const mw_message_t *message)

{ MW_ASSERT(message != (void*)0, "Parametro puntatore nullo"); /* La riga successiva interrompe gli avvisi del compilatore poiché la variabile non è attualmente utilizzata */ (void)window_W1_data; switch (message->message_id) { case MW_WINDOW_CREATED_MESSAGE: /* Aggiungi qui qualsiasi codice di inizializzazione della finestra */ break; case MW_MENU_BAR_ITEM_PRESSED_MESSAGE: /* Aggiungi qui il codice di gestione del menu della finestra */ break; case MW_BUTTON_PRESSED_MESSAGE: if (message->sender_handle == button_B1_handle) { /* Aggiungi qui il tuo codice gestore per questo controllo */ mw_create_window_dialog_colour_chooser(10, 10, "Colour", MW_HAL_LCD_RED, false, message->recipient_handle); } rottura; case MW_DIALOG_COLOUR_CHOOSER_OK_MESSAGE: { mw_hal_lcd_colour_t selected_colour = message->message_data; (vuoto)colore_scelto; } rottura; default: /* Mantieni felice MISRA */ break; } }

L'esecuzione del codice è mostrata nell'immagine sopra. Potresti notare che quando viene visualizzata una finestra di dialogo devi rispondere e ignorarla prima di fare qualsiasi altra cosa. Questo è chiamato comportamento modale. Le finestre di dialogo in MiniWin e tutte sempre globalmente modali e puoi avere solo una visualizzazione alla volta. C'è più spiegazione qui…

en.wikipedia.org/wiki/Modal_window

Passaggio 7: disegnare nella finestra

Disegnare alla finestra
Disegnare alla finestra

Finora abbiamo usato solo i controlli e si disegnano da soli. È ora di fare un disegno personalizzato sulla nostra finestra. La parte su cui puoi disegnare è all'interno dei bordi (se ce ne sono, sono facoltativi), all'interno delle barre di scorrimento (se definite, anche facoltative) e sotto la barra del titolo (se ce n'è una, anche quella è facoltativa). Si chiama area client nella terminologia della finestra.

C'è una libreria di comandi grafici in MiniWin che puoi usare. Sono tutti consapevoli della finestra. Ciò significa che non devi preoccuparti se la finestra è visibile, parzialmente oscurata da altre finestre, accesa, parzialmente spenta o completamente fuori dallo schermo, o se la coordinata di dove stai disegnando è nell'area client o oltre. È tutto a posto per te. Non puoi disegnare al di fuori della tua area cliente.

Disegnare sulle aree client nella terminologia di Windows è chiamato pittura e ogni finestra ha una funzione di disegno in cui si esegue il disegno. Non chiami la tua funzione di disegno, il gestore di finestre lo fa per te quando necessario. È necessario quando una finestra viene spostata o un'altra finestra in alto ha la sua posizione o la sua visibilità cambiata. Se hai bisogno di ridisegnare la tua finestra perché alcuni dei dati da cui dipende il contenuto della finestra sono cambiati (cioè sai che è necessario ridipingere piuttosto che il gestore di finestre lo sa), allora dici al gestore di finestre che è necessario ridisegnare e chiama la tua funzione di pittura. Non lo chiami tu. (Tutto questo è dimostrato nella prossima sezione).

Per prima cosa, devi trovare la tua funzione di pittura. Il generatore di codice lo crea per te ed è appena sopra la funzione del gestore dei messaggi modificata nella sezione precedente. Vai al tuo progetto e apri nuovamente il file W1.c.

In questo file troverai la funzione window_W1_paint_function(). Sembra così:

void window_W1_paint_function(mw_handle_t window_handle, const mw_gl_draw_info_t *draw_info)

{ MW_ASSERT(draw_info != (void*)0, "Parametro puntatore nullo"); /* Riempi l'area client della finestra con il bianco pieno */ 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); /* Aggiungi qui il codice per dipingere le finestre */ }

Questo è il codice appena generato e tutto ciò che fa è riempire l'area client con un bianco solido. Disegniamo un cerchio pieno di giallo nell'area client. Per prima cosa dobbiamo capire il concetto di contesto grafico (un'altra cosa di Windows). Impostiamo i parametri di disegno nel contesto grafico e quindi chiamiamo una routine di disegno circolare generica. Le cose che dobbiamo impostare in questo esempio sono se il cerchio ha un bordo, lo stile della linea del bordo, il colore del bordo, se il cerchio è pieno, il colore di riempimento e il motivo di riempimento. Puoi vedere il codice sopra che fa qualcosa di simile per riempire l'area client con un rettangolo bianco pieno senza bordi. I valori nel contesto grafico non vengono ricordati tra ogni chiamata della funzione paint, quindi devi impostare i valori ogni volta (vengono comunque ricordati con la funzione paint).

Nel codice sopra puoi vedere che il riempimento è attivo e il modello di riempimento è disattivato, quindi non è necessario impostarli di nuovo. Dobbiamo impostare il bordo su, lo stile della linea del bordo su solido, il colore del bordo in primo piano sul nero e il colore di riempimento sul giallo in questo modo:

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);

Aggiungi questo codice al commento in questa funzione dove dice di aggiungere il tuo codice. Quindi dobbiamo disegnare un cerchio che è fatto in questo modo:

mw_gl_circle(draw_info, 30, 30, 15);

Questo disegna un cerchio alle coordinate 30, 30 con raggio 15. Ricostruisci il codice e rieseguilo e vedrai un cerchio nella finestra come mostrato sopra. Noterai che il cerchio e il pulsante si sovrappongono ma il pulsante è in alto. Questo è di progettazione. I controlli sono sempre in primo piano su tutto ciò che disegni nell'area client.

Passaggio 8: dati della finestra

Dati finestra
Dati finestra

Finora abbiamo implementato il nostro codice nella funzione message di Window 1 (per gestire i messaggi in arrivo) e la sua funzione paint (per disegnare nell'area client della finestra). Ora è il momento di collegare i due. Riempiamo il cerchio disegnato nella funzione di pittura con il colore che l'utente sceglie dal selettore di colori quando è stato premuto il pulsante. Ricorda che non chiamiamo la funzione paint, lo fa il window manager, quindi la nostra funzione message (che conosce il colore scelto) non può chiamare direttamente la funzione paint. Invece abbiamo bisogno di memorizzare nella cache i dati e far sapere al gestore di finestre che è necessario ridisegnare. Il window manager chiamerà quindi la funzione paint che può utilizzare i dati memorizzati nella cache.

Nella parte superiore di W1.c vedrai una struttura dati vuota e un oggetto di questo tipo dichiarato dal generatore di codice in questo modo:

struttura typedef

{ /* Aggiungi qui i tuoi membri dati */ char dummy; /* Alcuni compilatori si lamentano delle strutture vuote; rimuovilo quando aggiungi i tuoi membri */ } window_W1_data_t; statico window_W1_data_t window_W1_data;

Qui è dove memorizziamo nella cache i nostri dati in modo che vengano preservati tra le chiamate ed è noto come dati della finestra. Abbiamo solo bisogno di memorizzare qui il colore scelto, in questo modo:

struttura typedef

{ /* Aggiungi qui i tuoi membri dati */ mw_hal_lcd_colour_t selected_colour; } window_W1_data_t; static window_W1_data_t window_W1_data = { MW_HAL_LCD_YELLOW };

Gli daremo un colore di partenza giallo. Ora nella funzione messaggio cambieremo leggermente il codice per salvare il colore scelto qui in questo modo:

caso MW_DIALOG_COLOUR_CHOOSER_OK_MESSAGE:

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

Quindi cambieremo la funzione di pittura per utilizzare questo valore quando disegna il cerchio in questo modo:

mw_gl_set_solid_fill_colour(window_W1_data.chosen_colour);

Ora abbiamo cambiato i dati da cui dipende il contenuto della finestra, quindi dobbiamo far sapere al window manager che la finestra ha bisogno di essere ridipinta. Lo facciamo nella funzione messaggio quando viene ricevuto il messaggio di dialogo OK, in questo modo:

mw_paint_window_client(message->recipient_handle);

Ciò non causa la verniciatura diretta della finestra. È una funzione di utilità che invia un messaggio al gestore di finestre che una finestra deve essere ridipinta (se ci entri puoi vedere come ciò accade). La finestra che deve essere ridisegnata in questo caso è se stessa e l'handle della finestra si trova nel parametro message della funzione del gestore del messaggio.

L'intero file ora ha questo aspetto se non sei sicuro di dove vadano alcuni dei frammenti di codice sopra:

#includere

#include "miniwin.h" #include "miniwin_user.h" #include "W1.h" typedef struct { /* Aggiungi qui i tuoi membri dati */ mw_hal_lcd_colour_t selected_colour; } window_W1_data_t; static 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, "Parametro puntatore nullo"); /* Riempi l'area client della finestra con il bianco pieno */ 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); /* Aggiungi qui il codice per dipingere le finestre */ 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, "Parametro puntatore nullo"); /* La riga successiva interrompe gli avvisi del compilatore poiché la variabile non è attualmente utilizzata */ (void)window_W1_data; switch (message->message_id) { case MW_WINDOW_CREATED_MESSAGE: /* Aggiungi qui qualsiasi codice di inizializzazione della finestra */ break; case MW_MENU_BAR_ITEM_PRESSED_MESSAGE: /* Aggiungi qui il codice di gestione del menu della finestra */ break; case MW_BUTTON_PRESSED_MESSAGE: if (message->sender_handle == button_B1_handle) { /* Aggiungi qui il tuo codice gestore per questo controllo */ mw_create_window_dialog_colour_chooser(10, 10, "Colour", MW_HAL_LCD_RED, false, message->recipient_handle); } rottura; case MW_DIALOG_COLOUR_CHOOSER_OK_MESSAGE: { window_W1_data.chosen_colour = message->message_data; mw_paint_window_client(message->recipient_handle); } rottura; default: /* Mantieni felice MISRA */ break; } }

Costruisci ed esegui di nuovo e dovresti essere in grado di impostare il colore di riempimento del cerchio.

Questo esempio di dati della finestra utilizza i dati archiviati in una struttura di dati statica nella parte superiore del file di origine. Questo va bene se hai solo un'istanza della finestra, come facciamo in questo esempio, ma se hai più di un'istanza, tutte condivideranno la stessa struttura di dati. È possibile avere dati per istanza in modo che più istanze dello stesso tipo di finestra abbiano i propri dati. Questo è spiegato nella documentazione di MiniWin che si trova nella directory docs. L'esempio di file lo usa per mostrare più immagini nello stesso tipo di finestra (come si vede nell'immagine principale nella parte superiore di questa istruzione).

Passaggio 9: un po' di divertimento sui caratteri finali

Un po' di divertimento sui caratteri finali
Un po' di divertimento sui caratteri finali

MiniWin supporta il rendering dei caratteri TrueType. Se c'è una cosa che rende la tua interfaccia utente bella sono i caratteri attraenti. Questo passaggio finale mostra come eseguire il rendering di un carattere TrueType in una finestra MiniWin.

Ci sono due modi per rendere i caratteri TrueType. Uno è disegnarli direttamente sulla tua area client come è stato fatto per il cerchio in precedenza, l'altro è aggiungere un controllo casella di testo nella tua finestra. Stiamo facendo quest'ultimo perché è più facile.

Ora aggiungeremo un controllo casella di testo nel nostro file di configurazione JSON. Aggiungilo alla definizione di Window 2 in modo che assomigli a questo:

come questo:

{

"Nome": "W2", "Titolo": "Finestra 2", "X": 50, "Y": 65, "Larghezza": 100, "Altezza": 80, "Bordi": vero, "TitleBar": true, "Visible": true, "Minimized": false, "TextBoxes": [{ "Name": "TB1", "X": 0, "Y": 0, "Width": 115, "Height": 50, "Giustificazione": "Centre", "BackgroundColour": "MW_HAL_LCD_YELLOW", "ForegroundColour": "MW_HAL_LCD_BLACK", "Font": "mf_rlefont_BLKCHCRY16", "Enabled": true, "Visible": true }] }

Una breve parola sui caratteri TrueType in MiniWin. I caratteri sono disponibili in file.ttf. Nei gestori di finestre su computer più grandi questi vengono visualizzati sul display quando sono necessari. Questo richiede molta potenza di elaborazione e memoria e non è adatto per dispositivi di piccole dimensioni. In MiniWin sono pre-elaborati in bitmap e collegati in fase di compilazione con una dimensione e uno stile di carattere fissi (grassetto, corsivo, ecc.), ovvero devi decidere quali caratteri a quale dimensione e stile utilizzerai in fase di compilazione. Questo è stato fatto per te per due font di esempio nel file zip MiniWin che hai scaricato. Se desideri utilizzare altri caratteri di altre dimensioni e stili, consulta la documentazione di MiniWin nella cartella docs. Ci sono strumenti in MiniWin per Windows e Linux per la pre-elaborazione dei file.ttf in file di codice sorgente che puoi inserire nel tuo progetto.

E una seconda parola veloce: la maggior parte dei caratteri sono protetti da copyright, inclusi quelli che troverai in Microsoft Windows. Usali a piacimento per uso personale, ma qualsiasi cosa pubblichi devi assicurarti che la licenza con cui sono pubblicati i font lo permetta, come nel caso dei 2 font inclusi in MiniWin, ma non dei font di Microsoft!

Torna al codice! Genera, rilascia file, crea e riesegui come prima e vedrai che Window 2 ora ha del testo predefinito su uno sfondo giallo in un carattere stravagante. Cambiamo il testo modificando il file sorgente di Window 2 W2.c.

Abbiamo bisogno di comunicare con la casella di testo che abbiamo appena creato e il modo in cui lo fai come qualsiasi comunicazione in MiniWin è inviargli un messaggio. Vogliamo impostare il testo nel controllo quando la finestra viene creata ma prima che venga mostrata, quindi aggiungiamo il codice nel gestore dei messaggi nel caso MW_WINDOW_CREATED_MESSAGE. Questo viene ricevuto dal codice della finestra appena prima che la finestra venga visualizzata ed è destinato a inizializzazioni come questa. Il generatore di codice ha creato un segnaposto simile a questo nella funzione del gestore dei messaggi:

caso MW_WINDOW_CREATED_MESSAGE:

/* Aggiungi qui qualsiasi codice di inizializzazione della finestra */ break;

Qui invieremo un messaggio al controllo della casella di testo dicendogli quale testo vogliamo che mostri usando la funzione mw_post_message in questo modo:

caso MW_WINDOW_CREATED_MESSAGE:

/* Aggiungi qui qualsiasi codice di inizializzazione della finestra */ mw_post_message(MW_TEXT_BOX_SET_TEXT_MESSAGE, message->recipient_handle, text_box_TB1_handle, 0UL, "Era una notte buia e tempestosa…", MW_CONTROL_MESSAGE); rottura;

Questi sono i parametri:

  • MW_TEXT_BOX_SET_TEXT_MESSAGE - Questo è il tipo di messaggio che stiamo inviando al controllo. Sono elencati in miniwin.he documentati nella documentazione.
  • message->recipient_handle - Ecco da chi proviene il messaggio - questa finestra - il cui handle si trova nel parametro del messaggio passato alla funzione del gestore del messaggio.
  • text_box_TB1_handle - A chi stiamo inviando il messaggio - l'handle del controllo casella di testo. Questi sono elencati nel file generato miniwin_user.h.
  • 0UL - Valore dei dati, nulla in questo caso.
  • "Era una notte buia e tempestosa…" - Valore puntatore - il nuovo testo.
  • MW_CONTROL_MESSAGE - Tipo di destinatario che è un controllo.

Questo è tutto. Ricostruisci e riesegui come al solito e otterrai la casella di testo mostrata come nell'immagine sopra.

L'invio di messaggi è fondamentale per MiniWin (come lo è per tutti i gestori di finestre). Per ulteriori esempi guarda i progetti di esempio nel file zip e per una spiegazione completa leggi la sezione sui messaggi MiniWin nella documentazione.

Passaggio 10: andare oltre

Image
Image

Questo è tutto per questa introduzione di base a MiniWin. MiniWin può fare molto di più di quanto è stato dimostrato qui. Ad esempio, lo schermo sulla lavagna utilizzato in questo tutorial è piccolo e i controlli sono piccoli e devono essere usati con un dibber. Tuttavia, altri esempi e hardware utilizzano controlli più grandi (ci sono 2 dimensioni) su display più grandi e questi possono essere azionati con le dita.

Esistono molti altri tipi di controllo oltre a quelli mostrati qui. Per ulteriori controlli dai un'occhiata ai vari file JSON di esempio nella cartella del generatore di codice. Tutti i tipi di controllo sono trattati in questi esempi.

Windows ha molte opzioni. Il bordo, la barra del titolo e le icone sono tutti configurabili. Puoi avere barre di scorrimento e aree client delle finestre a scorrimento, più istanze dello stesso tipo di finestra e le finestre possono essere nude (solo un'area client, nessun bordo o barra del titolo) il che significa che sono fisse in fase di compilazione sul display (vedere l'immagine in questa sezione con icone di grandi dimensioni - queste sono in realtà 6 finestre nude).

MiniWin non utilizza memoria dinamica. Ciò lo rende adatto a piccoli dispositivi vincolati ed è un requisito per alcuni progetti embedded. MiniWin e il codice che genera sono anche completamente conformi a MISRA 2012 al livello 'richiesto'.

Per ulteriori informazioni dai un'occhiata nella cartella docs per la documentazione e anche le altre app di esempio nel file zip. Ci sono esempi qui che mostrano come utilizzare tutte le funzionalità di MiniWin e come integrare MiniWin con FatFS e FreeRTOS.

Consigliato: