Benvenuti al secondo articolo sulla programmazione PM. In questi articoli saranno discussi semplici problemi di programmazione Presentation Manager. Questi articoli sono indirizzati a persone interessate alla programmazione PM o semplicemente curiose di sapere come funzionano i programmi PM. Per comprendere questi articoli, è utile un po' di esperienza di programmazione (preferibilmente in C++).
Il mese scorso abbiamo parlato del paradigma ad eventi. Ciò significa messaggi. Abbiamo
anche spiegato come i messaggi sono inviati e gestiti dalle finestre. Alcuni messaggi, ad esempio WM_QUIT
,
sono stati nominati nello scorso articolo.
Questa volta guarderemo più da vicino alcuni messaggi. Mentre stiamo ancora costruendo una semplice finestra per una applicazione, daremo uno sguardo a due messaggi usati nella creazione di una frame window. Il semplice programma che abbiamo creato il mese scorso sarà usato come punto di partenza per le nostre nuove esplorazioni. Alla fine di questo articolo saremo in grado di creare un semplice controllo nella nostra finestra (in effetti nella client area) e dimensionarlo/posizionarlo appropriatamente.
MLM_QUERYFONT
a quel MLE. Il
messaggio ci restituirà l'informazione richiesta.
Nella maggior parte dei casi, comunque, i messaggi sono il risultato di un evento, e permettendo alla nostra procedura di finestra di rispondere a questi messaggi possiamo avere un controllo su come gli eventi sono gestiti.
WinCreateStdWindow
. Tutto ciò che succede in seguito a quella chiamata può essere
visto come una serie di eventi nel sistema OS/2. Questo significa che ci sono messaggi a cui possiamo rispondere quando
una finestra viene creata.
Qui abbiamo una scelta: non abbiamo la necessità di gestire questi messaggi, c'è sempre la possibilità di lasciarli gestire alla procedura di default. Guarderemo da vicino due messaggi che giocano un ruolo chiave al momento della creazione di una finestra. (Notare che ci sono molti altri messaggi che potremmo usare nel processo di creazione. Questi messaggi sono più complessi e non saranno ancora discussi).
WM_CREATE
. È il primo messaggio che una finestra riceve dopo la sua
inizializzazione. Quando questo messaggio viene ricevuto, la finestra non è ancora visibile e non ha una dimensione
sullo schermo.
Cosa facciamo normalmente con il messaggio WM_CREATE
? Beh, ci sono varie possibilità.
WM_CREATE
riceve un puntatore a una struttura di tipo CREATESTRUCT
. Questa
struttura contiene tutti i parametri necessari alla creazione della finestra, e alcuni di questi li abbiamo già
visti nella chiamata a WinCreateStdWnd
. La struttura appare così:
typedef struct _CREATESTRUCT { PVOID pPresParams; // "Presentation parameters". PVOID pCtlData; // "Control data". ULONG id; // Identificatore della finestra. HWND hwndInsertBehind; // Finestra dietro la quale posizionare la nostra finestra. HWND hwndOwner; // Proprietario ("owner") della finestra. LONG cy; // Altezza della finestra. LONG cx; // Larghezza della finestra. LONG y; // Coordinata Y (verticale) dell'origine. LONG x; // Coordinata X (orizzontale) dell'origine. ULONG flStyle; // Stile della finestra. PSZ pszText; // Testo della finestra. PSZ pszClassName; // Nome della classe ("window class"). HWND hwndParent; // Handle della finestra madre ("parent"). } CREATESTRUCT;Possiamo usare queste informazioni per ulteriori azioni di impostazione, se vogliamo. Da notare che tutte queste informazioni possono essere ottenute richiedendole alla finestra, ma copiandole localmente, potreste ottenere qualche aumento di velocità. (Devo però dire che ho visto ben pochi programmi che facciano questo).
WM_CREATE
contiene un puntatore ai cosiddetti dati di controllo
("CTLDATA
"). Questa struttura ha un formato diverso per ogni window-class (controllo) messo a
disposizione da OS/2. Può essere usata per risparmiare linee di codice quando si impostano controlli tipo pulsanti
o simili (nota: non siamo ancora a questo punto, stiamo ancora creando una semplice frame window). In futuri articoli
incontreremo di nuovo questa struttura quando parleremo di semplici controlli. La parola-chiavi qui è PIGRIZIA:
non fare niente che il sistema possa fare al posto tuo.
WM_CREATE
è quella di impostare controlli
nella client area. La maggior parte delle applicazione funzionano così. Nel nostro esempio di questo mese
metteremo un pulsante al centro della client area. Possiamo farlo usando questa chiamata:
WinCreateWindow(hwnd, // Handle del parent (ovvero la client area) WC_BUTTON, // Classe della finestra (pulsante) "This is a button", // Testo della finestra WS_VISIBLE | BS_DEFAULT, // Flag del pulsante 0, 0, 0, 0, // in questo momento non abbiamo ancora né posizione né dimensione hwnd, // Handle dell'owner (sempre la client area) HWND_TOP, // mettilo in cima allo Z-order 100, // ID del controllo 0, // controllo 0); // Presentation ParametersLa API usata per far questo è
WinCreateWindow
. Questa chiamata creerà un singolo pulsante
(notare che WinCreateStdWindow
crea un complesso insieme di finestre). Cose tipo parent, owner, Z-order
e ID verranno spiegate il mese prossimo. Per ora è essenziale notare che ci sono quattro zeri al posto dei
parametri x,y,cx,cy. Questi parametri sono usati per impostare la dimensione e la posizione di una finestra. La nostra
client area a questo punto non ha ancora né una posizione né una dimensione, perciò dare al pulsante
una dimensione o una posizione all'interno della nostra finestra non ha alcun significato. Per esempio potrebbe essere
piazzato fuori dai bordi della finestra ed essere quindi invisibile e inutilizzabile.
WM_SIZE
.
WM_SIZE
è soprattutto usato per ridimensionare i controlli nella client area, ma
può anche essere usato per evitare che una finestra venga ridimensionata sotto o oltre una certa dimensione.
L'esempio che scriveremo consiste nel dare al pulsante una posizione e una dimensione. Noi vogliamo il pulsante al
centro della client area. Questo significa che dobbiamo riposizionare il pulsante ogni volta che la finestra viene
ridimensionata. Questo non è un problema poiché ogni volta che questo succede, viene inviato un messaggio
WM_SIZE
. Così con un solo blocco di codice possiamo gestire sia il momento della creazione sia il
ridimensionamento. Se avessimo usato le informazioni nella struttura CREATESTRUCT
durante
WM_CREATE
avremmo avuto bisogno di scrivere due blocchi, uno per la creazione e uno per il dimensionamento.
Oltre a piazzare il pulsante al centro della client area, vogliamo che abbia larghezza e altezza pari a 1/3 di quelle della client area.
Il messaggio WM_SIZE
ci fornisce proprio le informazioni di cui abbiamo bisogno. Questo messaggio passa
le vecchie dimensioni in mp1 e le nuove in mp2. Noi siamo interessati alle nuove dimensioni della finestra (nota:
questa è la dimensione della client area, non della frame window!).
Nell'articolo scorso avevamo parlato dei parametri dei messaggi (di tipo MPARAM
). Questi parametri sono
in effetti delle variabili ULONG
(interi lunghi 32 bit). I valori x,y,cx,cy sono interi corti (16 bit).
I due parametri di WM_SIZE
sono due ULONG
composti di due interi corti ciascuno. Possiamo
ottenere le due metà di un ULONG
come interi corti usando le cosiddette helper-macro (macro d'aiuto).
Le macro che ci servono sono SHORT1FROMMP
e SHORT2FROMMP
. Quindi per leggere i valori che
useremo per piazzare il nostro pulsante possiamo usare queste due macro.
Per impostare la posizione e la dimensione del pulsante useremo WinSetWindowPos
. Tramite questa API
possiamo dimensionare, spostare, rendere invisibile ecc. una finestra. Noi la useremo solo per ridimensionare e spostare
il pulsante. Il codice del nostro piccolo esperimento appare così:
case WM_SIZE: { short x = SHORT1FROMMP(mp2)/3; short y = SHORT2FROMMP(mp2)/3; WinSetWindowPos(hwndButton, // Sposta e dimensione il pulsante HWND_TOP, // In cima allo Z-order x, // coordinata x y, // coordinata y x, // dimensione cx y, // dimensione cy SWP_SIZE|SWP_MOVE);// cambia posizione e dimensione } break;Cercate di capire come funziona. Può essere consigliabile controllare il funzionamento preciso di
WinSetWindowPos
. È una API molto utile.
Per vedere come tutto questo funziona, prendete il file .exe dell'esempio (ZIP, 13.7k) e ridimensionate la finestra come volete. Noterete che il pulsante viene sempre mostrato al centro e che le sue dimensioni sono 1/3 di quelle della finestra.
Sento che qualcuno di voi sta pensando: "e i menu, le barre di stato, la toolbar, ecc.?". Beh, ci sono modi di implementare questi controlli come parte dell'insieme che costituisce la frame window. Ciò ha il vantaggio che non dobbiamo preoccuparci delle dimensioni ecc. In un futuro articolo prenderò un po' di tempo per studiare e spiegare tutto ciò.
Il prossimo mese, comunque, daremo uno sguardo a un modo di aggiungere qualche controllo alla nostra finestra, come menu e barre di scorrimento.
- [ Pagina precedente ] - - [ Sommario ] - - [ Just WARP! homepage ] - - [ Pagina successiva ] - |