TN006: Mappe messaggi

Questa nota viene descritta la funzionalità della mappa messaggi MFC.

Il problema

Microsoft Windows implementa le funzioni virtuali nelle classi di finestre che utilizzano la funzionalità di messaggistica.A causa del massimo numero di messaggi in questione, fornendo a una funzione virtuale separata per ogni messaggio di windows sopra riportato consente di creare un riferimento proibitivamente grande.

Poiché il numero di messaggi definiti dal sistema di windows modifiche nel corso del tempo e poiché le applicazioni possono definire propri messaggi di windows, le mappe dei messaggi fornisce un livello di riferimento indiretto che impedisce dell'interfaccia da interrompere il codice esistente.

Panoramica

MFC offre un'alternativa all'istruzione switch utilizzata nei programmi basati su Windows tradizionali per gestire i messaggi inviati a una finestra.Un mapping dai messaggi ai metodi può essere definito in modo che quando un messaggio viene ricevuto da una finestra, chiamare il metodo appropriato automaticamente.Questa funzionalità della mappa messaggi è progettata per essere simile alle funzioni virtuali ma ha assegnato di base non possibili con funzioni virtuali di C++.

Definizione della mappa messaggi

La macro di DECLARE_MESSAGE_MAP dichiara tre membri per una classe.

  • Una matrice privata delle voci di AFX_MSGMAP_ENTRY ha chiamato _messageEntries.

  • Una struttura protetta di AFX_MSGMAP ha chiamato messageMap che indica _messageEntries la matrice.

  • Una funzione virtuale protetta ha chiamato GetMessageMap che restituisce l'indirizzo di messageMap.

Questa macro deve essere immessa nella dichiarazione di una classe utilizzando le mappe dei messaggi.Per convenzione, si trova alla fine della dichiarazione di classe.Di seguito è riportato un esempio:

class CMyWnd : public CMyParentWndClass
{
    // my stuff...

protected:
    //{{AFX_MSG(CMyWnd)
    afx_msg void OnPaint();
    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()
};

È il formato generato da AppWizard e ClassWizard quando creano nuove classi.Le parentesi //e {{//}} sono necessari per ClassWizard.

La tabella della mappa messaggi è definita utilizzando un insieme di macro che si espandono le voci della mappa messaggi.Una tabella inizia con una chiamata di macro di BEGIN_MESSAGE_MAP , che definisce la classe che viene gestito da questa mappa messaggi e dalla classe padre a cui i messaggi non gestiti vengono passati.La tabella termina con la chiamata di macro di END_MESSAGE_MAP .

Tra queste due macro chiamate è una voce per ogni messaggio venga gestita da questa mappa messaggi.Ogni messaggio standard di windows ha una macro del form ON_WM_MESSAGE_NAME che genera una voce per il messaggio.

Firma della funzione standard è stata definita per decomprimere i parametri di ogni messaggio di windows e fornendo dell'indipendenza dai tipi.Le firme sono disponibili nel file Afxwin.h nella dichiarazione di CWnd.Ciascun oggetto è contrassegnato con la parola chiave afx_msg per l'identificazione semplice.

[!NOTA]

ClassWizard è necessario utilizzare la parola chiave di afx_msg nelle dichiarazioni del gestore della mappa messaggi.

Le firme della funzione sono state derivate utilizzando una convenzione semplice.Il nome della funzione inizia sempre con "On„.Seguita dal nome del messaggio di windows con “WM_„ rimosso e la prima lettera di ogni parola scritta in maiuscolo.L'ordine dei parametri è wParam seguito da LOWORD(lParam) quindi HIWORD(lParam).I parametri inutilizzati non sono stati superati.Tutti gli handle che viene eseguito il wrapping delle classi MFC vengono convertite in puntatori agli oggetti appropriati MFC.Nell'esempio seguente viene illustrato come gestire il messaggio di WM_PAINT e fare in modo che la funzione di CMyWnd::OnPaint a essere chiamato:

BEGIN_MESSAGE_MAP(CMyWnd, CMyParentWndClass)
    //{{AFX_MSG_MAP(CMyWnd)
    ON_WM_PAINT()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

La tabella della mappa messaggi deve essere definita all'esterno di qualsiasi funzione o definizione della classe.Non deve essere immessa in un blocco extern “c„.

[!NOTA]

ClassWizard modificherà le voci della mappa messaggi che si verificano tra parentesi di commento //e {{//}}.

Messaggi definiti dall'utente di windows

I messaggi definiti dall'utente possono essere inclusi in una mappa messaggi utilizzando la macro di ON_MESSAGE .Questa macro accetta un numero di messaggio e un metodo del form:

    // inside the class declaration
    afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);

    #define WM_MYMESSAGE (WM_USER + 100)

BEGIN_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 messaggio di windows derivato dalla base standard di WM_USER per i messaggi definiti dall'utente.Nell'esempio seguente viene illustrato come chiamare il gestore:

CWnd* pWnd = ...;
pWnd->SendMessage(WM_MYMESSAGE);

L'intervallo dei messaggi definiti dall'utente che utilizzano questo approccio deve essere compreso WM_USER a 0x7fff.

[!NOTA]

ClassWizard non supporta fornire le routine del gestore di ON_MESSAGEinterfaccia utente di ClassWizard.È necessario immetterli manualmente tramite l'editor di Visual C++.ClassWizard ricopre queste voci e consentono di esplorarli come tutte le altre voci della mappa messaggi.

Messaggi registrati di windows

La funzione di RegisterWindowMessage viene utilizzata per definire un messaggio della nuova finestra in cui è univoco in tutto il sistema.La macro ON_REGISTERED_MESSAGE viene utilizzata per gestire questi messaggi.Questa macro accetta un nome di una variabile di UINT NEAR contenente l'id di messaggio registrata windowsEsempio:

class CMyWnd : public CMyParentWndClass
{
public:
    CMyWnd();

    //{{AFX_MSG(CMyWnd)
    afx_msg LRESULT OnFind(WPARAM wParam, LPARAM lParam);
    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()
};

static UINT NEAR 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()

La variabile registrata del messaggio ID delle finestre (WM_FIND in questo esempio) deve essere una variabile di NEAR a causa della modalità con cui ON_REGISTERED_MESSAGE viene distribuito.

L'intervallo dei messaggi definiti dall'utente che utilizzano questo approccio verrà nell'intervallo 0xC000 a 0xFFFF.

[!NOTA]

ClassWizard non supporta fornire le routine del gestore di ON_REGISTERED_MESSAGEinterfaccia utente di ClassWizard.È necessario manualmente spostarli nell'editor di testo.ClassWizard ricopre queste voci e consentono di esplorarli come tutte le altre voci della mappa messaggi.

Messaggi di comando

I messaggi di comando dai menu e dei tasti di scelta rapida sono gestiti in mappe messaggi con la macro di ON_COMMAND .Questa macro accetta un ID di comando e un metodo.Solo il messaggio specifico di WM_COMMAND che ha wParam uguale all'ID comando specificato è gestito dal metodo specificato nella voce della mappa messaggi.Le funzioni membro del gestore comando non accettano parametri e voidrestituita.La macro ha il formato seguente:

ON_COMMAND(id, memberFxn)

I messaggi di aggiornamento dei comandi sono indirizzati attraverso lo stesso meccanismo, ma utilizzano la macro di ON_UPDATE_COMMAND_UI anziché.Le funzioni membro del gestore aggiornamento del comando accetta un singolo parametro, un puntatore a un oggetto di CCmdUI e voidrestituita.La macro presenta il formato

ON_UPDATE_COMMAND_UI(id, memberFxn)

Gli utenti avanzati possono utilizzare la macro di ON_COMMAND_EX , che è un form esteso dei gestori di messaggio di comando.La macro viene fornito un superset della funzionalità di ON_COMMAND .Le funzioni membro estese del gestore comando accetta un singolo parametro, UINT contenente l'ID di comando e restituiscono BOOL.Il valore restituito deve essere TRUE per indicare che il comando è stato gestito.In caso contrario il routing continuerà ad altri oggetti di destinazione comando.

Esempi di questi form:

  • Resource.h interno (solitamente generato da Visual C++)

    #define    ID_MYCMD      100
    #define    ID_COMPLEX    101
    
  • Nella dichiarazione di classe

    afx_msg void OnMyCommand();
    afx_msg void OnUpdateMyCommand(CCmdUI* pCmdUI);
    afx_msg BOOL OnComplexCommand(UINT nID);
    
  • Nella definizione della mappa messaggi

    ON_COMMAND(ID_MYCMD, OnMyCommand)
    ON_UPDATE_COMMAND_UI(ID_MYCMD, OnUpdateMyCommand)
    ON_COMMAND_EX(ID_MYCMD, OnComplexCommand)
    
  • Nel file di implementazione

    void CMyClass::OnMyCommand()
    {
        // handle the command
    }
    
    void CMyClass::OnUpdateMyCommand(CCmdUI* pCmdUI)
    {
        // set the UI state with pCmdUI
    }
    
    BOOL CMyClass::OnComplexCommand(UINT nID)
    {
        // handle the command
        return TRUE;
    }
    

Gli utenti avanzati possono gestire un intervallo dei comandi mediante un singolo gestore comando: ON_COMMAND_RANGE o ON_COMMAND_RANGE_EX.Consultare la documentazione del prodotto per ulteriori informazioni su queste macro.

[!NOTA]

ClassWizard supporta la creazione ON_COMMAND e gestori di ON_UPDATE_COMMAND_UI , ma non supporta la creazione ON_COMMAND_EX o i gestori di ON_COMMAND_RANGE .Tuttavia, la creazione guidata classe si analizza e comunicano esplorare le quattro varianti del gestore comando.

Messaggi di notifica di controllo

I messaggi inviati dai controlli figlio di una finestra con un bit aggiuntivo di informazioni nella rispettiva voce della mappa messaggi: l'id del controlloIl gestore di messaggi specificato in una voce della mappa messaggi viene chiamato solo se le condizioni seguenti sono vere:

  • Il codice di notifica di controllo (word alto di lParam), come BN_CLICKED, corrisponde al codice di notifica specificato nella voce della mappa messaggi.

  • ID del controllo (wParam) corrisponde all'ID del controllo specificato nella voce della mappa messaggi.

I messaggi di notifica di controllo personalizzati possono utilizzare la macro di ON_CONTROL per definire una voce della mappa messaggi con il codice di notifica personalizzato.Questa macro presenta il formato

ON_CONTROL(wNotificationCode, id, memberFxn)

Per un utilizzo avanzato ON_CONTROL_RANGE può essere utilizzato per mantenere una notifica di controllo specifica da una serie di controlli con lo stesso gestore.

[!NOTA]

ClassWizard non supporta creare un gestore di ON_CONTROL_RANGE o di ON_CONTROL nell'interfaccia utente.È necessario manualmente spostarli nell'editor di testo.ClassWizard ricopre queste voci e consentono di esplorarli come tutte le altre voci della mappa messaggi.

I controlli comuni di Windows utilizzano WM_NOTIFY più efficace per le notifiche di controllo complesse.Questa versione di MFC offre supporto diretto al nuovo messaggio utilizzando le macro di ON_NOTIFY_RANGE e di ON_NOTIFY .Consultare la documentazione del prodotto per ulteriori informazioni su queste macro.

Vedere anche

Altre risorse

Note tecniche del numero

Note tecniche per categoria