Questa nota descrive la struttura di mappa del messaggio MFC.
Il problema
Microsoft Windows implementa quali sono essenzialmente funzioni virtuali nelle classi finestra utilizzando il suo stabilimento di messaggistica. A causa di un gran numero di messaggi coinvolti, fornendo una funzione virtuale separata per ciascun messaggio Windows comporta un grande proibitivamente vtable.
Inoltre, poiché il numero di messaggi di Windows definiti dal sistema cambia nel tempo, e poiché una specifica applicazione potrebbe voler definire alcuni messaggi Windows propria, il meccanismo della mappa messaggi fornisce un livello di riferimento indiretto che impedisce a cambiamenti interfaccia di rompere il codice esistente.
Panoramica
MFC fornisce un'alternativa per l'istruzione switch utilizzata in tradizionali programmi Windows per gestire i messaggi inviati a una finestra. Un mapping da messaggi alle funzioni membro può essere definito in modo che quando un messaggio deve essere gestita da una finestra, la funzione membro appropriato viene chiamata automaticamente. Questa struttura mappa messaggi è progettata per essere simili alle funzioni virtuali, ma ha benefici supplementari non possibile con funzioni virtual C++.
Definire una mappa messaggi
La macro DECLARE_MESSAGE_MAP dichiara tre membri per una classe.
Questa macro deve essere collocata nella dichiarazione di qualsiasi classe utilizzando mappe messaggi. Per convenzione, esso è alla fine della dichiarazione della classe. Ad esempio:
classe CMyW&nd: pubblico CMyParentWndClass
{
nbsp; / / la mia roba...
protetto:
//{{AFX_MSG(CMyWnd)
afx_msg void OnPaint();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
}
Questo è il formato generato dalla creazione guidata applicazione e ClassWizard durante la creazione di nuove classi. Il / / {{e / /}} staffe sono necessari per la ClassWizard.
Tabella della mappa messaggio viene definito con un set di macro che espandono le voci map messaggio. Una tabella inizia con una chiamata di macro BEGIN_MESSAGE_MAP , che definisce la classe che viene gestita da questa mappa del messaggio e la classe padre a cui vengono passati i messaggi non gestiti. La tabella si conclude con la chiamata di macro END_MESSAGE_MAP.
Tra queste due macro chiamate è una voce per ogni messaggio venga gestita da questa mappa del messaggio. Ogni messaggio Windows standard ha una macro nella forma ON_WM_xxx (dove xxx è il nome del messaggio) che genera una voce per quel messaggio.
Una firma funzione standard è stata definita per estrarre i parametri di ogni messaggio Windows e fornire indipendenza dai tipi. Queste firme possono essere trovate nel file AFXWIN.H nella dichiarazione di CWnd. Ciascuno di essi è contrassegnato con la parola afx_msg per una facile identificazione.
&Notanbsp; ClassWizard è necessario utilizzare la parola chiave afx_msg nel vostra dichiarazioni del gestore della mappa messaggio.
Queste firme di funzioni sono stata ottenute utilizzando una semplice convenzione. Il nome della funzione inizia sempre con "On". Questo è seguito dal nome del messaggio di Windows con il WM _ rimosso e solo la prima lettera di ogni parola in maiuscolo. L'ordine dei parametri è wParam seguita da LOWORD (lParam) poi HIWORD(lParam). Parametri non utilizzati non sono passati. Eventuali handle che avvolti dalle classi MFC vengono convertiti a puntatori a oggetti MFC appropriati. Nell'esempio seguente viene illustrato come gestire il messaggio WM_PAINT e causare la CMyWnd:: OnPaint chiamata alla funzione
BEGI&N_MESSAGE_MAP (CMyWnd, CMyParentWndClass)
nbsp; //{{AFX_MSG_MAP(CMyWnd)
ON_WM_PAINT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
La tabella della mappa dei messaggi deve essere definita di fuori di qualsiasi definizione di classe o funzione. Non dovrebbe essere immessi all'interno di un blocco di extern "C".
&Notanbsp; ClassWizard permetterà di modificare le voci di mappa del messaggio che si trovano tra il / / {{e / /}} staffa di commento.
I messaggi di Windows definiti dall'utente
Messaggi definiti dall'utente possono essere inclusi in una mappa di messaggio utilizzando la macro ON_MESSAGE . Questa macro accetta un numero di messaggio e una funzione membro del form:
nbsp; / / all'interno della dichiarazione di classe
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
Ad esempio:
# define WM_MYMESSAGE (WM_USER + 100)
BEGI&N_MESSAGE_MAP (CMyWnd, CMyParentWndClass)
ON_MESSAGE (WM_MYMESSAGE, OnMyMessage)
END_MESSAGE_MAP()
In questo esempio, stabiliamo un gestore per un messaggio personalizzato con un ID di messaggio Windows derivato dagli standard WM_USER base per i messaggi definiti dall'utente. Si potrebbe richiamare questo gestore con il codice, come:
CWnd * pWnd =...;
pWnd-gt;SendMessage(WM_MYMESSA&GE)
La gamma di messaggi definiti dall'utente utilizzando questo approccio deve essere nel campo WM_USER a 0x7fff.
&Notanbsp; ClassWizard non supporta l'immissione ON_MESSAGE routine dall'interfaccia utente ClassWizard: è necessario immetterli manualmente dall'editor di Visual C++. Una volta entrato, ClassWizard sarà analizzare queste voci e ti permettono di navigare in proprio come tutte le voci mappa messaggi.
Messaggi registrati di Windows
Il :: RegisterWindowMessage funzione viene utilizzata per definire un nuovo messaggio di finestra che è garantito l'univocità in tutto il sistema. La macro ON_REGISTERED_MESSAGE viene utilizzata per gestire questi messaggi. Questa macro accetta un'il nome della variabile UINT vicino che contiene le finestre registrate messaggio ID. Ad esempio
classe CMyWnd: pubblico CMyParentWndClass
{
pubblica:
nbsp; CMyWnd();
//{{AFX_MSG(CMyWnd)
afx_msg LRESULT OnFind(WPARAM wParam, LPARAM lParam);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
UI&NT statici nei pressi di WM_FIND = RegisterWindowMessage("COMMDLG_FIND");
BEGIN_MESSAGE_MAP (CMyWnd, CMyParentWndClass)
//{{AFX_MSG_MAP(CMyWnd)
ON_REGISTERED_MESSAGE (WM_FIND, OnFind)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
Variabile ID messaggio Windows registrata (WM_FIND nell'esempio precedente) deve essere una variabile vicino a causa del modo in cui che viene implementato ON_REGISTERED_MESSAGE.
La gamma di messaggi definiti dall'utente utilizzando questo approccio sarà nella gamma 0xC000 a 0xFFFF.
&Notanbsp; ClassWizard non supporta l'immissione ON_REGISTERED_MESSAGE routine dall'interfaccia utente ClassWizard, è necessario inserire manualmente li dall'editor di testo. Una volta entrato, ClassWizard sarà analizzare queste voci e ti permettono di navigare in proprio come tutte le voci mappa messaggi.
Messaggi dei comandi
Messaggi di comando dal menu e acceleratori sono trattati in mappe messaggi con la macro ON_COMMAND . Questa macro accetta un ID di comando, come pure una funzione membro. Solo il messaggio WM_COMMAND specifico con un wParam uguale al comando specificato che ID viene gestito dalla funzione membro specificato nella voce della mappa messaggi. Funzioni membro di comando gestione non prendono parametri e restituiscono void. La macro ha la forma:
ON_COMMAND (id, memberFxn)
I messaggi di aggiornamento dei comandi vengono instradate attraverso lo stesso meccanismo come gestori ON_COMMAND . La macro ON_UPDATE_COMMAND_UI viene utilizzata. Funzioni membro di gestione aggiornamento comando prendono un solo parametro, un puntatore a un oggetto CCmdUI e restituiscono void. La macro ha la forma
ON_UPDATE_COMMAND_UI (id, memberFxn)
Una forma estesa del gestori di messaggi di comando è disponibile per usi avanzati. La macro ON_COMMAND_EX è usata invece e fornisce un soprainsieme delle funzionalità ON_COMMAND . Le funzioni membro di gestore di comandi estesi prendono un solo parametro, un UINT contenente l'ID di comando e restituiscono un BOOL. Il ritorno BOOL dovrebbe essere TRUE per indicare che il comando è stato gestito, altrimenti di routing continuerà ad altri oggetti di destinazione del comando.
Esempi delle suddette forme:
#defi&nenbsp; ID_MYCMD 100
# define ID_COMPLEX 101
afx_msg void OnMyCommand();
afx_msg public static void OnUpdateMyCommand (CCmdUI * pCmdUI);
BOOL OnComplexCommand(UINT nID) afx_msg
ON_COMMAND (ID_MYCMD, OnMyCommand)
ON_UPDATE_COMMAND_UI (ID_MYCMD, OnUpdateMyCommand)
ON_COMMAND_EX (ID_MYCMD, OnComplexCommand)
public static void CMyClass::OnMyCommand()
{
nbsp; / / handle il comando
}
public static void CMyClass::OnUpdateMyCommand (CCmdUI pCmdUI)
{
/ / imposta lo stato dell'interfaccia utente con pCmdUI
}
BOOL CMyClass::OnComplexCommand(UI&NT nID)
{
/ / handle il comando
return TRUE;
}
Disponibile anche per l'uso avanzato è ON_COMMAND_RANGE e ON_COMMAND_RANGE_EX che consentono di gestire una vasta gamma di comandi con un gestore unico comando. Vedere la documentazione del prodotto per ulteriori informazioni su queste macro.
&Notanbsp; ClassWizard supporta la creazione di gestori ON_COMMAND e ON_UPDATE_COMMAND_UI , ma non supporta la creazione di gestori ON_COMMAND_EX o ON_COMMAND_RANGE . Tuttavia, guidata classe sarà analizzare e ti permettono di navigare in tutte le varianti del gestore comando tre.
Messaggi di notifica di controllo
I messaggi inviati da controlli figlio a una finestra un extra bit di informazioni nel loro messaggio mappa voce: ID. del controllo Il gestore di messaggio specificato in una voce di mappa messaggi viene chiamato solo se corrisponde a (1) il codice di notifica di controllo (word alto del lParam), come ad esempio BN_CLICKED, il codice di notifica specificato nella voce mappa messaggi e controllo (2) ID (wParam) corrisponde all'ID di controllo specificato nella voce mappa messaggi.
I messaggi di notifica del controllo personalizzato possono utilizzare la macro ON_CONTROL per definire una voce di mappa messaggi con un codice di notifica personalizzata. Questa macro ha la forma
ON_CONTROL (wNotificationCode, id, memberFxn)
Per l'utilizzo avanzato ON_CONTROL_RANGE può essere utilizzato per gestire una notifica di controllo specifico da una serie di controlli con lo stesso gestore.
ClassWizard non supporta la creazione di un gestore ON_CONTROL o ON_CONTROL_RANGE nell'interfaccia utente; è necessario immetterli manualmente con l'editor di testo. Una volta entrato, ClassWizard sarà analizzare queste voci e ti permettono di navigare in proprio come voci di map di messaggio.
Windows Common Controls fare uso del più potente WM_NOTIFY per le notifiche di controllo complessi. Questa versione di MFC ha il supporto diretto per questo nuovo messaggio con le macro ON_NOTIFY e ON_NOTIFY_RANGE . Vedere la documentazione del prodotto per ulteriori informazioni su queste macro.
&Note tecniche per numero |nbsp; Note tecniche per la categoria