Condividi tramite


TN021: Comando e routing dei messaggi

[!NOTA]

La seguente nota tecnica non è stata aggiornata dalla prima volta che viene inclusa nella documentazione online.Di conseguenza, alcune procedure e argomenti potrebbero non essere aggiornati o errati.Per le informazioni più recenti, è consigliabile cercare l'argomento di interesseindice della documentazione online.

Questa nota viene descritta l'architettura di invio e di routing dei comandi nonché gli argomenti avanzati nell'instradamento dei messaggi generale della finestra.

Fare riferimento in alternativa a Visual C++ per informazioni generali su architetture descritte in questo argomento, in particolare la distinzione tra i messaggi di windows, notifiche di controllo e i controlli.Questa nota si presuppone che l'utente sia in grado di molto con i problemi descritti nella documentazione stampata e solo negli argomenti molto avanzati degli indirizzi.

La funzionalità di invio e di routing dei comandi MFC 1,0 si evolve l'architettura di MFC 2,0

Le finestre del messaggio di WM_COMMAND che viene eseguito l'overload di per fornire notifiche dei comandi di menu, i tasti di scelta rapida e delle notifiche della finestra di dialogo-controllo.

MFC 1,0 generato su quello di un piccolo consentendo a un gestore comando, ad esempio “OnFileNew„) in una classe derivata di CWnd venga chiamato in risposta a WM_COMMANDspecifico.Ciò viene incollato insieme a una struttura di dati chiamata la mappa messaggi e comporta un meccanismo molto spazio-efficiente del comando.

Funzionalità aggiuntive inoltre fornita da MFC 1,0 per la separazione delle notifiche di controllo dai messaggi di comando.I controlli sono rappresentati da uno 16 bit ID, talvolta noto come un ID di comandoI controlli in genere iniziano da CFrameWnd ovvero un menu selezionato o un tasto di scelta rapida tradotto) e vengono indirizzati a varie altre finestre.

MFC 1,0 è stato utilizzato il routing dei comandi in senso limitato per l'implementazione dell'interfaccia a documenti (MDI) multipli.(Un delegato della finestra cornice MDI ordina alla finestra figlio MDI attiva.)

Questa funzionalità è stata generalizzata e estesa in MFC 2,0 per consentire i controlli essere gestito da una più vasta gamma di oggetti (non solo gli oggetti della finestra.Fornisce un'architettura più formale e più versatile per inviare messaggi e riutilizzata il routing della destinazione comando non solo per la gestione dei comandi, ma anche per aggiornare l'interfaccia utente oggetti (ad esempio voci di menu e pulsanti della barra degli strumenti) per riflettere la disponibilità corrente di un comando.

ID di comando

Vedere Visual C++ per una spiegazione del routing dei comandi e del processo di associazione.nota tecnica 20 contiene le informazioni sulla denominazione degli ID.

È possibile utilizzare il prefisso generico “ID_„ per gli ID di comando.ID di comandi sono >= 0x8000.La riga del messaggio o la barra di stato verrà visualizzata la stringa descrittiva del comando se c " è una risorsa STRINGTABLE con gli stessi ID dell'ID di comando

Nelle risorse dell'applicazione, può ID comando viene visualizzato in diversi computer:

  • In una risorsa STRINGTABLE con lo stesso ID della richiesta di riga del messaggio.

  • Probabilmente in molte risorse di menu associati alle voci di menu da richiamare lo stesso comando.

  • (ANTICIPATO) in un pulsante della finestra di dialogo per un comando di GOSUB.

Nel codice sorgente dell'applicazione, può ID comando viene visualizzato in diversi computer:

  • Nel RESOURCE.H o altro file di intestazione simboli principale) per definire gli ID controlli specifici.

  • FORSE in una matrice di ID utilizzata per creare una barra degli strumenti.

  • In una macro di ON_COMMAND .

  • FORSE in una macro di ON_UPDATE_COMMAND_UI .

Attualmente, l'unica implementazione in MFC che richiede che gli ID di comando è >= 0x8000 è l'implementazione delle finestre di dialogo e controlli di GOSUB.

L'architettura del comando di routing i controlli e abilitare è compatibile con le applicazioni utilizzano, le voci di menu, pulsanti della barra degli strumenti, barra della finestra di dialogo utilizzare i pulsanti, le altre barre di controllo e altri elementi dell'interfaccia utente progettati per aggiornare i controlli di route e su richiesta o il controllo ID a una destinazione comando principale (in genere la finestra cornice principale).Che la destinazione comando principale può utilizzare il comando o le notifiche di controllo a un'altra destinazione comando oggetti in base alle proprie esigenze.

Una finestra di dialogo (modale o non modale) può trarre vantaggio da alcune delle funzionalità dell'architettura del comando se si assegna ID di controllo della finestra di dialogo all'identificazione appropriata di comandoIl supporto per le finestre di dialogo non è automatico, pertanto è possibile che sia necessario scrivere il codice del componente aggiuntivo.

Si noti che per tutte queste funzionalità funzionino correttamente, gli ID di comando deve essere >= 0x8000.Poiché molte finestre di dialogo potrebbero ottenere destinate allo stesso frame, i controlli condivisi devono essere >= 0x8000, mentre il IDCs non condiviso in una finestra di dialogo specifica deve essere <= 0x7FFF.

È possibile inserire un pulsante standard in una finestra di dialogo modale normale con il IDC impostare il pulsante all'identificazione appropriata di comandoQuando l'utente seleziona il pulsante, il proprietario della finestra di dialogo (in genere la finestra cornice principale) ottiene il comando come qualsiasi altro comando.Si tratta di un comando di GOSUB poiché in genere è utilizzata per accedere a un'altra finestra di dialogo (un GOSUB della prima finestra di dialogo).

È anche possibile chiamare la funzione CWnd::UpdateDialogControls nella finestra di dialogo e passare l'indirizzo della finestra cornice principale.Questa funzione attiva o disabilita i controlli della finestra di dialogo basati su se dispongono di gestori comandi in un frame.Questa funzione viene chiamata automaticamente automaticamente per le barre di controllo nel ciclo inattivo dell'applicazione, ma è necessario chiamarlo direttamente per le finestre di dialogo comuni che si desidera ottenere questa funzionalità.

Quando ON_UPDATE_COMMAND_UI viene chiamato

Gestendo in/stato di selezione di tutte le voci di menu di un programma continuamente possono rappresentare un problema dispendiosa in termini di calcolo.Una tecnica comune è voci di menu controllo/abilitare solo quando l'utente seleziona il POPUP.L'implementazione di MFC 2,0 di CFrameWnd gestisce il messaggio di WM_INITMENUPOPUP e utilizza l'architettura di routing dei comandi per determinare gli stati dei menu tramite i gestori di ON_UPDATE_COMMAND_UI .

CFrameWnd gestisce inoltre il messaggio di WM_ENTERIDLE per descrivere la voce di menu corrente selezionata nella barra di stato (anche nota come la riga del messaggio).

La struttura di menu di un'applicazione, modificata tramite Visual C++, viene utilizzata per rappresentare i controlli potenziali disponibili al momento di WM_INITMENUPOPUP .I gestori diON_UPDATE_COMMAND_UI possono modificare lo stato o il testo di un menu, o per gli utilizzi avanzati quali l'elenco dei file utilizzati di recente o il menu di scelta rapida di verbi OLE), effettivamente modificare la struttura del menu prima che il menu venga applicato lo stile.

Lo stesso tipo di elaborazione di ON_UPDATE_COMMAND_UI avviene per le barre degli strumenti (e altre barre di controllo) quando l'applicazione passa nel ciclo inattivo.Vedere il riferimento la libreria di classi e nota tecnica 31 per ulteriori informazioni sulle barre di controllo.

Se si utilizza una struttura annidata del menu, si noterà che il gestore di ON_UPDATE_COMMAND_UI per la prima voce del menu di scelta rapida viene chiamato in due casi diversi.

Innanzitutto, viene chiamato dal menu di scelta rapida stesso.Questa operazione è necessaria perché i menu di scelta rapida non hanno ID e viene utilizzato l'ID della prima voce di menu del menu di scelta rapida per riferirci per l'intero menu di scelta rapida.In questo caso, la variabile membro di m_pSubMenu dell'oggetto di CCmdUI non sarà Null e indicherà il menu di scelta rapida.

In secondo luogo, viene chiamato immediatamente prima delle voci del menu di scelta rapida devono essere disegnate.In questo caso, l'ID si riferisce solo alla prima voce di menu e la variabile membro di m_pSubMenu dell'oggetto di CCmdUI sarà NULL.

Ciò consente di attivare il menu di scelta rapida separato dalle relative voci di menu, ma che richiede la scrittura in un determinato dal codice presente.Ad esempio, in un menu annidato con la struttura seguente:

File>
    New>
        Sheet (ID_NEW_SHEET)
        Chart (ID_NEW_CHART)

I controlli di ID_NEW_CHART e di ID_NEW_SHEET possono essere abilitati o disabilitati indipendente.Il menu di scelta rapida di Nuovo deve essere abilitato se uno dei due è abilitato.

Il gestore comando per ID_NEW_SHEET (il primo comando nel popup) è simile al seguente:

void CMyApp::OnUpdateNewSheet(CCmdUI* pCmdUI)
{
    if (pCmdUI->m_pSubMenu != NULL)
    {
        // enable entire pop-up for "New" sheet and chart
        BOOL bEnable = m_bCanCreateSheet || m_bCanCreateChart;

        // CCmdUI::Enable is a no-op for this case, so we
        //   must do what it would have done.
        pCmdUI->m_pMenu->EnableMenuItem(pCmdUI->m_nIndex,
            MF_BYPOSITION | 
                (bEnable ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
        return;
    }
    // otherwise just the New Sheet command
    pCmdUI->Enable(m_bCanCreateSheet);
}

Il gestore comando per ID_NEW_CHART sarebbe un gestore comando e un aspetto normali di aggiornamento simile al seguente:

void CMyApp::OnUpdateNewChart(CCmdUI* pCmdUI)
{
    pCmdUI->Enable(m_bCanCreateChart);
}

ON_COMMAND e ON_BN_CLICKED

Le macro della mappa messaggi per ON_COMMAND e ON_BN_CLICKED sono uguali.Il meccanismo di routing di comandi e di notifica di controllo MFC utilizza solo l'ID di comando per decidere dove il routing su.Le notifiche di controllo con un codice di notifica di controllo di zero (BN_CLICKED) vengono interpretate come controlli.

[!NOTA]

Infatti, tutti i messaggi di notifica di controllo attraversano la catena del gestore comando.Ad esempio, sia tecnicamente possibile che scrivere un gestore di notifica per EN_CHANGE nella classe del documento.Questa operazione non è in genere consigliabile perché le applicazioni pratiche di questa funzionalità sono poche, la funzionalità non è supportata da ClassWizard e l'utilizzo della funzionalità può generare codice fragile.

Disabilitare disabilitare automatico dei pulsanti

Se si inserisce un pulsante di una barra della finestra di dialogo, o una finestra di dialogo utilizzando dove si chiama CWnd::UpdateDialogControls sui propri, si noterà che i pulsanti che non dispongono di gestori ON_UPDATE_COMMAND_UI o di ON_COMMAND automaticamente verranno disabilitati automaticamente dal framework.In alcuni casi, non sarà necessario disporre di un gestore, ma sarà il pulsante per rimanere attivato.Il modo più semplice per ottenere questo risultato consiste nell'aggiungere un gestore comando fittizio (facile eseguire con ClassWizard) e non effettuare alcuna operazione.

Instradamento dei messaggi delle finestre

L'esempio seguente viene illustrato un certo numero di argomenti avanzati sulle classi MFC e come il routing dei messaggi di windows e altri argomenti di influiscono su.Le informazioni di seguito vengono descritte solo brevemente.Fare riferimento al riferimento della libreria di classi per informazioni dettagliate sulle API pubblici.Fare riferimento al codice sorgente della libreria MFC per ulteriori informazioni sui dettagli di implementazione.

Fare riferimento in alternativa a nota tecnica 17 per informazioni dettagliate sulla pulitura della finestra, un argomento molto importante per qualsiasi CWnddi classi derivate.

Problemi di CWnd

La funzione membro CWnd::OnChildNotify di implementazione fornisce un'architettura potente ed estensibile per le finestre figlio (denominate anche i controlli) a hook o altrimenti viene ricezione dei messaggi, dei controlli e delle notifiche di controllo che visitano il relativo padre (o “al proprietario„).Se la finestra figlio (/control) è un oggetto stesso C++ CWnd , la funzione virtuale OnChildNotify viene chiamata prima con i parametri dal messaggio originale (ovvero una struttura di MSG ).La finestra figlio può lasciare il messaggio solo, mangiarla, o modificare il messaggio per il padre (in).

L'implementazione di CWnd di impostazione predefinita gestisce i seguenti messaggi e utilizza la funzione hook di OnChildNotify per consentire alle finestre figlio (controlli) al primo accesso al messaggio:

  • WM_MEASUREITEM e WM_DRAWITEM (per auto-tiraggio)

  • WM_COMPAREITEM e WM_DELETEITEM (per auto-tiraggio)

  • WM_HSCROLL e WM_VSCROLL

  • WM_CTLCOLOR

  • WM_PARENTNOTIFY

Si noterà che l'hook di OnChildNotify viene utilizzato per modificare i messaggi di disegno del proprietario nei messaggi di auto-tiraggio.

Oltre agli hook di OnChildNotify , i messaggi di scorrimento sono ulteriore comportamento di routing.Vedere di seguito per ulteriori informazioni sulle barre di scorrimento e i database di origine messaggi di WM_VSCROLL e di WM_HSCROLL .

Problemi di CFrameWnd

La classe di CFrameWnd fornisce il routing dei comandi einterfaccia utente che aggiorna l'implementazione.Ciò viene utilizzata principalmente per la finestra cornice principale dell'applicazione (CWinApp::m_pMainWnd) ma si applica a tutte le applicazioni utilizzano.

La finestra cornice principale è la finestra con la barra dei menu e costituisce l'elemento padre della barra di stato o riga del messaggio.Fare riferimento in alternativa alla discussione di precedenza sul routing dei comandi e su WM_INITMENUPOPUP.

La classe di CFrameWnd fornisce la gestione della visualizzazione attiva.I seguenti messaggi vengono indirizzati alla visualizzazione attiva:

  • Tutti i messaggi di comando (la visualizzazione attiva ottiene il primo accesso di scelta.

  • Messaggi di WM_VSCROLL e diWM_HSCROLL barre di scorrimento di pari livello (vedere di seguito).

  • WM_ACTIVATE (e WM_MDIACTIVATE per MDI) vengono attivati nelle chiamate alla funzione virtuale CView::OnActivateView.

Problemi di CMDIFrameWnd/CMDIChildWnd

Entrambe le classi della finestra cornice MDI derivano da CFrameWnd e pertanto sia abilitate per lo stesso tipo di routing dei comandi di aggiornamento dell'interfaccia utente descritti in CFrameWnd.In un'applicazione MDI tipica, solo la finestra cornice principale ovvero l'oggetto di CMDIFrameWnd ) utilizza la barra dei menu e la barra di stato e pertanto è l'origine principale dell'implementazione di routing dei comandi.

La combinazione generale di routing è che la finestra figlio MDI attiva ottiene il primo accesso ai controlli.Le funzioni di PreTranslateMessage di impostazione predefinita gestiscono le tabelle dei tasti di scelta rapida sia per le finestre figlio MDI primo) che la cornice MDI (secondo) nonché i tasti di scelta rapida comando di sistema standard MDI in genere gestiti da TranslateMDISysAccel (').

Problemi della barra di scorrimento

Nella gestione del scorrimento-messaggio (WM_HSCROLL/OnHScroll e/o WM_VSCROLL/OnVScroll), è necessario tentare di scrivere il codice del gestore in modo da non si basa su se il messaggio della barra di scorrimento non riuscito.Ciò non solo è finestre generali pubblica, poiché i messaggi di scorrimento possono provenire da quello dei controlli barra di scorrimento o dalle barre di scorrimentoWS_VSCROLL / WS_HSCROLLche non sono controlli barra di scorrimento.

MFC estende quello di consentire ai controlli barra di scorrimento sia figlio o elementi di pari livello della finestra che si scorre (infatti, la relazione tra la barra di scorrimento e finestra padre/figlio che si scorre possono essere qualsiasi elemento).Ciò è particolarmente importante per le barre di scorrimento condivise con finestre con separatore.Fare riferimento in alternativa a nota tecnica 29 per i dettagli nell'implementazione di CSplitterWnd inclusi ulteriori informazioni sui problemi condivise barra di scorrimento.

In una nota rapida, esistono due classi derivate di CWnd in cui gli stili della barra di scorrimento specificati creano il tempo sono bloccati o non sono stati passati alle finestre.Una volta passato a una routine di creazione, WS_HSCROLL e WS_VSCROLL possono essere impostati in modo indipendente, ma dopo la creazione non può essere modificata.Naturalmente, non è necessario direttamente test o impostare il WS_? SCORRERE i bit di stile della finestra che hanno creato.

Per CMDIFrameWnd gli stili che barra di scorrimento si passa a Create o LoadFrame viene utilizzato per creare il MDICLIENT.Se si desidera ottenere un'area scorrevole di MDICLIENT quali le finestre Program Manager) assicurarsi di impostare entrambi gli stili della barra di scorrimento (WS_HSCROLL | WS_VSCROLL) per lo stile utilizzato per creare CMDIFrameWnd.

Per CSplitterWnd gli stili della barra di scorrimento vengono applicate le barre di scorrimento condivise speciali per le aree del separatore.Per finestre con separatore statico, in genere non verrà impostata qualsiasi stile della barra di scorrimento.Per le finestre con separatore dinamico, in genere impostare lo stile della barra di scorrimento per la direzione in cui suddividerete, ovvero, WS_HSCROLL se è possibile dividere le righe, WS_VSCROLL se è possibile dividere le colonne.

Vedere anche

Altre risorse

Note tecniche del numero

Note tecniche per categoria