Sincronizza Indice |
Scarica il progetto |
Testo dell'articolo |
Stampa l'articolo |
In un HowTo abbiamo visto come richiamare il menu
di sistemadi
un form ed in un altro abbiamo visto come disabilitare
mediante la cancellazione una voce del menu di sistema.
In questo progetto avremo bisogno di un forme di un modulo standard in cui inseriremo la Window Procedure che riceverà i messaggi inviati al form. Infatti per poter controllare il click sulla voce di menu aggiunta dovremo subclassare il form creando una funzione di gestione dei messaggi. Cominciamo a vedere il form. Al suo interno non c'è nessun controllo. Noi abbiamo inserito soltanto una Labelesplicativa, ma essa non è necessaria in alcun modo. Il codice del form è il seguente:
Alla riga 3 abbiamo dichiarato la funzione CretePopupMenu che crea ed alloca un nuovo menu di popup e ne restituisce l'handle. La riga successiva effettua l'operazione inversa, deallocando e distruggendo un menu. Alla riga 5 abbiamo la dichiarazione della funzione AppendMenu. Essa servirà per aggiungere un menu ad un menu esistente. Tuttavia, essa si occuperà soltanto di collegare i due menu, non gestendoli in alcun modo. Alla riga 6 abbiamo la funzione GetSystemMenu, vista in un altro HowTo, che restituisce l'handle del menu di sistema. Ad esso infatti, si dovrà aggiungere il nuovo menu. L'ultima funzione API è la SetWindowLong, una funzione molto complessa e pericolosa (riga 7). Essa effettua varie operazioni sulle finestre e nel nostro caso provvederà a collegare la nuova Window Procedure per effettuare il subclassing del form. Seguono (righe 8-10) tre costanti (MF_POPUP, MF_SEPARATOR e MF_STRING) che indicano il tipo di operazione da effettuare con AppendMenu. La costante GWL_WNDPROC alla riga 11 comunicherà alla funzione SetWindowLong di collegare una nuova Window Procedure. Abbiamo anche una variabile
Al caricamento del form avviene la creazione del nuovo menu e il subclassing
del form.
Alla riga 17 verrà creato un nuovo menu a comparsa. Il suo handle sarà memorizzato nella variabile newMenu (essa è dichiarata all'interno del modulo standard). Nella riga successiva creeremo una nuova voce di menu nel nuovo menu. Utilizzeremo la funzione AppendMenu, passandole come parametri l'handle del menu in cui verrà inserita la voce, il tipo di menu (MF_STRING), l'identificatore che verrà restituito come messaggio alla Window Procedure (IDM_INFOS) ed il testo "Informazioni" che apparirà all'utente. Questo nuovo menu andrà inserito nel menu di sistema. Così, alla riga 19, aggiungeremo prima una voce di separazione (MF_SEPARATOR) al menu di sistema SysMenu. Subito sotto questa incolleremo il nuovo menu impostando come testo d'esso "Informazioni". In pratica abbiamo creato un sottomenu il cui handle è newMenu ed impostato per esso la Caption "Informazioni". All'interno di questo menu abbiamo inserito una voce di menu con il testo "Informazioni". Nel momento in cui l'utente clicca su questa voce di menu viene lanciato il messaggio che indica che è stato premuta una voce di menu e verrà specificato come "responsabile" della chiamata la costante IDM_INFOS. Per rintracciare però questo messaggio, sarà necessario subclassare il form specificando l'indirizzo di una funzione che fungerà da Window Procedure. Poiché l'operatore AddressOf richiede il nome di una funzione a livello di modulo, abbiamo dovuto inserire la nostra funzione in un modulo standard. Così, alla riga 21, viene effettuato il subclassing: la funzione SetWindowLong con il parametro GWL_WNDPROC specifica che desideriamo creare una nuova Window Procedure. L'indirizzo della nuova Window Procedure è indicato da AddressOf MenuHandler. Così facendo, tutti i messaggi inviati dal form, passeranno prima dalla funzione MenuHandler, che si occuperà di verificarli e reagire di conseguenza. L'indirizzo della Window Procedure originale - che deve essere ripristinato in chiusura del programma - viene salvato nella variabile pubblica lProcOld.
Così, nello scaricamento del form, ripristiniamo la Window Procedure
originale, passandole come indirizzo il puntatore
salvato precedentemente. Il nostro form termina qui. Possiamo vedere l'unica funzione di cui si compone il modulo, che funzionerà da Window Procedure.
Poiché la nostra Window Procedure riceverà tutti i messaggi inviati dal form, è necessario richiamare la Window Procedure originale, per effettuare tutte le altre operazioni (il movimento del mouse, il ridisegno, la pressione sopra il form, gli spostamenti, etc...).
A tal scopo abbiamo dichiarato la funzione API CallWindowProc che richiama una Window Procedure di cui conosciamo l'indirizzo (riga 3). Alla riga 4 abbiamo la costante costante WM_SYSCOMMAND che identifica i messaggi inviati dal menu di sistema. Segue la costante IDM_INFOS, inventata, che indica il numero identificativo della voce di menu creata nel form. Alla riga 6 risiede la dichiarazione della variabile lProcOld che dovrà contenere il puntatore alla Window Procedure originale, da richiamare per tutti i messaggi e per ripristinare il programma in uscita.
La funzione MenuHandler è la nostra Window Procedure. La definizioe dei parametri è obbligatoria in questa forma per tutte le Window Procedure. Se il messaggio inviato proviene dal menu di sistema (costante WM_SYSCOMMAND), sarà necessario verificare se è stata scelta la voce IDM_INFOS, ovvero il nostro menu. In tal caso verrà mostrata una finestra informativa con il testo "Questa voce è stata aggiunta al menu di sistema". Fatto questo la Window Procedure ha terminato la sua funzione. Se invece la voce di menu non è quella da noi creata, oppure il messaggio non riguarda il menu di sistema, sarà necessario chiamare la Window Procedure originale, per permettere il corretto funzionamento del form. La chiamata alla funzione originale avviene tramite la funzione CallWindowProc e specificando come indirizzo il puntatore lProcOld, salvato al momento del subclassing. Il nostro codice termina qui. Possiamo provare il nostro programma e vederne gli effetti.
Nel momento in cui apriremo il menu di sistema troveremo un sottomenu e dentro d'esso una voce di menu. Il click sopra d'essa mostrerà una finestra informativa. |
Il progetto contiene molti rischi e molte trappole. Se le chiamate sono gestite correttamente il progetto funzione, ma un semplice errore può trasformarsi in un blocco del computer. Fibia
FBI
|
Torna all'indice degli HowTo |