TN021: routing poleceń i komunikatów
[!UWAGA]
Następująca uwaga techniczna nie został zaktualizowana od pierwszego uwzględnienia jej w dokumentacji online.W rezultacie niektóre procedury i tematy może być nieaktualne lub nieprawidłowe.Aby uzyskać najnowsze informacje, zaleca się wyszukać temat w indeksie dokumentacji online.
Uwaga ta opisuje polecenia routingu i wysyłki architektury, jak również Tematy zaawansowane przy rozsyłaniu wiadomości Ogólne okna.
Zajrzyj do Visual C++ ogólnych informacji na temat architektury opisanych tutaj, zwłaszcza rozróżnienie między wiadomości, powiadomienia kontroli i poleceń systemu Windows.Uwaga ta zakłada, doskonale znają problemy opisane w dokumentacji drukowanej i odnosi się jedynie bardzo zaawansowane zagadnienia.
Rozwija funkcjonalność polecenia routingu i wysyłki MFC 1.0 do MFC 2.0 architektury
System Windows ma WM_COMMAND komunikat jest przeciążony zapewnienie powiadomienia poleceń menu, klawisze skrótu i sterowania okno dialogowe powiadomienia.
MFC 1.0 zbudowany na tym trochę poprzez umożliwienie obsługi polecenia (na przykład "OnFileNew") w CWnd klasy sprawdzeni w odpowiedzi z określonym WM_COMMAND.Sklejone jest strukturą danych, nazywany mapą wiadomość i powoduje mechanizm bardzo efektywnym polecenia.
MFC 1.0 zapewnia dodatkowe funkcje do oddzielania powiadomienia kontroli z wiadomości polecenia.Polecenia są reprezentowane przez identyfikator 16-bitowe, czasami znany jako nazwę polecenia.Poleceń rozpoczyna się zwykle od CFrameWnd (czyli menu wybierz lub przetłumaczonych accelerator) i uzyskać kierowane do szeregu innych okien.
MFC 1.0 używane polecenia routingu w sensie ograniczone do wykonania z Multiple Document Interface (MDI). (Okna MDI ramki delegować poleceń do jego aktywne okno potomne MDI).
Ta funkcjonalność została uogólnione i rozszerzone w MFC 2.0, aby umożliwić poleceń obsługiwanych przez szerszego zakresu obiekty (nie tylko okno).Zapewnia bardziej formalnych i rozszerzalną architekturę routingu wiadomości i ponownie używa polecenia docelowej routingu, nie tylko obsługi poleceń, ale także dla aktualizacji obiektów interfejsu użytkownika (np. elementy menu i przycisków na pasku narzędzi) w celu uwzględnienia dostępności bieżącego polecenia.
Identyfikatory poleceń
Zobacz Visual C++ wyjaśnienie polecenia routingu i proces wiązania.Techniczne 20 Uwaga zawiera informacje na temat nazw identyfikator.
Identyfikatory poleceń używamy rodzajowy prefiksu "ID_".Identyfikatory poleceń są >= 0x8000.Linii lub stan paska komunikatów pokaże polecenia ciąg opisu, jeśli istnieje zasób STRINGTABLE z identyfikatorami sam jak identyfikator polecenia.
Zasoby aplikacji polecenie, które można identyfikator pojawia się w kilku miejscach:
W jednym STRINGTABLE zasób, który ma taki sam identyfikator jak wiersz wiersz wiadomości.
W ewentualnie wiele MENU zasobów, które są dołączone do elementów menu, które wywołują te same polecenia.
(Zaawansowane) w przycisk okna dialogowego polecenia GOSUB.
W kodzie źródłowym aplikacji polecenie, które można identyfikator pojawia się w kilku miejscach:
W swoim ZASOBIE.H (lub innych głównych symbol nagłówka pliku) do definiowania identyfikatorów poleceń specyficznych dla aplikacji.
Być może w tablicy identyfikator używany do tworzenia paska narzędzi.
W ON_COMMAND makro.
Być może w ON_UPDATE_COMMAND_UI makro.
Obecnie można tylko wykonania w MFC, która wymaga identyfikatory poleceń >= 0x8000 jest implementacją GOSUB okien dialogowych/commands.
GOSUB polecenia, za pomocą polecenia architektury w oknach dialogowych
Architektura polecenia routingu i włączenie polecenia działa dobrze z ramka okna, elementów menu, przyciski paska narzędzi, przyciski paska okno, pozostałych pasków kontroli i inne elementy interfejsu użytkownika, przeznaczone do aktualizacji na żądanie i trasę polecenia lub Sterowanie identyfikatorów do obiektu docelowego głównego polecenia (zwykle w oknie ramkę główną).Główne polecenia obiektu docelowego może rozesłać powiadomienia polecenia lub formantu do innych obiektów docelowych polecenia odpowiednio.
Okno dialogowe (formularz modalny lub niemodalny) mogą korzystać z niektórych funkcji architektury polecenia, jeśli identyfikator formantu formant okna dialogowego zostanie przypisany do identyfikatora odpowiednie polecenie.Wsparcie dla okien dialogowych nie jest automatyczne, więc musisz do pisania dodatkowego kodu.
Należy zauważyć, że wszystkie te funkcje działały poprawnie swoje identyfikatory poleceń należy >= 0x8000.Ponieważ wiele okien dialogowych można uzyskać kierowane do tej samej ramce, powinny być udostępnione poleceń >= 0x8000, podczas gdy powinna być udostępniana IDCs w określonego okna dialogowego <= 0x7FFF.
Normalny przycisk można umieścić w normalnym modalne okno dialogowe z IDC przycisku Ustaw identyfikator odpowiednie polecenie.Po wybraniu przycisku przez użytkownika, właściciel okno (zwykle okno ramkę główną) pobiera polecenia, podobnie jak inne polecenie.Jest to polecenie GOSUB, ponieważ zwykle jest używany aby przywołać kolejne okno (GOSUB pierwsze okno dialogowe)
Można również wywołać funkcję CWnd::UpdateDialogControls na dialogu i przekazywanie ich adres okna ramkę główną.Ta funkcja włącza lub wyłącza okno formanty oparte na czy mają one polecenia obsługi w ramce.Ta funkcja jest wywoływana automatycznie dla Ciebie pasków kontroli w pętlę bezczynności aplikacji, ale należy go wywołać bezpośrednio dla normalnego okna dialogowe, które chcą mieć tę funkcję.
Gdy ON_UPDATE_COMMAND_UI jest wywoływana
Utrzymywanie cały czas włączony sprawdzany stan elementu menu wszystkie programy mogą być kosztowne obliczeniowo problem.Popularna technika stosowana jest enable/wyboru elementów menu tylko wtedy, gdy użytkownik wybierze opcję menu PODRĘCZNEGO.Wykonania MFC 2.0 CFrameWnd uchwyty WM_INITMENUPOPUP wiadomość i używa polecenia architekturę routingu w celu określenia stanów menu za pomocą ON_UPDATE_COMMAND_UI obsługi.
CFrameWnd obsługuje również WM_ENTERIDLE komunikat opisujący zaznaczonej pozycji na pasku (znany również jako wiersz wiadomości) stanu bieżącego menu.
Struktura menu aplikacji, edytowany w programie Visual C++, jest używana do reprezentowania potencjalnych poleceń dostępnych w WM_INITMENUPOPUP czasu.ON_UPDATE_COMMAND_UI programy obsługi można zmodyfikować stan lub tekst menu lub do zaawansowanych zastosowań (np. listy ostatnio używanych plików, menu podręcznego zleceń OLE), rzeczywiście modyfikować struktury menu przed menu jest rysowany.
Taki sam rodzaj ON_UPDATE_COMMAND_UI przetwarzanie odbywa się na paski narzędzi (i inne paski sterowania) po przejściu jego pętlę bezczynności aplikacji.Zobacz Informacje dotyczące biblioteki klas i technicznej 31 Uwaga uzyskać więcej informacji dotyczących sterowania paski.
Zagnieżdżone wyskakujących menu
Jeśli używasz struktury zagnieżdżone menu, można zauważyć, że ON_UPDATE_COMMAND_UI w dwóch różnych przypadków nazywa się obsługi dla pierwszego elementu menu w menu podręcznym.
Po pierwsze nazywany jest wyskakujące menu, sam.Jest to konieczne, ponieważ wyskakujących menu nie mają identyfikatorów i używamy identyfikator pierwszego elementu menu wyskakującego menu odnoszą się do całego menu wyskakującego.W tym przypadku m_pSubMenu zmienną z CCmdUI obiekt będzie NIEZEROWE i wskaże z wyskakującego menu.
Po drugie nazywa się tuż przed elementów menu wyskakującego menu mają być tworzone.W tym przypadku identyfikator odnosi się tylko do pierwszego elementu menu i m_pSubMenu zmienną z CCmdUI obiekt będzie mieć wartość NULL.
Umożliwia włączenie odmienne od jego elementów menu wyskakującego menu, ale wymaga to napisać kod świadomość niektórych menu.Na przykład w zagnieżdżonych menu o następującej strukturze:
File>
New>
Sheet (ID_NEW_SHEET)
Chart (ID_NEW_CHART)
Polecenia ID_NEW_SHEET i ID_NEW_CHART może być niezależnie włączona lub wyłączona.Nowy wyskakującego menu powinien być włączony, jeśli jeden z dwóch jest włączony.
Program obsługi poleceń dla ID_NEW_SHEET (pierwsze polecenie w podręcznym) będzie wyglądało mniej więcej tak:
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);
}
Program obsługi poleceń dla ID_NEW_CHART będzie program obsługi poleceń aktualizacji i wyglądało:
void CMyApp::OnUpdateNewChart(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_bCanCreateChart);
}
ON_COMMAND i ON_BN_CLICKED
Makra mapę wiadomości dla ON_COMMAND i ON_BN_CLICKED są takie same.MFC dowodzenia i kontroli mechanizm rozsyłania powiadomień używa tylko identyfikator polecenia podjąć decyzję, gdzie do kierowania do.Kontrolować powiadomienia z formantu kodu powiadomienia zero (BN_CLICKED) są interpretowane jako polecenia.
[!UWAGA]
W rzeczywistości wszystkie wiadomości powiadomień kontroli przejść przez łańcuch polecenia obsługi.Na przykład, jest technicznie możliwe do pisania obsługi powiadomień sterowania EN_CHANGE w klasie dokumentu.To nie jest ogólnie wskazane ponieważ praktycznych zastosowań tej funkcji jest kilka, funkcja nie jest obsługiwana przez ClassWizard i użycie funkcji może spowodować delikatny kod.
Wyłączanie automatycznego wyłączania formantów przycisku
Jeśli umieścić formant przycisku na pasku okno lub w oknie dialogowym, używając w miarę wywoływania CWnd::UpdateDialogControls na własną rękę, zauważysz, że przyciski, które nie mają ON_COMMAND lub ON_UPDATE_COMMAND_UI obsługi jest automatycznie wyłączane automatycznie w ramach.W niektórych przypadkach nie trzeba będzie mieć program obsługi, ale możesz przycisk pozostaną włączone.Najprostszym sposobem osiągnięcia tego jest dodanie obsługi polecenia manekina (łatwe do czynienia z ClassWizard) i nie robić nic w nim.
Routowanie wiadomości okno
Poniżej opisano kilka bardziej zaawansowanych tematów na klasy MFC i jak przesyłanie wiadomości systemu Windows oraz innych tematów wpływu ich.Krótko opisane jest tylko informacje tutaj.Odnoszą się do Informacje dotyczące biblioteki klas szczegółowe informacje na temat publicznych interfejsów API.Sprawdź kod źródłowy biblioteki MFC, aby uzyskać więcej informacji dotyczących szczegółów implementacji.
Można znaleźć w technicznej 17 Uwaga dla szczegółów na okno Oczyszczanie, temat bardzo ważne dla wszystkich CWnd-klasy pochodne.
CWnd problemów
Wdrożenie funkcji składowej CWnd::OnChildNotify zapewnia wydajne i rozszerzalnej architekturze dziecka do systemu Windows (znane również jako formanty) hak lub inny sposób informowany o wiadomości, poleceń i powiadomienia kontroli, które go do ich nadrzędnego (lub "właściciel").Jeśli okno podrzędne (/ kontrola) C++ jest CWnd obiektu, funkcji wirtualnych OnChildNotify jest wywoływana po raz pierwszy z parametrów z oryginalnej wiadomości (czyli MSG struktury).Okno podrzędne można zostawić w spokoju wiadomości, jeść lub modyfikować wiadomości dla nadrzędnego (rzadko).
Domyślnie CWnd wykonania obsługuje następujące komunikaty i korzysta z OnChildNotify hak Aby dziecko system windows (formantów) pierwszego dostępu do wiadomości:
WM_MEASUREITEM i WM_DRAWITEM (własny narysuj)
WM_COMPAREITEM i WM_DELETEITEM (własny narysuj)
WM_HSCROLL i WM_VSCROLL
WM_CTLCOLOR
WM_PARENTNOTIFY
Można zauważyć, OnChildNotify hak służy do zmieniania wiadomości rysowania przez właściciela do wiadomości samodzielnie rysować.
W uzupełnieniu do OnChildNotify hak, przewijania wiadomości mają go dalej przesyłać zachowanie.Zobacz poniżej więcej informacji na temat pasków przewijania i źródeł WM_HSCROLL i WM_VSCROLL wiadomości.
CFrameWnd problemów
CFrameWnd klasa zawiera większość polecenia routingu i interfejs użytkownika wdrożenia aktualizacji.To służy przede wszystkim do okna ramce głównej aplikacji (CWinApp::m_pMainWnd), ale stosuje się do wszystkich okien ramek.
Okno główne ramek jest okno z paskiem menu i jest elementem nadrzędnym na pasku stanu lub wiadomości linii.Zajrzyj do dyskusji na polecenie routing i WM_INITMENUPOPUP.
CFrameWnd klasy zapewnia zarządzanie aktywnego widoku.Następujące wiadomości są routowane przez widok aktywny:
Wszystkie komunikaty polecenia (aktywny widok pobiera pierwszy dostęp do nich).
WM_HSCROLL i WM_VSCROLL wiadomości od tego samego poziomu przewiń paski (patrz poniżej).
WM_ACTIVATE (i WM_MDIACTIVATE dla MDI) uzyskać zamienił wywołań funkcji wirtualnych CView::OnActivateView.
Problemy z CMDIFrameWnd/CMDIChildWnd
Obie klasy okna ramki MDI pochodzić od CFrameWnd i dlatego są oba włączone dla tego samego rodzaju polecenia routingu i aktualizowanie interfejsu użytkownika w CFrameWnd.W typowych aplikacji MDI, tylko w oknie głównym ramki (czyli CMDIFrameWnd obiektu) posiada pasek menu i pasek stanu, a zatem jest głównym źródłem routingu wykonania polecenia.
Ogólny schemat routingu jest, że aktywnego okna podrzędnego MDI staje się pierwszym dostęp do poleceń.Domyślnie PreTranslateMessage funkcje obsługi tabel akcelerator dla obu okien podrzędnych MDI (na początku) i ramki MDI (drugi), jak również standardowe akceleratory polecenia systemu MDI obsługiwanych przez TranslateMDISysAccel (ostatni).
Problemy pasek przewijania
Podczas obsługi komunikatu przewijania (WM_HSCROLL/OnHScroll i/lub WM_VSCROLL/OnVScroll), staraj się pisać kod obsługi, więc nie opiera się na którym pochodzi od danego nadawcy paska przewijania.To nie tylko Windows kwestii ogólnych, ponieważ przewijania wiadomości mogą pochodzić z true scroll bar formantów lub z WS_HSCROLL/WS_VSCROLL , które nie są formanty paska przewijania paski przewijania.
MFC rozciąga się, aby umożliwić dla formantów paska przewijania za dziecko lub elementy równoważne są przewijane okna (w rzeczywistości relacji nadrzędny/podrzędny między pasek przewijania i okna są przewijane może być cokolwiek).Jest to szczególnie ważne dla pasków przewijania udostępnionego z rozdzielacza windows.Można znaleźć w technicznej 29 Uwaga szczegółowe informacje na temat realizacji CSplitterWnd tym więcej informacji na temat udostępnionych problemy paska przewijania.
Na stronie notatki, istnieją dwa CWnd klas pochodnych, gdzie style pasków przewijania określone na tworzenie czasu są stosowane nadlewki i podlewki i nie są przekazywane do systemu Windows.Gdy dane są przekazywane do procedury tworzenia, WS_HSCROLL i WS_VSCROLL można samodzielnie ustawić, ale po utworzenia nie można zmienić.Oczywiście nie bezpośrednio należy przetestować lub ustawić WS_?Bity styl PRZEWIJANIA okna, które sami utworzyli.
Dla CMDIFrameWnd style pasków przewijania można przekazać do Create lub LoadFrame są używane do tworzenia MDICLIENT.Jeśli chcesz mieć przewijalne obszar MDICLIENT (takich jak Menedżer systemu Windows Program) należy ustawić przewijać oba style pasków (WS_HSCROLL | WS_VSCROLL) dla stylu używane do tworzenia CMDIFrameWnd.
Dla CSplitterWnd style pasków przewijania dotyczą pasków przewijania udostępnionego specjalne dla regionów rozdzielacza.Dla windows rozdzielacza statycznego zwykle nie zostanie ustawiona albo styl paska przewijania.Dla windows splitter dynamiczne, zwykle mają pasek zestaw stylów dla kierunku podzieli, to znaczy przewijania WS_HSCROLL Jeśli można dzielić wierszy, WS_VSCROLL jeżeli można podzielić kolumny.