TN062: Windows Denetimleri için İleti Yansıması
Dekont
Aşağıdaki teknik not, çevrimiçi belgelere ilk kez eklendiğinden beri güncelleştirilmemiştir. Sonuç olarak, bazı yordamlar ve konular güncel olmayabilir veya yanlış olabilir. En son bilgiler için, çevrimiçi belge dizininde ilgilendiğiniz konuyu aramanız önerilir.
Bu teknik not, MFC 4.0'daki yeni bir özellik olan ileti yansımasını açıklar. Ayrıca, ileti yansımasını kullanan basit bir yeniden kullanılabilir denetim oluşturmaya yönelik yönergeler içerir.
Bu teknik not, ActiveX denetimleri (eski adı OLE denetimleri) için geçerli olduğundan ileti yansımasını ele almaz. Lütfen ActiveX Denetimleri: Windows Denetimini Alt Sınıflama makalesine bakın.
İleti Düşünceler nedir?
Windows denetimleri, üst pencerelerine sık sık bildirim iletileri gönderir. Örneğin, birçok denetim, üst denetimin arka planını boyamak için bir fırça sağlamasına izin vermek için üst öğelerine bir denetim rengi bildirim iletisi (WM_CTLCOLOR veya değişkenlerinden biri) gönderir.
Windows'ta ve 4.0 sürümünden önceki MFC'de, bu iletilerin işlenmesi genellikle bir iletişim kutusu olan üst pencere sorumludur. Bu, ileti işleme kodunun üst pencerenin sınıfında olması ve bu iletiyi işlemesi gereken her sınıfta çoğaltılması gerektiği anlamına gelir. Yukarıdaki örnekte, özel arka planlara sahip denetimleri isteyen her iletişim kutusunun denetim rengi bildirim iletisini işlemesi gerekir. Kendi arka plan rengini işleyecek bir denetim sınıfı yazılabilirse kodu yeniden kullanmak çok daha kolay olacaktır.
MFC 4.0'da eski mekanizma hala çalışır; üst pencereler bildirim iletilerini işleyebilir. Buna ek olarak, MFC 4.0, bu bildirim iletilerinin alt denetim penceresinde veya üst pencerede ya da her ikisinde de işlenmesini sağlayan "ileti yansıması" adlı bir özellik sağlayarak yeniden kullanımı kolaylaştırır. Denetim arka plan rengi örneğinde, artık yansıtılan WM_CTLCOLOR iletisini işleyerek kendi arka plan rengini ayarlayan bir denetim sınıfı yazabilirsiniz . (İleti yansıması Windows tarafından değil MFC tarafından uygulandığından, ileti yansımasının çalışması için üst pencere sınıfının türetilmesi CWnd
gerektiğini unutmayın.)
MFC'nin eski sürümleri, sahip tarafından çizilen liste kutularına yönelik iletiler (WM_DRAWITEM vb.) gibi birkaç ileti için sanal işlevler sağlayarak ileti yansımasına benzer bir şey yaptı. Yeni ileti yansıma mekanizması genelleştirilmiş ve tutarlıdır.
İleti yansıması, 4.0'dan önceki MFC sürümleri için yazılmış kodla geriye dönük olarak uyumludur.
Üst pencerenizin sınıfında belirli bir ileti için veya bir ileti aralığı için bir işleyici sağladıysanız, temel sınıf işleyici işlevini kendi işleyicinizde çağırmadığınız takdirde aynı iletinin yansıtılmış ileti işleyicilerini geçersiz kılar. Örneğin, iletişim kutusu sınıfınızdaki WM_CTLCOLOR işlerseniz, işlemeniz yansıtılan ileti işleyicilerini geçersiz kılar.
Üst pencere sınıfınızda belirli bir WM_NOTIFY iletisi veya WM_NOTIFY ileti aralığı için bir işleyici sağlarsanız, işleyiciniz yalnızca bu iletileri gönderen alt denetimin üzerinden ON_NOTIFY_REFLECT()
yansıtılmış bir ileti işleyicisi yoksa çağrılır. İleti eşlemenizde kullanıyorsanız ON_NOTIFY_REFLECT_EX()
, ileti işleyiciniz üst pencerenin iletiyi işlemesine izin verebilir veya vermeyebilir. İşleyici FALSE döndürürse, ileti üst öğe tarafından da işlenirken, TRUE döndüren bir çağrı üst öğe tarafından işlenmesine izin vermez. Yansıtılan iletinin bildirim iletisinden önce işlendiğini unutmayın.
bir WM_NOTIFY iletisi gönderildiğinde, denetime iletinin işlenmesi için ilk şans sunulur. Başka bir yansıtılan ileti gönderilirse, üst pencerenin bunu işlemek için ilk şansı vardır ve denetim yansıtılan iletiyi alır. Bunu yapmak için bir işleyici işlevi ve denetimin sınıf ileti eşlemesinde uygun bir giriş gerekir.
Yansıtılan iletiler için ileti eşleme makrosunun normal bildirimlere göre biraz farklı olması gerekir: normal adının sonuna _REFLECT eklenmiştir. Örneğin, üst öğedeki WM_NOTIFY bir iletiyi işlemek için üst ileti eşlemesinde makro ON_NOTIFY kullanırsınız. Alt denetimde yansıtılan iletiyi işlemek için alt denetimin ileti eşlemesindeki ON_NOTIFY_REFLECT makroyu kullanın. Bazı durumlarda parametreler de farklıdır. ClassWizard'ın genellikle sizin için ileti eşlemesi girdilerini ekleyebileceğini ve doğru parametrelerle iskelet işlev uygulamaları sağlayabildiğini unutmayın.
Yeni WM_NOTIFY iletisi hakkında bilgi için bkz . TN061: ON_NOTIFY ve WM_NOTIFY İletileri .
Düşünceler İletiler için İleti Eşleme Girdileri ve İşleyici İşlev Prototipleri
Yansıtılmış bir denetim bildirim iletisini işlemek için aşağıdaki tabloda listelenen ileti eşleme makrolarını ve işlev prototiplerini kullanın.
ClassWizard genellikle sizin için bu ileti eşlemesi girdilerini ekleyebilir ve iskelet işlev uygulamaları sağlayabilir. Yansıtılan iletiler için işleyicileri tanımlama hakkında bilgi için bkz. Düşünceler İleti için İleti İşleyicisi Tanımlama.
İleti adından yansıtılan makro adına dönüştürmek için ON_ ekleyin ve _REFLECT ekleyin. Örneğin, WM_CTLCOLOR ON_WM_CTLCOLOR_REFLECT olur. (Hangi iletilerin yansıtılabildiğini görmek için, aşağıdaki tabloda yer alan makro girişlerinde ters dönüştürme yapın.)
Yukarıdaki kuralın üç özel durumu şunlardır:
WM_COMMAND bildirimleri için makro ON_CONTROL_REFLECT.
WM_NOTIFY yansımaları için makro ON_NOTIFY_REFLECT.
ON_UPDATE_COMMAND_UI yansımaları için makro ON_UPDATE_COMMAND_UI_REFLECT.
Yukarıdaki özel durumların her birinde işleyici üye işlevinin adını belirtmeniz gerekir. Diğer durumlarda, işleyici işleviniz için standart adı kullanmanız gerekir.
İşlevlerin parametrelerinin ve dönüş değerlerinin anlamları, işlevin adı veya işlevin adı altında On prepended ile belgelenmiştir. Örneğin, CtlColor
içinde OnCtlColor
belgelenmiştir. Yansıtılan birkaç ileti işleyicisi, üst penceredeki benzer işleyicilerden daha az parametreye ihtiyaç duyar. Aşağıdaki tabloda yer alan adları belgelerdeki resmi parametrelerin adlarıyla eşleştirmesi gerekir.
Eşleme girdisi | İşlev prototipi |
---|---|
ON_CONTROL_REFLECT(wNotifyCode ,)memberFxn |
afx_msg voidmemberFxn ( ); |
ON_NOTIFY_REFLECT(wNotifyCode ,)memberFxn |
afx_msg voidmemberFxn ( NMHDR*pNotifyStruct , LRESULT*sonucu); |
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 |
ON_NOTIFY_REFLECT ve ON_CONTROL_REFLECT makroları, belirli bir iletiyi birden çok nesnenin (denetim ve üst öğe gibi) işlemesine olanak sağlayan çeşitlemelere sahiptir.
Eşleme girdisi | İşlev prototipi |
---|---|
ON_NOTIFY_REFLECT_EX(wNotifyCode ,)memberFxn |
afx_msg BOOLmemberFxn ( NMHDR*pNotifyStruct , LRESULT*sonucu); |
ON_CONTROL_REFLECT_EX(wNotifyCode ,)memberFxn |
afx_msg BOOLmemberFxn ( ); |
Düşünceler İletileri İşleme: Yeniden Kullanılabilir denetim örneği
Bu basit örnek adlı CYellowEdit
yeniden kullanılabilir bir denetim oluşturur. Denetim, sarı arka planda siyah metin görüntülemesi dışında normal düzenleme denetimiyle aynı şekilde çalışır. Denetimin farklı renkler görüntülemesini sağlayacak CYellowEdit
üye işlevleri eklemek kolay olabilir.
Yeniden kullanılabilir bir denetim oluşturan örneği denemek için
Var olan bir uygulamada yeni bir iletişim kutusu oluşturun. Daha fazla bilgi için iletişim kutusu düzenleyicisi konusuna bakın.
Yeniden kullanılabilir denetimi geliştirmek için bir uygulamanız olmalıdır. Kullanılacak bir uygulamanız yoksa AppWizard kullanarak iletişim kutusu tabanlı bir uygulama oluşturun.
Projeniz Visual C++'a yüklendiğinde ClassWizard'ı kullanarak tabanlı
CEdit
adlıCYellowEdit
yeni bir sınıf oluşturun.Sınıfınıza
CYellowEdit
üç üye değişkeni ekleyin. İlk ikisi, metin rengini ve arka plan rengini tutan COLORREF değişkenleri olacaktır. Üçüncüsü, arka planı boyamak için fırçayı tutacak birCBrush
nesne olacaktır. NesneCBrush
, fırçayı bir kez oluşturmanıza, yalnızca ondan sonra başvurmanıza ve denetim yok edildiğindeCYellowEdit
fırçayı otomatik olarak yok etmenizi sağlar.Oluşturucuyu aşağıdaki gibi yazarak üye değişkenlerini başlatın:
CYellowEdit::CYellowEdit() { m_clrText = RGB(0, 0, 0); m_clrBkgnd = RGB(255, 255, 0); m_brBkgnd.CreateSolidBrush(m_clrBkgnd); }
ClassWizard kullanarak, sınıfınıza
CYellowEdit
yansıtılan WM_CTLCOLOR iletisi için bir işleyici ekleyin. İşleyebileceğiniz iletiler listesindeki ileti adının önündeki eşittir işaretinin iletinin yansıtıldığını gösterdiğine dikkat edin. Bu, Düşünceler İleti için İleti İşleyicisi Tanımlama bölümünde açıklanmıştır.ClassWizard sizin için aşağıdaki ileti eşleme makro ve iskelet işlevini ekler:
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; }
işlevinin gövdesini aşağıdaki kodla değiştirin. Kod, denetimin geri kalanı için metin rengini, metin arka plan rengini ve arka plan rengini belirtir.
pDC->SetTextColor(m_clrText); // text pDC->SetBkColor(m_clrBkgnd); // text bkgnd return m_brBkgnd; // ctl bkgnd
İletişim kutunuzda bir düzenleme denetimi oluşturun, ardından denetim tuşunu basılı tutarak düzenleme denetimine çift tıklayarak bunu bir üye değişkenine ekleyin. Üye Değişkeni Ekle iletişim kutusunda değişken adını tamamlayın ve kategori için "Denetim" öğesini, ardından değişken türü için "CYellowEdit" öğesini seçin. İletişim kutusunda sekme sırasını ayarlamayı unutmayın. Ayrıca, iletişim kutunuzun üst bilgi dosyasına denetimin
CYellowEdit
üst bilgi dosyasını eklediğinizden emin olun.Uygulamanızı derleyin ve çalıştırın. Düzenleme denetiminin arka planı sarı olur.