Sviluppo

Come faccio? - parte VI

Gianni Ceccarelli
 

stesura originale in inglese di Eric Slaats - liberamente tradotto da Gianni Ceccarelli
comparso per la prima volta su Os/2 e-Zine! volume 2 numero 3

Capacità non sfruttate

OS/2 è un sistema operativo stupefacente. Ha una gran quantità di caratteristiche molto interessanti quali Drag-and-Drop, presentation parameters, profili, ecc. Quel che mi stupisce spesso è non ci sono molti programmi che fanno veramente uso di tutto questo. Prendete una cosa semplice come salvare la posizione della finestra principale e i suoi presentation parameters. Molte delle applicazioni che ho provato non sfruttano affatto queste caratteristiche. OS/2 Works, nel BonusPak, per esempio: nessun supporto per i presentation parameters, nessun salvataggio della posizione della finestra, niente barra di stato scalabile. Tutto ciò è ancora più stupefacente perché queste caratteristiche sono molto semplici da implementare.

Per interderci: implementare un completo supporto per il drag-and-drop (come in Smalled o con DragText) non è semplice, anzi, è molto difficile! Ma, implementare cose basilari come il salvataggio della posizione di una finestra con i suoi presentation parameters è molto semplice e non richiede poi molto lavoro. Questo è proprio ciò di cui discuteremo questo mese.

Molti termini citati sopra richiedono una spiegazione. Perciò prima di addentrarci nella programmazione vediamo cosa significano.

Presentation Parameters. Li adoro! I PP sono un modo fantastico di cambiare (e ricordare) le informazioni sui colori e i font di praticamente ogni parte della vostra applicazione. Chiunque usi OS/2 li conosce ma probabilmente non li riconoscerà sotto il nome di Presentation Parameters. I PP sono molto facili da applicare, basta usare le tavolozze colori e font nella cartella Impostazioni del sistema e trascinare un font o un colore sull'area che si vuole cambiare. Vedremo come salvare i PP tra un momento.

Profili. Questa è un'altra caratteristica di OS/2 che tutti usano, lo vogliano o no. Qualsiasi cosa facciate nel vostro sistema, come cambiare i colori, cambiare la posizione di finestre o icone, ecc, viene registrato. In questo modo OS/2 può ripristinare tutte le vostre impostazioni quando riavviate il sistema. OS/2 usa due profili, OS2.INI per le impostazioni utente (useremo anche queste) e OS2SYS.INI per le impostazioni di sistema.

Il profilo di OS/2 può essere confrontato con il file SYSTEM.INI di Windows. Ad ogni modo, la versione OS/2 del profilo è un database binario ed è molto superiore alla versione Windows.

A parte questi due profili, è anche possibile usare un profilo privato (tratteremo questo aspetto un'altra volta).

Ora, dopo questa introduzione piuttosto lunga, cosa faremo questo mese? Aggiungeremo una funzionalità al nostro programma esempio (ZIP, 14.5k) che salverà la posizione della finestra e tutti le informazioni sui colori e i font che vengono modificate tramite i PP. Poiché molti non gradiscono che i programmi mettano le mani sul loro OS2.INI, aggiungeremo anche un'opzione di menu per rimuovere queste informazioni dal file OS2.INI.

Cosa succede quando un programma viene chiuso?

È meglio salvare le dimensioni e la posizione della finestra, nonché le informazioni sui PP, quando l'applicazione viene chiusa. In questo modo non dobbiamo agire dopo ogni cambiamento, ci limitiamo a salvare tutto alla chiusura. Quindi vediamo cosa succede quando un programma viene chiuso.

Molti messaggi hanno un ruolo nella chiusura di una applicazione. Ovviamente c'è il messaggio WM_QUIT (ne abbiamo parlato in un articolo precedente). Questo messaggio non è molto conveniente da usare per azioni dell'ultimo minuto perché è questo messaggio che termina la coda messaggi per l'applicazione.

C'è anche il messaggio WM_CLOSE. Questo messaggio viene inviato dal PM quando l'utente seleziona la voce "Chiudi" dal menu sistema o fa doppio click sull'icona del menu sistema [o preme il pulsante di chiusura in Warp4 n.d.t.]. La "window procedure" di default (WinDefWindowProc) reagisce a questo messaggio inviando un WM_QUIT, quindi chiudendo l'applicazione. Però non possiamo assumere che WM_CLOSE venga inviato ogni volta che l'applicazione viene chiusa (un WM_QUIT può essere inviato da un'altra azione).

Così, cosa stiamo cercando? C'è un altro messaggio che viene inviato dal PM appena prima che l'applicazione si chiuda, è il messaggio WM_SAVEAPPLICATION (un nome adatto). Questo messagio è fatto apposta per salvare lo stato dell'applicazione e sicuramente è il messaggio che useremo nel nostro esempio.

Gli sviluppatori di OS/2 2.0 aggiunsero due funzioni che rendono davvero semplice salvare e ripristinare lo stato corrente della frame window. Sono le funzioni WinStoreWindowPos e WinRestoreWindowPos. Queste funzioni salvano la dimensione e la posizione, nonché tutti i PP, di ogni controllo del frame. (Nota: quando si aggiungono controlli come una barra di stato, è sempre conveniente renderli controlli di frame, perché in questo modo non dovete preoccuparvi di salvare font, colori, ecc. separatamente. Ci occuperemo di questo qualche altra volta).

Vediamo la funzione WinStoreWindowPos per prima. Lo svantaggio di queste funzioni è che salvano tutto nel file OS2.INI. Come detto prima, non tutti gradiscono ciò. La funzione WinStoreWindowPos prende tre parametri:

PSZ     pAppName;  // Stringa che contiene il nome dell'applicazione.
PSZ     pKeyName;  // Stringa che contiene il nome della chiava.
HWND    hwnd;      // Handle della finestra che si vuol salvare.

rc = WinRestoreWindowPos(pAppName, pKeyName, hwnd);
Per capire questi parametri, dobbiamo sapere qualcosa sui profili. I profili sono database binari che gestiscono le informazioni a due livelli. Il livello più alto è il livello dell'applicazione. Sotto il livello dell'applicazione si possono creare delle chiavi e assegnare dati ad ogni chiave, questi possono essere molteplici, da una semplice stringa o un intero fino a strutture molto complesse.

La funzione WinStoreWindowPos deve conoscere solo il nome dell'applicazione e il nome della chiave per i dati nel file OS2.INI. Normalmente, si assegnano questi nomi con dei #define nel file header. In questo modo è più semplice tenere traccia di quali nomi vengono usati. L'estrazione dei valori dalla frame window è gestita interamente da WinStoreWindowPos perciò l'azione che eseguiamo in risposta a WM_SAVEAPPLICATION è molto semplice.

// Segmento dal file Sample6.h

#define APPNAME "Sample6"
#define WINPOS  "Sample6WinPos"

//----------------------------------------------------------------------------
// Salva posizione e dimensioni della finestra all'uscita
//----------------------------------------------------------------------------
case WM_SAVEAPPLICATION:
        {
        WinStoreWindowPos(APPNAME, WINPOS,
                                   WinQueryWindow(hwnd, QW_PARENT));
        }
break;
Sembra semplice, vero? Be', è tutto quello che serve. C'è comunque una cosa che richiede una piccola spiegazione, la linea WinQueryWindow(hwnd, QW_PARENT). Questo è l'handle che serve alla funzione per salvare i dati della frame window. Con questa chiamata chiediamo alla client window qual è l'handle del parent (la frame window).

Parliamo ora di ripristinare i dati. Vogliamo farlo quando siamo sicuri che la finestra sia stata creata. Anche questo codice è molto semplice:

WinRestoreWindowPos(APPNAME,       // Ripristina dimensione/posizione e PP da OS2.INI
                                WINPOS,        //
                                hwndFrame))    //
Ci sono però dei trabocchetti qui. La prima volta che il programma viene avviato, non c'è nessuna voce nel file OS2.INI. Questo significa che non ci sono dati per ripristinare la finestra.

Nessun problema, abbiamo definito il flag FCF_SHELLPOSITION per la creazione della finestra. E di sicuro, la prima volta che il programma viene eseguito, questo gestisce tutto il dimensionamento e posizionamento della finestra.

Però, se c'è una voce in OS2.INI, il flag FCF_SHELLPOSITION fa in modo che la finestra venga prima mostrata nella posizione e dimensione determinate dal PM, e poi venga spostata secondo quanto salvato dalla sessione precedente. Questo non è esattamente elegante. Quindi cosa facciamo? Dobbiamo impostare dimensioni e posizione a mano se la chiamata a WinRestoreWindowPos fallisce. Per fortuna, questo funzione ritorna un valore per determinare se è stata eseguita con successo. Se questo non si verifica, dobbiamo chiamare WinSetWindowPos con posizione e dimensioni esplicite. Il codice per gestire tutto questo appare così:

//-------------------------------------------------------------------------
// Ripristina posizione/dimensioni e PP da OS2.INI
//-------------------------------------------------------------------------
if (!WinRestoreWindowPos(APPNAME, WINPOS, hwndFrame))
     {
     WinSetWindowPos(hwndFrame,
                     NULLHANDLE,
                     10,10,550,300,
                     SWP_ACTIVATE| SWP_MOVE| SWP_SIZE |SWP_SHOW);
     }
Per vedere come funziona, aprite la finestra, spostatela, ridimensionatela e trascinate colori e font sulla barra del titolo e sui menu (ricordate che finestre attive e inattive possono avere colori diversi sulla barra del titolo). Potete anche cambiare il colore del bordo in questo modo. Chiudete la finestra e apritela di nuovo e osservate il risultato (notate che la client area non accetta trascinamenti di PP).

Siamo arrivati all'ultima parte di questo articolo. Sarebbe bello rimuovere la voce che sample6.exe inserisce nel file OS2.INI. Questo può essere fatto con una delle API per i profili. La funzione PrfWriteProfileData può essere usata per inserire dati nel profilo, ma anche per rimuoverli. Senza scendere nei dettagli (lo farò qualche altra volta), farò solo vedere la funzione che si occuperà del nostro problema. Per renderla accessibile, c'è una voce di menu. Questa chiama la seguente funzione:

PrfWriteProfileData(HINI_USERPROFILE, APPNAME, NULL, NULL, 0);
Questo effettimente rimuove la voce dal file OS2.INI. Ad ogni modo, non siamo ancora a posto visto che il programma è ancora attivo, chiudendolo si attiverà il messaggio WM_SAVEAPPLICATION e quindi i dati verranno salvati di nuovo. Per correggere ciò in questo esempio, ho usato una poco elegante variabile globale booleana per scegliere se salvare i dati. Quando la voce di menu viene selezionata, l'applicazione si chiude e a causa dello stato della variabile globale (bSave), non verrà salvata nessuna informazione. Controllate nel codice per vedere come si fa.

Note conclusive

L'articolo di questo mese descrive una delle cose che prefisco: applicazioni che ricordano cosa l'utente sta facendo. Spero di aver mostrato quanto sono semplici le operazioni di base. Inoltre, ricordate che molti preferiscono tenere il proprio OS2.INI pulito, quindi pensateci due volte prima di usarlo. Secondo me, comunque, una delle ragioni per usare OS2.INI è che è molto veloce. È probabile che il file OS2.INI sia già in memoria. Questa è una delle ragioni per cui programmi come Smalled usano OS2.INI, per assicurare un'avvio veloce. Sono disponibili alcuni programmi che vi permettono di esaminare il file OS2.INI. Per esempio Initor (2.0) di Jobst Schmalenbach funziona molto bene. Dateci un'occhiata.

Fino al prossimo mese, arrivederci.


[Pagina precedente] [Sommario] [Pagina successiva]