Udostępnij za pośrednictwem


TN062: odbicie komunikatu dla formantów systemu Windows

Uwaga

Następująca uwaga techniczna nie została zaktualizowana, ponieważ została po raz pierwszy uwzględniona w dokumentacji online. W związku z tym niektóre procedury i tematy mogą być nieaktualne lub nieprawidłowe. Aby uzyskać najnowsze informacje, zaleca się wyszukanie interesującego tematu w indeksie dokumentacji online.

Ta uwaga techniczna opisuje odbicie komunikatu, nową funkcję w MFC 4.0. Zawiera również wskazówki dotyczące tworzenia prostej kontrolki wielokrotnego użytku, która używa odbicia komunikatu.

Ta uwaga techniczna nie omawia odbicia komunikatu, ponieważ dotyczy kontrolek ActiveX (dawniej nazywanych kontrolkami OLE). Zobacz artykuł Kontrolki ActiveX: podklasowanie kontrolki systemu Windows.

Co to jest Emocje wiadomości

Kontrolki systemu Windows często wysyłają komunikaty powiadomień do okien nadrzędnych. Na przykład wiele kontrolek wysyła komunikat powiadomienia o kolorze kontrolki (WM_CTLCOLOR lub jeden z jego wariantów) do elementu nadrzędnego, aby umożliwić rodzicowi podanie pędzla do malowania tła kontrolki.

W systemie Windows i w MFC przed wersją 4.0 okno nadrzędne, często okno dialogowe, jest odpowiedzialne za obsługę tych komunikatów. Oznacza to, że kod do obsługi komunikatu musi znajdować się w klasie okna nadrzędnego i musi być zduplikowany w każdej klasie, która musi obsługiwać ten komunikat. W powyższym przypadku każde okno dialogowe, które chciało kontrolować z niestandardowymi tłami, musi obsługiwać komunikat powiadomienia o kolorze kontrolki. Byłoby znacznie łatwiej użyć kodu, jeśli można napisać klasę sterowania, która będzie obsługiwać własny kolor tła.

W MFC 4.0 stary mechanizm nadal działa — okna nadrzędne mogą obsługiwać komunikaty powiadomień. Ponadto, MFC 4.0 ułatwia ponowne użycie, zapewniając funkcję o nazwie "odbicie komunikatów", która umożliwia obsługę tych komunikatów powiadomień w oknie sterowania podrzędnego lub w oknie nadrzędnym, albo w obu. W przykładzie koloru tła kontrolki można teraz napisać klasę kontrolki, która ustawia własny kolor tła, obsługując odbity komunikat WM_CTLCOLOR — wszystko bez polegania na obiekcie nadrzędnym. (Należy pamiętać, że ponieważ odbicie komunikatu jest implementowane przez MFC, a nie przez system Windows, klasa okna nadrzędnego musi pochodzić od CWnd elementu , aby odbicie komunikatu działało).

Starsze wersje MFC działały podobnie do odbicia komunikatów, udostępniając funkcje wirtualne dla kilku komunikatów, takich jak wiadomości dla pól listy narysowanych przez właściciela (WM_DRAWITEM itd.). Nowy mechanizm odbicia komunikatów jest uogólniony i spójny.

Odbicie komunikatu jest zgodne z poprzednim kodem napisanym dla wersji MFC przed 4.0.

Jeśli podano procedurę obsługi dla określonego komunikatu lub dla zakresu komunikatów, w klasie okna nadrzędnego zastąpi on programy obsługi komunikatów odzwierciedlane dla tego samego komunikatu, pod warunkiem, że nie wywołasz funkcji obsługi klas bazowych we własnej procedurze obsługi. Jeśli na przykład obsłużysz WM_CTLCOLOR w klasie okna dialogowego, obsługa zastąpi wszystkie programy obsługi komunikatów, które zostały odzwierciedlone.

Jeśli w klasie okna nadrzędnego należy podać procedurę obsługi dla określonego komunikatu WM_NOTIFY lub zakresu komunikatów WM_NOTIFY, program obsługi będzie wywoływany tylko wtedy, gdy kontrolka podrzędna wysyłająca te komunikaty nie ma programu obsługi komunikatów odzwierciedlonych za pomocą metody ON_NOTIFY_REFLECT(). Jeśli używasz ON_NOTIFY_REFLECT_EX() na mapie komunikatów, program obsługi komunikatów może lub nie zezwala okno nadrzędne na obsługę komunikatu. Jeśli program obsługi zwróci wartość FALSE, komunikat zostanie również obsłużony przez element nadrzędny, podczas gdy wywołanie zwracające wartość TRUE nie zezwala na obsługę elementu nadrzędnego. Należy pamiętać, że odzwierciedlona wiadomość jest obsługiwana przed komunikatem powiadomienia.

Po wysłaniu komunikatu WM_NOTIFY kontrolka jest oferowana jako pierwsza szansa na jego obsługę. Jeśli zostanie wysłany jakikolwiek inny odzwierciedlony komunikat, okno nadrzędne ma pierwszą szansę na jego obsługę, a kontrolka otrzyma odzwierciedlona wiadomość. W tym celu będzie ona potrzebować funkcji obsługi i odpowiedniego wpisu na mapie komunikatów klasy kontrolki.

Makro mapy komunikatów dla komunikatów odzwierciedlanych komunikatów jest nieco inne niż w przypadku zwykłych powiadomień: _REFLECT dołączony do swojej zwykłej nazwy. Na przykład w celu obsługi komunikatu WM_NOTIFY w elemecie nadrzędnym należy użyć ON_NOTIFY makra na mapie komunikatów nadrzędnych. Aby obsłużyć odbity komunikat w kontrolce podrzędnej, użyj makra ON_NOTIFY_REFLECT na mapie komunikatów kontrolki podrzędnej. W niektórych przypadkach parametry są różne. Należy pamiętać, że klasa ClassWizard zwykle może dodawać wpisy mapy komunikatów i dostarczać szkieletowe implementacje funkcji z poprawnymi parametrami.

Zobacz TN061: komunikaty ON_NOTIFY i WM_NOTIFY , aby uzyskać informacje na temat nowego komunikatu WM_NOTIFY.

Wpisy mapy komunikatów i prototypy funkcji obsługi dla komunikatów Emocje

Aby obsłużyć odzwierciedlone powiadomienie o kontrolce, użyj makr mapy komunikatów i prototypów funkcji wymienionych w poniższej tabeli.

KlasaWizard może zwykle dodawać te wpisy mapy komunikatów i udostępniać szkieletowe implementacje funkcji. Zobacz Definiowanie programu obsługi komunikatów dla komunikatu Emocje ed, aby uzyskać informacje o sposobie definiowania programów obsługi dla komunikatów odzwierciedlonych.

Aby przekonwertować z nazwy komunikatu na nazwę odzwierciedlonego makra, wstępnie ON_ i dołącz _REFLECT. Na przykład WM_CTLCOLOR staje się ON_WM_CTLCOLOR_REFLECT. (Aby zobaczyć, które komunikaty można odzwierciedlić, wykonaj odwrotną konwersję na wpisy makr w poniższej tabeli).

Trzy wyjątki od powyższej reguły są następujące:

  • Makro dla powiadomień WM_COMMAND jest ON_CONTROL_REFLECT.

  • Makro dla odbicia WM_NOTIFY jest ON_NOTIFY_REFLECT.

  • Makro dla odbicia ON_UPDATE_COMMAND_UI jest ON_UPDATE_COMMAND_UI_REFLECT.

W każdym z powyższych przypadków specjalnych należy określić nazwę funkcji składowej programu obsługi. W innych przypadkach należy użyć standardowej nazwy funkcji obsługi.

Znaczenie parametrów i zwracanych wartości funkcji są udokumentowane pod nazwą funkcji lub nazwą funkcji z prepended. Na przykład CtlColor dokument jest udokumentowany w pliku OnCtlColor. Kilka programów obsługi komunikatów odzwierciedlanych wymaga mniejszej liczby parametrów niż podobne programy obsługi w oknie nadrzędnym. Wystarczy dopasować nazwy w poniższej tabeli z nazwami parametrów formalnych w dokumentacji.

Wpis mapy Prototyp funkcji
ON_CONTROL_REFLECT(wNotifyCode,)memberFxn afx_msg voidmemberFxn( );
ON_NOTIFY_REFLECT(wNotifyCode,)memberFxn afx_msg voidmemberFxn( NMHDRpNotifyStruct*, wynik LRESULT);*
ON_UPDATE_COMMAND_UI_REFLECT(memberFxn) afx_msg voidmemberFxn( CCmdUI);*pCmdUI
ON_WM_CTLCOLOR_REFLECT( ) afx_msg HBRUSH CtlColor (CDCpDC*, UINT);nCtlColor
ON_WM_DRAWITEM_REFLECT( ) afx_msg void DrawItem ( LPDRAWITEMSTRUCTlpDrawItemStruct);
ON_WM_MEASUREITEM_REFLECT( ) afx_msg void MeasureItem ( LPMEASUREITEMSTRUCTlpMeasureItemStruct);
ON_WM_DELETEITEM_REFLECT( ) afx_msg void DeleteItem ( LPDELETEITEMSTRUCTlpDeleteItemStruct);
ON_WM_COMPAREITEM_REFLECT( ) afx_msg int CompareItem ( LPCOMPAREITEMSTRUCTlpCompareItemStruct);
ON_WM_CHARTOITEM_REFLECT( ) afx_msg int CharToItem ( UINTnKey, UINT);nIndex
ON_WM_VKEYTOITEM_REFLECT( ) afx_msg int VKeyToItem (UINTnKey, UINT);nIndex
ON_WM_HSCROLL_REFLECT( ) afx_msg void HScroll (UINTnSBCode, UINT);nPos
ON_WM_VSCROLL_REFLECT( ) afx_msg void VScroll (UINTnSBCode, UINT);nPos
ON_WM_PARENTNOTIFY_REFLECT( ) afx_msg void ParentNotify ( UINTmessage, LPARAM);lParam

Makra ON_NOTIFY_REFLECT i ON_CONTROL_REFLECT mają odmiany, które zezwalają na obsługę danego komunikatu przez więcej niż jeden obiekt (taki jak kontrolka i jej element nadrzędny).

Wpis mapy Prototyp funkcji
ON_NOTIFY_REFLECT_EX(wNotifyCode,)memberFxn afx_msg BOOLmemberFxn( NMHDR*pNotifyStruct, wynik LRESULT);*
ON_CONTROL_REFLECT_EX(wNotifyCode,)memberFxn afx_msg BOOLmemberFxn( );

Obsługa komunikatów Emocje: przykład kontrolki wielokrotnego użytku

Ten prosty przykład tworzy kontrolkę wielokrotnego użytku o nazwie CYellowEdit. Kontrolka działa tak samo jak zwykła kontrolka edycji, z tą różnicą, że wyświetla czarny tekst na żółtym tle. Łatwo byłoby dodać funkcje składowe, które umożliwiłyby kontrolce CYellowEdit wyświetlanie różnych kolorów.

Aby wypróbować przykład, który tworzy kontrolkę wielokrotnego użytku

  1. Utwórz nowe okno dialogowe w istniejącej aplikacji. Aby uzyskać więcej informacji, zobacz temat edytora okien dialogowych.

    Musisz mieć aplikację, w której ma zostać utworzona kontrolka wielokrotnego użytku. Jeśli nie masz istniejącej aplikacji do użycia, utwórz aplikację opartą na oknie dialogowym przy użyciu aplikacji AppWizard.

  2. Gdy projekt został załadowany do języka Visual C++, użyj klasy ClassWizard, aby utworzyć nową klasę o nazwie CYellowEdit na CEditpodstawie .

  3. Dodaj trzy zmienne składowe do CYellowEdit klasy. Pierwsze dwa będą zmiennymi COLORREF do przechowywania koloru tekstu i koloru tła. Trzeci będzie obiektem CBrush , który będzie trzymać szczotkę do malowania tła. Obiekt CBrush umożliwia jednokrotne utworzenie pędzla, jedynie odwoływanie się do niego po tym i automatyczne zniszczenie pędzla po zniszczeniu kontrolki CYellowEdit .

  4. Zainicjuj zmienne składowe, zapisując konstruktor w następujący sposób:

    CYellowEdit::CYellowEdit()
    {
        m_clrText = RGB(0, 0, 0);
        m_clrBkgnd = RGB(255, 255, 0);
        m_brBkgnd.CreateSolidBrush(m_clrBkgnd);
    }
    
  5. Za pomocą klasy ClassWizard dodaj procedurę obsługi dla odzwierciedlonego komunikatu WM_CTLCOLOR do CYellowEdit klasy. Pamiętaj, że znak równości przed nazwą wiadomości na liście komunikatów, które można obsłużyć, wskazuje, że komunikat jest odzwierciedlony. Opisano to w temacie Definiowanie programu obsługi komunikatów dla Emocje komunikatu.

    KlasaWizard dodaje następujące makro mapy komunikatów i funkcję szkieletu:

    ON_WM_CTLCOLOR_REFLECT()
    // Note: other code will be in between....
    
    HBRUSH CYellowEdit::CtlColor(CDC* pDC, UINT nCtlColor)
    {
        // TODO: Change any attributes of the DC here
        // TODO: Return a non-NULL brush if the
        //       parent's handler should not be called
        return NULL;
    }
    
  6. Zastąp treść funkcji następującym kodem. Kod określa kolor tekstu, kolor tła tekstu i kolor tła pozostałej części kontrolki.

    pDC->SetTextColor(m_clrText);   // text
    pDC->SetBkColor(m_clrBkgnd);    // text bkgnd
    return m_brBkgnd;               // ctl bkgnd
    
  7. Utwórz kontrolkę edycji w oknie dialogowym, a następnie dołącz ją do zmiennej składowej, klikając dwukrotnie kontrolkę edycji przy zachowaniu klawisza sterowania w dół. W oknie dialogowym Dodawanie zmiennej składowej zakończ nazwę zmiennej i wybierz pozycję "Kontrolka" dla kategorii, a następnie "CYellowEdit" dla typu zmiennej. Nie zapomnij ustawić kolejności tabulacji w oknie dialogowym. Ponadto należy uwzględnić plik nagłówka kontrolki CYellowEdit w pliku nagłówkowym okna dialogowego.

  8. Skompiluj i uruchom aplikację. Kontrolka edycji będzie mieć żółte tło.

Zobacz też

Uwagi techniczne według numerów
Uwagi techniczne według kategorii