TN021: Befehl und Nachrichtenrouting

Diese Applikationsschrift beschreibt den Befehl routing und Versand Architektur sowie fortgeschrittene Themen im allgemeinen Fenster Nachrichtenrouting.

Siehe Visual C++ Programmer's Guide für allgemeine Informationen über die hier beschriebenen Architekturen vor allem die Unterscheidung zwischen Windows Nachrichten, Steuerelement-Benachrichtigungen und Befehle. Diese Notiz nimmt, Sie sind sehr vertraut mit den Fragen, die in der gedruckten Dokumentation beschrieben und nur sehr fortgeschrittene Themen behandelt.

MFC-Befehlsrouting und Versand 1.0 Funktionalität entwickelt sich zu MFC 2.0 Architektur

Windows hat die WM_COMMAND -Nachricht, die überlastet ist, Benachrichtigungen von Menübefehlen, Zugriffstasten und Dialogfeld-Steuerelement-Benachrichtigungen bereitstellen.

MFC 1.0 bebaut, die ein wenig dadurch, dass einen Befehlshandler (z. B. "OnFileNew") in einem CWnd abgeleitete Klasse als Reaktion auf eine bestimmte WM_COMMANDaufgerufen. Dies zusammen mit einer Datenstruktur namens die Meldungszuordnung geklebt ist, und führt eine sehr platzsparende Befehl Mechanismus.

MFC 1.0 bereitgestellt auch zusätzliche Funktionen für das Trennen der Steuerelement-Benachrichtigungen von Befehlsmeldungen. Befehle werden durch einen 16-Bit-ID, manchmal bekannt als eine Befehls-ID dargestellt. Befehle fangen normalerweise von einem CFrameWnd (zB: ein Menü auswählen oder einen übersetzten Beschleuniger) und erhalten eine Vielzahl von anderen Fenstern weitergeleitet.

MFC 1.0 verwendet Befehlsrouting in einem begrenzten Sinne für die Durchführung von mehrere Dokument Interface (MDI). (Ein MDI-Rahmenfenster delegieren Befehle an seine aktiven untergeordneten MDI-Fenster.)

Diese Funktionalität wurde generalisiert und verlängert in MFC 2.0 Befehle von einer breiteren Palette von Objekte (nicht nur Fenster) behandelt werden können. Es bietet eine weitere formale und erweiterbare Architektur für das routing von Nachrichten und wiederverwendet den Befehl Ziel Arbeitsplan für die Behandlung nicht nur Befehle, sondern auch für die Aktualisierung der Benutzeroberflächenobjekte (wie Menüelemente und Symbolleisten-Schaltflächen) entsprechend die aktuelle Verfügbarkeit eines Befehls.

Befehls-IDs

Eine Erklärung des Befehls-routing und verbindlichen Prozeß finden Sie unter Visual C++ Programmer's Guide . Technische Anmerkung 20 enthält Informationen zur Benennung von ID.

Wir verwenden das generische Präfix "ID_" für Befehls-IDs. Befehls-IDs sind ≫ = 0 x 8000. Die Statusleiste für die Zeile oder Status wird der Befehlszeichenfolge Beschreibung zeigen, wenn eine STRINGTABLE-Ressource mit den selben IDs wie die Befehls-ID vorhanden ist.

In den Ressourcen der Anwendung wird ein Befehl ID können an mehreren Stellen:

Im Quellcode der Anwendung wird ein Befehl ID können an mehreren Stellen:

Derzeit werden die einzige Implementierung in MFC, die Befehls-IDs erfordert ≫ = 0 x 8000 ist die Implementierung der GOSUB Dialoge/Befehle.

GOSUB-Befehle, mit Befehl Architektur in Dialogen

Die Befehl Architektur routing und Aktivieren von Befehlen funktioniert gut mit Rahmenfenster, Menüelemente, Symbolleisten-Schaltflächen, Dialogfeld Schaltflächen, anderen Steuerleisten und andere Elemente der Benutzeroberfläche aktualisieren auf Nachfrage und Route Befehle oder Steuerelement-IDs zu einem Hauptbefehl Ziel (in der Regel das Hauptrahmenfenster) entwickelt. Die wichtigsten Befehlsziel kann die Befehl oder das Steuerelement Benachrichtigungen, andere Befehl Zielobjekte als geeignete route.

Ein Dialog (modal oder nicht modal) kann von einige der Features der Befehl Architektur profitieren, wenn Sie das Dialogfeld-Steuerelement die Steuerelement-ID der entsprechenden Befehls-ID zuweisen Unterstützung für Dialoge erfolgt nicht automatisch, so dass Sie möglicherweise zusätzlichen Code schreiben.

Beachten Sie, daß die Befehls-IDs für alle diese Funktionen ordnungsgemäß funktionieren, Gt; = 0 x 8000. Da viele Dialoge auf den gleichen Rahmen weitergeleitet bekommen konnte, sollte gemeinsam genutzten Befehle > = 0 x 8000, während des nicht freigegebenen IDC in einem bestimmten Dialogfeld sollte < = 0x7FFF.

Sie können eine normale Schaltfläche in einen normalen modalen Dialog mit den IDC der Schaltfläche legen Sie auf der entsprechenden Befehls-ID platzieren. Wenn der Benutzer die Schaltfläche auswählt, ruft den Besitzer des Dialogfelds (in der Regel das Hauptrahmenfenster) den Befehl genau wie jeden anderen Befehl ab. Dies wird als GOSUB-Befehl bezeichnet, da es in der Regel verwendet wird, um eine andere öffnen (eine GOSUB im ersten Dialog).

Sie können auch rufen Sie die Funktion CWnd::UpdateDialogControls auf Ihr Dialogfeld und übergeben sie die Adresse des das Hauptrahmenfenster. Diese Funktion wird aktiviert oder deaktiviert die Dialogfeldsteuerelemente Grundlage ob sie Befehlshandler im Rahmen haben. Diese Funktion wird automatisch für Sie zum Anpassen von Steuerleisten in Ihrer Anwendung Leerlaufschleife aufgerufen, aber Sie müssen es für normale Dialoge, die Sie wünschen, haben diese Funktion direkt aufrufen.

Wenn ON_UPDATE_COMMAND_UI aufgerufen wird

Der aktiviert/geprüften Zustand der Menüelemente ein Programm ständig beibehalten kann rechnerisch teuer problematisch. Eine gängige Technik ist zu aktivieren/Menüelemente Kontrollkästchen nur, wenn der Benutzer das POPUP auswählt. Die MFC 2.0-Implementierung von CFrameWnd verarbeitet die Nachricht WM_INITMENUPOPUP und Routingarchitektur Befehl verwendet, um zu bestimmen, die Zustände des Menüs durch ON_UPDATE_COMMAND_UI -Handler.

CFrameWnd behandelt auch die WM_ENTERIDLE Nachricht beschreiben das aktuelle Menü ausgewählten Element auf dem Status-Stab (auch bekannt als der Nachrichtenzeile).

Einer Anwendung Menüstruktur, herausgegeben von Visual C++ wird verwendet, um die potenziellen WM_INITMENUPOPUP Zeitpunkt verfügbaren Befehle darstellen. ON_UPDATE_COMMAND_UI -Handler können der Staat oder Text eines Menüs, oder für Fortgeschrittene Anwender (wie die Datei MRU-Liste oder im Popupmenü OLE-Verben), tatsächlich ändern die Menüstruktur bevor das Menü gezeichnet wird.

Die gleiche Art von ON_UPDATE_COMMAND_UI Verarbeitung erfolgt für Symbolleisten (und anderen Steuerleisten) Wenn die Anwendung die Leerlaufschleife betritt. Finden Sie weitere Informationen zum Anpassen von Steuerleisten im Class Library Reference und technischer Hinweis 31.

Geschachtelte Popupmenüs

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

Zunächst wird es für das Popup selbst aufgerufen. Dies ist notwendig, da die Popup-Menüs haben keine IDs und die ID des ersten Menüelements des Popup verwenden wir das gesamte Popup auf. In diesem Fall die M_pSubMenu -Membervariable des Objekts CCmdUI wird ungleich NULL sein, und verweist auf Popup-Menü.

Zweitens heißt es, kurz bevor die Menüpunkte im Popup sind gezeichnet werden soll. In diesem Fall die ID bezieht sich nur auf das erste Menüelement und die M_pSubMenu -Membervariable des Objekts CCmdUI wird NULL sein.

Dies ermöglicht es Ihnen, aktivieren Sie das Popup-Menüelemente unterscheiden, aber erfordert, dass Sie bewusst im Menü Code schreiben. Zum Beispiel in einem verschachtelten Menü mit der folgenden Struktur:

Filegt;
    Neu >
        Blatt (ID_NEW_SHEET)
        Diagramm (ID_NEW_CHART)

Die Befehle ID_NEW_SHEET und ID_NEW_CHART können unabhängig voneinander aktiviert oder deaktiviert werden. Das Popup-Menü "Neu" sollte aktiviert werden, wenn eine der beiden aktiviert ist.

Der Command-Ereignishandler für die ID_NEW_SHEET (der erste Befehl in das Popup) würde wie aussehen:

privatevoid CMyApp::OnUpdateNewSheet (CCmdUI pCmdUI)
{
 Nbsp;  Wenn (pCmdUI - > M_pSubMenu! = NULL)
    {
        / / Aktivieren Sie gesamte Popup für "New" Tabellen- und Diagramm
        BOOL bAktivieren Sie = M_bCanCreateSheet || M_bCanCreateChart;

/ / CCmdUI::Enable ist keine Aktion für diesen Fall, so dass wir
        / / müssen tun, was es gemacht hätte.
        pCmdUI - > M_pMenu - > EnableMenuItem (pCmdUI - > M_nIndex,
            MF_BYPOSITION | 
                (bAktivieren Sie? MF_ENABLED: (MF_DISABLED | MF_GRAYED)));
        Rückkehr;
    }
    / / sonst nur den Befehl neues Blatt
    pCmdUI - > Enable(m_bCanCreateSheet);
}

Der Command-Ereignishandler für die ID_NEW_CHART wäre ein normales Update Befehlshandler und Aussehen so etwas wie:

privatevoid CMyApp::OnUpdateNewChart (CCmdUI pCmdUI)
{
 Nbsp;  pCmdUI - > Enable(m_bCanCreateChart);
}

ON_COMMAND und ON_BN_CLICKED

Die Meldung Karte Makros für ON_COMMAND und ON_BN_CLICKED sind identisch. Der MFC Führungs- und routing Benachrichtigungsmechanismus verwendet nur die Befehls-ID zu um entscheiden, wo an weiterleiten. Steuerelement-Benachrichtigungen mit Aviscode Kontrolle von NULL (BN_CLICKED) werden als Befehle interpretiert.

Erweiterte Hinweis: In der Tat alle Steuerelement-Benachrichtigungen durchlaufen die Befehlskette Handler. Daher ist es technisch möglich, für einen Steuerelement-Benachrichtigung-Handler für sagen EN_CHANGE-Ereignis in der Dokumentenklasse schreiben. Dies ist nicht im allgemeinen ratsam, da die praktische Anwendung dieser Funktion nur wenige gibt, die Funktion nicht von Klassen-Assistent unterstützt wird und Einsatz der Funktion kann fragile Code führen.

Deaktivieren der automatischen Sperrung des Button-Steuerelemente

Wenn Sie platzieren Sie ein Button-Steuerelement auf eine Dialogleiste oder in einem Dialogfeld mit wo Sie CWnd::UpdateDialogControls auf Ihren eigenen anrufen, werden Sie feststellen, dass Schaltflächen für ON_COMMAND oder ON_UPDATE_COMMAND_UI -Handler keinen vom Framework automatisch für Sie deaktiviert werden. In einigen Fällen müssen Sie nicht auf einen Handler zu haben, aber Sie sollten die Schaltfläche aktiviert bleibt. Der einfachste Weg, dies zu erreichen ist, fügen Sie einen dummy Befehlshandler (einfach mit ClassWizard zu tun) und nichts drin.

Fenster-Nachrichtenrouting

Im folgenden werden einige fortgeschrittenen Themen über die MFC-Klassen und wie Windows routing von Nachrichten und anderen Themen sie Auswirkungen auf. Hier wird nur kurz beschrieben. Finden Sie in der Class Library Reference Informationen über öffentliche APIs. Finden Sie in den MFC-Bibliothek Source Code für weitere Informationen über Einzelheiten der Implementierung.

Siehe technische Anmerkung 17 für Details beim Fenster Cleanup, ein sehr wichtiges Thema für alle CWnd-abgeleiteten Klassen.

CWnd Fragen

Die Umsetzung-Memberfunktion CWnd::OnChildNotify stellt eine leistungsstarke und erweiterbare Architektur für untergeordnete Fenster (auch bekannt als Steuerelemente) Haken oder anders Nachrichten, Befehle und Steuerelement-Benachrichtigungen, die an Eltern (oder "Besitzer") informiert werden. Wenn das untergeordnete Fenster (/ control) ist eine C++- CWnd Objekt selbst, die virtuelle Funktion OnChildNotify zuerst mit den Parametern aus der ursprünglichen Nachricht (d. h. ein MSG -Struktur aufgerufen). Das untergeordnete Fenster kann lassen die Nachricht allein, es essen oder die Nachricht für den übergeordneten (selten).

Die CWnd -Standardimplementierung behandelt die folgenden Nachrichten und verwendet den OnChildNotify Haken um zu ermöglichen, dass untergeordnete Fenster (Steuerelemente), erhalten zunächst die Meldung knacken:

Sie werden feststellen, dass der OnChildNotify Haken dient zum Ändern von Ownerdrawn-Nachrichten in self-draw Nachrichten.

Zusätzlich zu den Haken OnChildNotify haben Bildlaufmeldungen weitere Routingverhalten. Siehe unten für weitere Informationen über Bildlaufleisten und Quellen von WM_HSCROLL und WM_VSCROLL -Meldungen.

CFrameWnd Fragen

Die CFrameWnd -Klasse stellt die meisten Befehlsrouting und Benutzeroberfläche aktualisieren Umsetzung. Dies dient in erster Linie für das Hauptrahmenfenster der Anwendung (CWinApp::m_pMainWnd), sondern für alle Frame-Fenster.

Das Hauptrahmenfenster ist das Fenster über die Menüleiste und das übergeordnete Element der Statusleiste oder Nachricht Linie. Entnehmen Sie bitte der obigen Diskussion zum Befehlsrouting und WM_INITMENUPOPUP.

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

CMDIFrameWnd/CMDIChildWnd Fragen

Sowohl MDI Rahmenfensterklassen CFrameWnd abgeleitet und daher sowohl für die gleiche Art von Befehlsrouting und Benutzeroberflächen-Aktualisierung gemäß CFrameWndaktiviert sind. In einer typischen MDI-Anwendung nur das Hauptrahmenfenster (d. h. das Objekt CMDIFrameWnd ) hält die Menüleiste und die Statusleiste und daher ist die wichtigste Quelle der Befehl routing Umsetzung.

Im allgemeine routing System ist, dass das aktive untergeordnete MDI-Fenster ersten Sprung at-Befehle erhält. Die Standardfunktionen PreTranslateMessage behandeln Zugriffstastentabellen für beide untergeordnete MDI-Fenster (zuerst) und des MDI-Rahmenfensters (zweite) als auch die standard MDI-System-Befehl Beschleuniger normalerweise behandelt, indem TranslateMDISysAccel (letzte).

Bildlaufleiste Fragen

Beim Umgang mit Scroll-Nachricht (WM_HSCROLL/OnHScroll und/oder WM_VSCROLL/OnVScroll ), sollten Sie den Handlercode schreiben, damit es nicht angewiesen ist auf wo die Schriftrolle-Bar-Nachricht kam. Dies ist nicht nur ein allgemeines Windows Problem, da Bildlaufmeldungen aus wahre Bildlaufleiste Steuerelemente oder WS_HSCROLLkommen können /WS_VSCROLL Bildlaufleisten sind keine Bildlaufleisten-Steuerelemente.

MFC erweitert, ermöglichen die Bildlaufleisten-Steuerelemente entweder Kind oder Geschwister des Fensters wird ein Bildlauf durchgeführt (in der Tat, dass die Parent-Child-Beziehung zwischen der Bildlaufleiste und Fenster gescrollt wird alles sein kann). Dies ist besonders wichtig für freigegebene Bildlaufleisten mit Splitterfenster. Siehe technische Anmerkung 29 für Einzelheiten zur Implementierung von CSplitterWnd einschließlich weiterer Informationen zu freigegebenen Scroll Bar Fragen.

On a Side Note gibt es zwei CWnd abgeleitete Klassen wo am angegebenen Scroll Bar Stile erstellen gefangen sind und nicht an Windows übergeben. Wenn eine Erstellung Routine übergeben, WS_HSCROLL und WS_VSCROLL können unabhängig voneinander festgelegt werden, aber nach der Erstellung nicht geändert werden kann. Natürlich sollten Sie nicht direkt testen oder Festlegen der WS_?SCROLL Formatbits des Fensters, das sie erstellt.

Für CMDIFrameWnd sind die Scroll-Bar-Stile, die Sie in Erstellen oder LoadFrame übergeben verwendet, um das MDICLIENT erstellen. Wollen Sie einen bildlauffähigen Bereich MDICLIENT (wie dem Windows Programm-Manager) legen haben beide Stile Bildlaufleiste (WS_HSCROLL | WS_VSCROLL) für die Formatvorlage zur Erstellung der CMDIFrameWnd.

CSplitterWnd beantragen die Scroll-Bar-Stile den speziellen freigegebenen Bildlaufleisten für das Splitter-Regionen. Für statische Splitterfenster werden Sie normalerweise nicht entweder Scroll Bar-Stil festgelegt. Für dynamischen Teilfenstern müssen in der Regel Sie die Bildlaufleiste Formatvorlagensatz für die Richtung, die Sie geteilt werden, die d. h. WS_HSCROLL Wenn Sie Zeilen, WS_VSCROLL teilen können, wenn Sie Spalten aufteilen können.

Technische Hinweise von &Nummer |nbsp; Technische Hinweise nach Kategorie

Index