共用方式為


TN062: 訊息反映的 Windows 控制項

注意事項注意事項

由於它第一次線上文件中包含尚未更新下列技術提示。如此一來,某些程序和主題可能已經過期或不正確。如需最新資訊,建議您先搜尋線上文件索引中有興趣的主題。

這份技術提示說明訊息反映,MFC 4.0 中的新功能。 它也包含如何建立簡單的可重複使用控制項訊息反映會使用。

這份技術提示不討論訊息反映,因為這適用於 ActiveX (以前稱為 OLE 控制項) 的控制項。 請參閱文件 ActiveX 控制項: 子類別化 Windows 控制項

訊息反映是什麼?

Windows 控制項經常會將通知訊息傳送給它們的父視窗。 舉個例說,許多控制項傳送控制色彩通知訊息 (WM_CTLCOLOR或變種的其中一個) 能夠提供繪製控制項的背景的筆刷的父代其父系。

在 Windows 和 MFC 4.0 版之前,父視窗,通常一個對話方塊,負責處理這些訊息。 這表示處理郵件的程式碼必須以父視窗的類別,且其為每一個類別都需要處理該訊息內的重複。 在上面的例子中,每一個想要自訂背景與控制項的對話方塊必須處理這些控制項的色彩通知訊息。 所以您可以更容易重複使用程式碼,如果要寫入的控制項類別,就需要處理其本身的背景色彩。

MFC 4.0 中舊的機制仍能運作,父視窗能夠處理告知訊息。 此外,不過,MFC 4.0 可重複使用藉由提供一種稱為 「 訊息反映 」 功能,可讓這些告知訊息來處理在子控制項的視窗、 父視窗,或兩者。 在控制項背景色彩範例中,現在您可以撰寫的控制項類別藉由處理反映會設定自己的背景色彩的WM_CTLCOLOR訊息 — 完全不需依賴父代。 (請注意因為 mfc 實作訊息反映時,無法由 Windows 中,父視窗類別必須衍生自CWnd的訊息反映處理。)

較舊版本的 MFC 並沒有方法是提供幾個訊息,例如主控描繪清單方塊的訊息中的虛擬函式的類似訊息反映 (WM_DRAWITEM,依此類推)。 通用和一致,就會是新的訊息反映機制。

訊息反映是回溯相容的程式碼版本的 MFC 4.0 之前使用。

如果您所提供的處理常式的某一封郵件,或某個範圍內的父視窗的類別中的郵件,就會覆寫反映訊息處理常式相同的訊息,前提是在未呼叫基底類別處理常式函式,在您自己的處理常式。 比方說,如果您處理WM_CTLCOLOR在對話方塊類別,您的處理將會覆寫任何反映的訊息處理常式。

如果在父視窗類別中,您將常式提供給特定的 WM_NOTIFY 訊息或某個範圍的 WM_NOTIFY 才傳送這些郵件的子控制項並沒有透過反映的訊息處理常式,您的處理常式將呼叫的訊息, ON_NOTIFY_REFLECT()。 如果您使用 ON_NOTIFY_REFLECT_EX() 在您的訊息對應,您的訊息處理常式可能,否則將不允許的父視窗,若要處理的訊息。 如果這個處理常式會傳回 ,則為 FALSE,它的父系,傳回的呼叫時處理訊息 ,則為 TRUE 不允許來處理它的父代。 請注意處理反映的訊息的通知訊息之前。

WM_NOTIFY 訊息會傳送,該控制項所提供的第一個機會來處理它。 如果任何其他的反映的訊息傳送時,第一個父視窗都能處理,和控制項就會收到反映的訊息。 若要執行這項操作,就需要處理函式,並在控制項的類別訊息對應中的適當項目。

反映訊息的訊息對應巨集是與一般通知稍有不同: 它有 _REFLECT 附加至其一般名稱。 舉個例說,來處理 WM_NOTIFY 訊息中的父項目,您可以使用巨集ON_NOTIFY在父項的訊息對應中。 若要處理子控制項中的反映的訊息,請使用 ON_NOTIFY_REFLECT 中子控制項的訊息對應巨集。 在某些情況下,參數會改變,也。 請注意類別精靈的通常為您新增的訊息對應項目,可以提供正確的參數使用的基本架構函式實作。

請參閱 TN061: ON_NOTIFY 和 WM_NOTIFY 訊息 如有關新 WM_NOTIFY 訊息。

訊息對應項目,並反映訊息的處理常式函式原型

若要處理反映的控制項告知訊息,請使用訊息對應巨集,如下表所述的函式原型。

類別精靈通常可以為您新增這些訊息對應項目,並提供基本架構函式實作。 請參閱定義反映訊息的訊息處理常式如需如何定義反映訊息處理常式。

若要將訊息名稱轉換為反映巨集名稱,請在前面加上 ON_ 與附加 _REFLECT。 例如, WM_CTLCOLOR變成 ON_WM_CTLCOLOR_REFLECT。 (若要查看哪些訊息可以反映,待辦事項相反的轉換,如下表中的巨集項目上)。

以下是上述規則的三個例外:

  • 巨集, WM_COMMAND 通知是 ON_CONTROL_REFLECT

  • 巨集, WM_NOTIFY 倒影是 ON_NOTIFY_REFLECT

  • 巨集, ON_UPDATE_COMMAND_UI倒影是 ON_UPDATE_COMMAND_UI_REFLECT

在上述的特殊案例中,您必須指定處理常式成員函式的名稱。 在其他情況下,您必須使用您的處理常式函式的標準名稱。

參數的意義和函式的傳回值會記載在函式名稱或函式名稱與並於前端。 舉個例說, CtlColor 中會說明OnCtlColor。 數個反映的訊息處理常式需要較少的參數比類似的處理常式,在父視窗中。 只要符合下表中的名稱與文件中的型式參數的名稱。

對應項目

函式原型

ON_CONTROL_REFLECT( wNotifyCode, memberFxn )

afx_msg void memberFxn ( );

ON_NOTIFY_REFLECT( wNotifyCode, memberFxn )

afx_msg void memberFxn ( NMHDR * pNotifyStruct, LRESULT* result );

ON_UPDATE_COMMAND_UI_REFLECT (memberFxn)

afx_msg void memberFxn ( CCmdUI* pCmdUI );

ON_WM_CTLCOLOR_REFLECT)

afx_msg HBRUSH CtlColor ( CDC* pDC, UINT nCtlColor );

ON_WM_DRAWITEM_REFLECT)

afx_msg 會造成 DrawItem (LPDRAWITEMSTRUCTlpDrawItemStruct);

ON_WM_MEASUREITEM_REFLECT)

afx_msg 會造成 MeasureItem (LPMEASUREITEMSTRUCTlpMeasureItemStruct);

ON_WM_DELETEITEM_REFLECT)

afx_msg 會造成 DeleteItem (LPDELETEITEMSTRUCTlpDeleteItemStruct);

ON_WM_COMPAREITEM_REFLECT)

afx_msg int CompareItem (LPCOMPAREITEMSTRUCTlpCompareItemStruct);

ON_WM_CHARTOITEM_REFLECT)

afx_msg int CharToItem ( UINT nKey, UINT nIndex );

ON_WM_VKEYTOITEM_REFLECT)

afx_msg int VKeyToItem ( UINT nKey, UINT nIndex );

ON_WM_HSCROLL_REFLECT)

afx_msg void HScroll ( UINT nSBCode, UINT nPos );

ON_WM_VSCROLL_REFLECT)

afx_msg void VScroll ( UINT nSBCode, UINT nPos );

ON_WM_PARENTNOTIFY_REFLECT)

afx_msg void ParentNotify ( UINT message, LPARAM lParam );

ON_NOTIFY_REFLECTON_CONTROL_REFLECT 巨集有變化,可讓多個物件 (例如控制項和其父系) 來處理指定的訊息。

對應項目

函式原型

ON_NOTIFY_REFLECT_EX( wNotifyCode, memberFxn )

afx_msg BOOL memberFxn ( NMHDR * pNotifyStruct, LRESULT* result );

ON_CONTROL_REFLECT_EX( wNotifyCode, memberFxn )

afx_msg BOOL memberFxn ( );

可重複使用控制項的範例處理反映訊息:

這個簡單的範例會建立可重複使用的控制項,稱為CYellowEdit。 控制項是標準的編輯控制項相同唯一的黑色文字顯示在黃色背景上。 可輕鬆加入成員函式,讓CYellowEdit控制項來顯示不同的色彩。

若要建立可重複使用的控制項範例

  1. 在 [現有的應用程式中建立新的對話方塊。 如需詳細資訊,請參閱對話方塊編輯器主題。

    您必須在程式開發重複使用的控制項之應用程式。 如果您不能使用現有的應用程式,建立使用 AppWizard 對話方塊架構應用程式。

  2. 專案載入 Visual C++ 中,使用類別精靈來建立新的類別稱為CYellowEdit的CEdit

  3. 加入三個成員變數,以您CYellowEdit類別。 前兩個將會是 COLORREF 變數來保存文字色彩與背景色彩。 第三個將會是CBrush會保存繪製背景的筆刷的物件。 CBrush物件可讓您建立一次,只是參考之後,筆刷,並摧毀筆刷時自動CYellowEdit控制項就會損毀。

  4. 初始化成員變數,藉由撰寫建構函式,如下所示:

    CYellowEdit::CYellowEdit()
    {
       m_clrText = RGB( 0, 0, 0 );
       m_clrBkgnd = RGB( 255, 255, 0 );
       m_brBkgnd.CreateSolidBrush( m_clrBkgnd );
    }
    
  5. 使用類別精靈,加入的處理常式的反映WM_CTLCOLOR訊息至您CYellowEdit類別。 請注意表示郵件會反映在等號,您可以處理的郵件清單中的訊息名稱的前面。 請參閱定義反映訊息的訊息處理常式

    類別精靈為您新增下列的訊息對應巨集與基本架構函式:

    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. 取代為下列的程式碼的函式主體。 程式碼指定的文字色彩、 文字的背景色彩,以及其他控制項的背景色彩。

       pDC->SetTextColor( m_clrText );   // text
       pDC->SetBkColor( m_clrBkgnd );   // text bkgnd
       return m_brBkgnd;            // ctl bkgnd
    
  7. 建立編輯控制項在對話方塊中,然後將它附加至成員變數中,按兩下編輯控制項,同時按住 ctrl 鍵。 在 [加入成員變數] 對話方塊中,完成變數的名稱並選擇 [控制] 分類中,然後"CYellowEdit"變數的型別。 別忘了在對話方塊中設定 tab 鍵順序。 此外,務必要包含的標頭檔CYellowEdit控制項在對話方塊的標頭檔。

  8. 建置並執行您的應用程式。 編輯控制項必須為黃色背景。

請參閱

其他資源

技術的備忘稿編號

依類別的技術注意事項