TN021: Befehl und Meldungsrouting

HinweisHinweis

Im Folgenden technischen Hinweis ist nicht aktualisiert wurde, seitdem er erstmals in der Onlinedokumentation enthalten waren.Folglich können mehrere Prozeduren und Themen veraltet oder falsch.Die aktuellsten Informationen wird empfohlen, zum Thema Onlinedokumentations im Index finden.

Dieser Hinweis wird die Architektur der Weiterleitung und - routing- Befehls sowie die erweiterten allgemeinen Themen in der Meldungslenkung Fenster.

Verweisen Sie in Visual C++ für allgemeine Informationen über die Architektur an, welche hier besonders die Unterscheidung zwischen Windows-Meldungen, Steuerelementbenachrichtigungen und Befehle beschrieben werden.Dieser Hinweis wird davon ausgegangen, dass Sie mit den Problemen sehr vertraut sind, die in der gedruckten Dokumentation und nur sehr Adressen der Erweiterte Themen beschrieben werden.

Der Befehls-Routing-und Dispatch-MFC 1.0 entwickelte Funktionen zur Architektur MFC 2.0

Windows bietet die WM_COMMAND Meldung überladen wird, um Benachrichtigungen von Menübefehlen, Zugriffstasten und Dialogfelds Steuerelement Benachrichtigungen bereitzustellen.

MFC 1.0 auf dem wenig erstellt durch das Allow einem Befehlshandler (z. B. "OnFileNew") in einer abgeleiteten Klasse, um CWnd als Reaktion auf ein bestimmtes WM_COMMAND aufgerufen werden.Dies wird zusammen mit einer Datenstruktur geklebt, die die Meldungszuordnung aufgerufen wird und führt zu einem sehr SPACE-effizienten Mechanismus für den Befehl.

Das bereitgestellte zusätzliche Funktionalität MFC 1.0 auch für das Trennen von Meldungen aus den Befehl Steuerelementbenachrichtigungen.Befehle werden von einer 16-Bit-ID dargestellt, manchmal auch als eine Befehls-ID.Befehle werden normalerweise von CFrameWnd (d. h. ein Menü ausgewählt oder eine Tastenkombination übersetzter) ab, und rufen weitergeleitet an verschiedene andere Fenster ab.

Verwendetes Befehls routing MFC 1.0 in einem eingeschränkten Sinn für die Implementierung (Multiple Document Interface-).MDI-Rahmenfenster (Befehle eines Delegaten zu dem aktiven untergeordneten MDI-Fenster.)

Diese Funktionalität ist in MFC 2.0 verallgemeinert wurde und erweitert, um Befehle zu ermöglichen, über einen breiteren Bereich von Objekten (nicht nur Fensterobjekte) behandelt werden sollen.Sie stellt eine formalere und erweiterbarere Architektur zum Weiterleiten von Nachrichten bereit und verwendet das Befehlsziel nicht nur für die Behandlung von Befehlen für routing, sondern auch zum Aktualisieren von Benutzeroberflächenobjekte (z. B. Menüelemente und Symbolleisten-Schaltflächen), um die aktuelle Verfügbarkeit eines Befehls erneut wiederzugeben.

Befehls-ID

Für Visual C++ finden Sie eine Erläuterung des Befehls routings und des Bindungsvorgangs.Technischer Hinweis 20 enthält Informationen zu ID-Benennung.

Wir verwenden das allgemeine Präfix "ID_" für Befehls-IDs.Befehls-ID ist >= 0x8000.Die Meldungszeile oder der Statusleiste zeigt die Zeichenfolge beschreibungs Befehls auf, wenn es eine STRINGTABLE-Ressource mit der gleichen ID vorhanden sind, z. B. die Befehls-ID.

In den Ressourcen der Anwendung, wird eine Befehls-ID-Dose in mehreren eingefügt:

  • In einer STRINGTABLE-Ressource, die dieselbe ID wie die Nachricht Zeile Eingabeaufforderung enthält.

  • In vielen Menüressourcen, die möglicherweise an-Menüelemente angefügt werden, die denselben Befehl aufrufen.

  • GEWECHSELT (Dialogfeld) in einer Schaltfläche für einen GOSUB-Befehl.

Im Quellcode der Anwendung, wird eine Befehls-ID-Dose in mehreren eingefügt:

  • In Ihrem RESOURCE.H (oder in anderer Haupter Symbol headerdatei), um anwendungsspezifischer Befehls-IDs zu definieren.

  • MÖGLICHERWEISE ID in einem Array verwendet, um eine Symbolleiste zu erstellen.

  • In einem ON_COMMAND Makro.

  • MÖGLICHERWEISE in einem ON_UPDATE_COMMAND_UI Makro.

Derzeit ist die einzige Implementierung in MFC, die Befehls-IDs erfordert, >= 0x8000 ist die Implementierung von GOSUB-Dialogfeldern/- Befehlen.

GOSUB-Befehle unter Verwendung der Befehls-Architektur in den Dialogfeldern

Die Architektur der Befehls und der Aktivieren des Routings Befehle funktioniert gut mit den Menüelementen, Rahmenfenstern Symbolleisten-Schaltflächen Dialogleisten anderen Steuerleisten, Schaltflächen und anderen Benutzeroberflächenelementen, die entwickelt, um bei Bedarf aktualisiert und Befehle oder Steuerelement-IDs zu einem zentralen Befehlsziel (normalerweise das Hauptrahmenfenster) weitergeleitet werden.Diese Hauptes Befehlsziel möglicherweise den Befehl oder die Steuerelementbenachrichtigungen zu einem anderen Befehl zielobjekten entsprechend weitergeleitet werden.

Ein nicht modales oder modale Dialogfeld () kann einige der Features der Architektur der Befehl profitieren, wenn Sie die Steuerelement-ID des Dialogfelds Steuerelements zur entsprechenden Befehl zuweisen.Unterstützung für Dialogfelder ist nicht automatisch. Daher müssen Sie möglicherweise einen zusätzlichen Code schreiben.

Beachten Sie, dass alle diese Funktionen ordnungsgemäß, die Befehls-IDs >= 0x8000 sein sollten.Da viele Dialogfelder abrufen können den gleichen Frame weitergeleitet, sollten freigegebene Befehle >= 0x8000 nicht freigegeben sein, während das Dialogfeld <= IDC in einem bestimmten 0x7FFF werden soll.

Sie können eine normale Schaltfläche in einem normalen modales Dialogfeld mit den Schaltflächen des IDC mit der entsprechenden festgelegten platzieren Befehls-ID.Wenn der Benutzer auf die Schaltfläche auswählt, ruft der Besitzer des Dialogfelds (normalerweise das Hauptrahmenfenster) den Befehl ebenso wie jeder andere Befehl ab.Dies wird als GOSUB-Befehl aufgerufen, da es normalerweise verwendet wird, um ein weiteres Dialogfeld (ein GOSUB des ersten Dialogfelds oben) zu bringen.

Sie können die Funktion CWnd::UpdateDialogControls im Dialogfeld aufrufen und führen die Adresse des Hauptrahmenfensters.Diese Funktion aktiviert oder deaktiviert die Steuerelemente Dialogfeld abhängig davon, ob sie Befehlshandler in den Frames haben.Diese Funktion wird automatisch für die Steuerleisten in der Ruheschleife Ihrer Anwendung, Sie müssen diese jedoch direkt für normale Dialogfelder aufrufen, dass Sie diese Funktion verwenden möchten.

Wenn ON_UPDATE_COMMAND_UI aufgerufen wird

Aufrechterhalten aktiviert/Aktivierungszustand aller Menüelemente eines Programms kann ein Problem rechenintensives ständig sein.Eine übliche Vorgehensweise besteht darin zu aktivieren bzw. menüelemente überprüft nur, wenn der Benutzer das POPUP auswählt.Die Implementierung von MFC 2.0 CFrameWnd behandelt die WM_INITMENUPOPUP Meldung und die Architektur der routing Befehls verwendet, um die Zustände von Menüs von ON_UPDATE_COMMAND_UI-Handler zu bestimmen.

Bearbeiten CFrameWnd auch die WM_ENTERIDLE Nachricht, um das aktuelle Menüelement zu beschreiben, das auf der Statusleiste ausgewählt wird (auch als die Meldungszeile).

Die Menüstruktur einer Anwendung, die von Visual C++ bearbeitet, wird die möglichen Befehle darstellen, die an WM_INITMENUPOPUP verfügbar sind.ON_UPDATE_COMMAND_UI-Handler können den Status und den Text eines Menüs ändern oder für erweitertes verwenden (z. B. die Datei-MRU-Liste oder das OLE-Verb popupmenü) ändern, die Menüstruktur, bevor das Menü gezogen wird.

Die gleiche Sortierung von ON_UPDATE_COMMAND_UI Verarbeitung ist für Symbolleisten und andere Steuerleisten) ausgeführt (wenn die Anwendung ihre Ruheschleife eintritt.Zeigen Sie die Klassenbibliothek zu verweisen und Technischer Hinweis 31 Informationen zu Steuerleisten.

Geschachtelte Popupmenüs

Wenn Sie eine geschachtelte Menüstruktur verwenden, beachten Sie, dass der ON_UPDATE_COMMAND_UI-Handler für das erste Menüelement im Popupmenü in zwei verschiedenen Fällen aufgerufen wird.

Zuerst wird es für das Popupmenü selbst aufgerufen.Dies ist erforderlich, da Popupmenüs keine ID haben und die ID des ersten Menüelements des Popupmenüs verwenden, um das gesamte Popupmenü zuzugreifen.In diesem Fall ist die m_pSubMenu-Membervariable des CCmdUI-Objekts nicht NULL und zeigt auf das Popupmenü.

Zweitens wird sie aufgerufen, unmittelbar bevor die Menüelemente im Popupmenü gezeichnet werden sollen.In diesem Fall wird die ID nur zum ersten Menüelement und die m_pSubMenu-Membervariable des CCmdUI-Objekts ist NULL.

Dies ermöglicht es Ihnen, das Popupmenü zu aktivieren, die von den Menüelementen unterscheidet, erfordert jedoch, dass Sie einem Menü bewussten Code schreiben.Beispielsweise kann in einem geschachtelten Menü mit der folgenden Struktur:

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

Die ID_NEW_SHEET- und ID_NEW_CHART-Befehle können einzeln aktiviert oder deaktiviert werden.Das Neu Popupmenü muss aktiviert werden, wenn einer der beiden aktiviert ist.

Der Befehlshandler für ID_NEW_SHEET (der erste Befehl im Popupfenster) würde etwa aussehen:

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);
}

Der Befehlshandler für ID_NEW_CHART würde ein normaler Befehls Updates Klassenhandler werden, und etwa aussehen:

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

ON_COMMAND und ON_BN_CLICKED

Die Meldungszuordnungs Makros für ON_COMMAND und ON_BN_CLICKED sind identisch.Der MFC-Befehls- und - Steuerelementbenachrichtigungs routing Mechanismus für die Befehls-ID nur verwendet, um zu entscheiden, wo auf weiterleitet.Steuerelementbenachrichtigungen mit Steuerelementbenachrichtigungs Code BN_CLICKED(null) werden als Befehl interpretiert.

HinweisHinweis

Tatsächlich ausgeführt werden alle Meldungen Steuerelementbenachrichtigungs die Befehlshandler Kette durch.Beispielsweise ist es technisch möglich Steuerelementbenachrichtigungs Sie einen Ereignishandler für EN_CHANGE in der Dokumentklasse zu schreiben.Dies ist im Allgemeinen nicht, da die praktische Anwendungen diese Funktion wenige sind, die Funktion wird nicht unterstützt ClassWizard empfehlenswert, und durch Verwendung der Funktion kann empfindlichen Code führen.

Die automatische Deaktivierung von Schaltflächen-Steuerelementen deaktivieren

Wenn Sie ein Schaltflächen-Steuerelement auf einer Dialogleiste oder in einem Dialogfeld platzieren, mit dem Sie CWnd::UpdateDialogControls auf Ihren eigenen aufrufen, werden Sie feststellen, dass Schaltflächen, die nicht ON_COMMAND oder ON_UPDATE_COMMAND_UI-Handler verfügen, durch das Framework automatisch für Sie deaktiviert werden.In einigen Fällen müssen Sie keinen Handler haben, aber Sie möchten die Schaltfläche aktiviert bleiben.Die einfachste Möglichkeit, dies zu erreichen, einen blinden Befehlshandler hinzu (einfach, mit ClassWizard erforderlich) und nichts in ihr durchzuführen.

Fenster-Meldungslenkung

Im Folgenden wird beschrieben mehr erweiterte Themen auf den MFC-Klassen und andere Themen Windows-Meldungs-Routing und wie sie auswirken.Die Informationen werden hier nur kurz beschrieben.Weitere Informationen finden Sie unter Klassenbibliotheks-Verweis den Einzelheiten über öffentliche API an.Weitere Informationen dazu finden Sie in den Quellcode der MFC-Bibliotheks Weitere Informationen zu Implementierungsdetails an.

Verweisen Sie stattdessen Technischer Hinweis 17 cleanup Einzelheiten über Fenster, ein sehr wichtiges Thema für alle von CWnd abgeleiteten Klassen.

CWnd-Probleme

Die Memberfunktion einer Implementierung CWnd::OnChildNotify stellt ein leistungsstarkes und erweiterbare Architektur für untergeordnete Fenster (auch Steuerelemente) an den Hook bereit oder andernfalls der Meldungen, der den Befehlen und Steuerelementbenachrichtigungen informiert, die zum übergeordneten Element wechseln (oder "Besitzer").Wenn das untergeordnete Fenster (/control) CWnd ++ im C-Format Objekt selbst befindet, wird die virtuelle Funktion OnChildNotify zunächst mit den Parametern aus der ursprünglichen Nachricht aufgerufen (d. h. eine MSG-Struktur).Das untergeordnete Fenster kann die Nachricht nicht verlassen, um sie essen oder die Meldung für das übergeordnete Element ändern (selten).

Die standardmäßige Implementierung CWnd behandelt die folgenden Meldungen verknüpfen und verwendet den OnChildNotify untergeordnete Steuerelemente (Fenster) zum ersten Zugriff an der Nachricht zu ermöglichen:

  • WM_MEASUREITEM und WM_DRAWITEM (für Selbstzeichnunges)

  • WM_COMPAREITEM und WM_DELETEITEM (für Selbstzeichnunges)

  • WM_HSCROLL und WM_VSCROLL

  • WM_CTLCOLOR

  • WM_PARENTNOTIFY

Beachten Sie den OnChildNotify Hook dienen zum Ändern von Ownerdrawn- Selbstzeichnunge in Nachrichten.

Zusätzlich zum OnChildNotify Hook haben Bildlaufmeldungen weiteren Routing verhalten.Weitere Informationen finden Sie unten für die weitere Informationen über WM_HSCROLL Quellen für Bildlaufleisten und WM_VSCROLL und Meldungen.

CFrameWnd-Probleme

Die CFrameWnd-Klasse stellt die meisten des Befehls routings und die Benutzeroberfläche Implementierung aktualisiert.Dies wird hauptsächlich für das Hauptrahmenfenster der Anwendung (CWinApp::m_pMainWnd) gilt jedoch alle Rahmenfenster.

Das Hauptrahmenfenster ist das Fenster mit der Menüleiste und ist das übergeordnete Element der Statusleisten- oder Meldungszeile.Weitere Informationen finden Sie in der oben genannten Diskussion ein Befehl Routing und WM_INITMENUPOPUP. an

Die CFrameWnd-Klasse stellt Verwaltung der aktiven Ansicht.Die folgenden Meldungen werden durch die aktive Ansicht weitergeleitet:

  • Alle Meldungen Befehls (die aktive Ansicht ruft ersten Zugriff darauf).

  • WM_HSCROLL und WM_VSCROLL Meldungen von den gleichgeordneten Bildlaufleisten (siehe unten).

  • WM_ACTIVATE (und WM_MDIACTIVATE für MDI) gelegt werden Aufrufe der virtuellen Funktion CView::OnActivateView ab.

Probleme bei CMDIFrameWnd-/CMDIChildWnd

Beide Klassen leiten sich von CFrameWnd MDI-Rahmenfenster und werden daher für dieselbe Sortierung des Befehls routings und der Benutzeroberfläche aktualisierens ermöglicht, die in CFrameWnd bereitgestellt werden.In einer typischen MDI-Anwendung nur das Hauptrahmenfenster (d. h. das CMDIFrameWnd-Objekt) enthält die Menüleiste und die Statusleiste an und ist daher die zentrale Quelle der Implementierung des Befehls routing.

Das allgemeine Schema für das Routing handelt, dass das aktive untergeordnete MDI-Fenster ersten Zugriff auf den Befehlen abruft.Die Standardeinstellung PreTranslateMessage Zugriffstastentabellen bearbeiten Funktionen für untergeordnete MDI-Fenster (first) und die MDI-Frame (second) sowie die standardmäßige MDI SYSTEM Befehl Zugriffstasten, die normalerweise durch TranslateMDISysAccel behandelt werden (Last).

Bildlaufleisten-Probleme

Von wenn Sie WM_HSCROLL SCROLL Nachricht (bzw.OnHScroll und/oder WM_VSCROLL/OnVScroll) behandeln, sollten Sie versuchen, den Handlercode zu schreiben. Daher wird er nicht aufgelistet, wo die für eine Bildlaufleiste stammt.Dies ist nicht nur ein Problem, da Windows allgemeinen Bildlaufmeldungen von den echten ScrollBar-Steuerelementen oder WS_HSCROLL/WS_VSCROLL Bildlaufleisten stammen können, die nicht ScrollBar-Steuerelementen sind.

MFC erweitert das zum ScrollBar-Steuerelementen können, sodass entweder untergeordnete Elemente oder nebengeordnete Elemente des Fensters befinden, das den Bildlauf ausgeführt wird, kann das tatsächlich (über- und untergeordnete Beziehung zwischen der Bildlaufleiste und das Fenster, das den Bildlauf durchgeführt wird, alle sein).Dies ist für freigegebene Bildlaufleisten mit Splitterfenstern besonders wichtig.Verweisen Sie stattdessen Technischer Hinweis 29 Einzelheiten über die Implementierung von CSplitterWnd einschließlich weitere Informationen zu freigegebenen Probleme im Zusammenhang mit Bildlaufleisten angezeigt.

Auf einer Randbemerkung gibt es zwei CWnd abgeleitete Klassen, in denen die Bildlaufleisten Formate, die zur Erstellungszeit angegeben werden, aufgefangen werden, die nicht mit Windows übergeben.Wenn sie in einer routine Build übergeben werden, können WS_HSCROLL und WS_VSCROLL unabhängig festgelegt werden, aber nach der Erstellung nicht geändert werden kann.Natürlich sollten Sie das WS_ nicht direkt festlegen oder testen? FÜHREN Sie einen Bildlauf des Fensters Formatbits dem sie erstellt haben.

Für CMDIFrameWnd die Bildlaufleisten Stile, die Sie in Create übergeben, oder LoadFrame werden verwendet, um das MDICLIENT zu erstellen.Wenn Sie einen bildlauffähigen MDICLIENT-Bereich haben möchten (z. B. den Windows-Programm-Manager) müssen Sie unbedingt beide Formate für Bildlaufleisten festgelegt (WS_HSCROLL | WS_VSCROLL) für das Format verwendet, um CMDIFrameWnd zu erstellen.

Für CSplitterWnd gelten die Bildlaufleisten Spaltenformate auf die spezifischen Bereiche Splitter für die Bildlaufleisten freigegebenen.Für statische Splitterfenster legen Sie normalerweise nicht jedes Format für Bildlaufleisten festgelegt.Für dynamische Splitterfenster haben Sie in der Regel das Format für Bildlaufleisten festgelegt für die Richtung, die Sie teilen WS_HSCROLL d. h., wenn Sie Zeilen teilen können, WS_VSCROLL, wenn Sie Spalten aufteilen können.

Siehe auch

Weitere Ressourcen

Technische Hinweise durch Zahl

Technische Hinweise nach Kategorie