Bagikan melalui


TN062: Refleksi Pesan untuk Kontrol Windows

Catatan

Catatan teknis berikut belum diperbarui sejak pertama kali disertakan dalam dokumentasi online. Akibatnya, beberapa prosedur dan topik mungkin kedaluarsa atau salah. Untuk informasi terbaru, disarankan agar Anda mencari topik yang menarik dalam indeks dokumentasi online.

Catatan teknis ini menjelaskan refleksi pesan, fitur baru di MFC 4.0. Ini juga berisi petunjuk arah untuk membuat kontrol sederhana yang dapat digunakan kembali yang menggunakan pantulan pesan.

Catatan teknis ini tidak membahas refleksi pesan karena berlaku untuk kontrol ActiveX (sebelumnya disebut kontrol OLE). Silakan lihat artikel Kontrol ActiveX: Subkelas Kontrol Windows.

Apa itu Refleksi Pesan

Kontrol Windows sering mengirim pesan pemberitahuan ke jendela induknya. Misalnya, banyak kontrol mengirim pesan pemberitahuan warna kontrol (WM_CTLCOLOR atau salah satu variannya) ke induknya untuk memungkinkan induk menyediakan kuas untuk melukis latar belakang kontrol.

Di Windows dan di MFC sebelum versi 4.0, jendela induk, sering kali kotak dialog, bertanggung jawab untuk menangani pesan-pesan ini. Ini berarti bahwa kode untuk menangani pesan harus berada di kelas jendela induk dan harus diduplikasi di setiap kelas yang perlu menangani pesan tersebut. Dalam kasus di atas, setiap kotak dialog yang menginginkan kontrol dengan latar belakang kustom harus menangani pesan pemberitahuan warna kontrol. Akan jauh lebih mudah untuk menggunakan kembali kode jika kelas kontrol dapat ditulis yang akan menangani warna latar belakangnya sendiri.

Di MFC 4.0, mekanisme lama masih berfungsi — jendela induk dapat menangani pesan pemberitahuan. Namun, MFC 4.0 memfasilitasi penggunaan kembali dengan menyediakan fitur yang disebut "pantulan pesan" yang memungkinkan pesan pemberitahuan ini ditangani di jendela kontrol anak atau jendela induk, atau di keduanya. Dalam contoh warna latar belakang kontrol, Anda sekarang dapat menulis kelas kontrol yang mengatur warna latar belakangnya sendiri dengan menangani pesan WM_CTLCOLOR yang tercermin — semua tanpa mengandalkan induk. (Perhatikan bahwa karena refleksi pesan diimplementasikan oleh MFC, bukan oleh Windows, kelas jendela induk harus berasal dari CWnd agar refleksi pesan berfungsi.)

Versi MFC yang lebih lama melakukan sesuatu yang mirip dengan refleksi pesan dengan menyediakan fungsi virtual untuk beberapa pesan, seperti pesan untuk kotak daftar yang digambar pemilik (WM_DRAWITEM, dan sebagainya). Mekanisme refleksi pesan baru digeneralisasi dan konsisten.

Refleksi pesan kompatibel mundur dengan kode yang ditulis untuk versi MFC sebelum 4.0.

Jika Anda telah menyediakan handler untuk pesan tertentu, atau untuk rentang pesan, di kelas jendela induk Anda, itu akan menimpa handler pesan yang tercermin untuk pesan yang sama asalkan Anda tidak memanggil fungsi handler kelas dasar di handler Anda sendiri. Misalnya, jika Anda menangani WM_CTLCOLOR di kelas kotak dialog, penanganan Anda akan menimpa penangan pesan yang tercermin.

Jika, di kelas jendela induk, Anda menyediakan handler untuk pesan WM_NOTIFY tertentu atau rentang pesan WM_NOTIFY, handler Anda akan dipanggil hanya jika kontrol anak yang mengirim pesan tersebut tidak memiliki handler pesan yang tercermin melalui ON_NOTIFY_REFLECT(). Jika Anda menggunakan ON_NOTIFY_REFLECT_EX() dalam peta pesan, penanganan pesan Anda mungkin atau mungkin tidak mengizinkan jendela induk untuk menangani pesan. Jika handler mengembalikan FALSE, pesan akan ditangani oleh induk juga, sementara panggilan yang mengembalikan TRUE tidak memungkinkan induk untuk menanganinya. Perhatikan bahwa pesan yang tercermin ditangani sebelum pesan pemberitahuan.

Ketika pesan WM_NOTIFY dikirim, kontrol ditawarkan kesempatan pertama untuk menanganinya. Jika ada pesan lain yang tercermin dikirim, jendela induk memiliki kesempatan pertama untuk menanganinya dan kontrol akan menerima pesan yang tercermin. Untuk melakukannya, diperlukan fungsi handler dan entri yang sesuai dalam peta pesan kelas kontrol.

Makro peta pesan untuk pesan yang direfleksikan sedikit berbeda dari untuk pemberitahuan reguler: makro tersebut telah _REFLECT ditambahkan ke nama yang biasa. Misalnya, untuk menangani pesan WM_NOTIFY di induk, Anda menggunakan ON_NOTIFY makro di peta pesan induk. Untuk menangani pesan yang tercermin dalam kontrol turunan, gunakan makro ON_NOTIFY_REFLECT di peta pesan kontrol anak. Dalam beberapa kasus, parameternya juga berbeda. Perhatikan bahwa ClassWizard biasanya dapat menambahkan entri peta pesan untuk Anda dan menyediakan implementasi fungsi kerangka dengan parameter yang benar.

Lihat TN061: pesan ON_NOTIFY dan WM_NOTIFY untuk informasi tentang pesan WM_NOTIFY baru.

Entri Peta Pesan dan Prototipe Fungsi Handler untuk Pesan yang Tercermin

Untuk menangani pesan pemberitahuan kontrol yang tercermin, gunakan makro peta pesan dan prototipe fungsi yang tercantum dalam tabel di bawah ini.

ClassWizard biasanya dapat menambahkan entri peta pesan ini untuk Anda dan menyediakan implementasi fungsi kerangka. Lihat Menentukan Penanganan Pesan untuk Pesan Tercermin untuk informasi tentang cara menentukan penangan untuk pesan yang tercermin.

Untuk mengonversi dari nama pesan ke nama makro yang tercermin, tambahkan ON_ sebelumnya dan tambahkan _REFLECT. Misalnya, WM_CTLCOLOR menjadi ON_WM_CTLCOLOR_REFLECT. (Untuk melihat pesan mana yang dapat direfleksikan, lakukan konversi yang berlawanan pada entri makro dalam tabel di bawah ini.)

Tiga pengecualian untuk aturan di atas adalah sebagai berikut:

  • Makro untuk pemberitahuan WM_COMMAND ON_CONTROL_REFLECT.

  • Makro untuk pantulan WM_NOTIFY ON_NOTIFY_REFLECT.

  • Makro untuk pantulan ON_UPDATE_COMMAND_UI ON_UPDATE_COMMAND_UI_REFLECT.

Dalam setiap kasus khusus di atas, Anda harus menentukan nama fungsi anggota handler. Dalam kasus lain, Anda harus menggunakan nama standar untuk fungsi handler Anda.

Arti parameter dan nilai pengembalian fungsi didokumentasikan dengan nama fungsi atau nama fungsi dengan On prepended. Misalnya, CtlColor didokumenkan dalam OnCtlColor. Beberapa penangan pesan yang tercermin membutuhkan lebih sedikit parameter daripada handler serupa di jendela induk. Cukup cocokkan nama dalam tabel di bawah ini dengan nama parameter formal dalam dokumentasi.

Entri peta Prototipe fungsi
ON_CONTROL_REFLECT(wNotifyCode,)memberFxn afx_msg batalmemberFxn( );
ON_NOTIFY_REFLECT(wNotifyCode,)memberFxn afx_msg voidmemberFxn( NMHDRpNotifyStruct*, hasil LRESULT*);
ON_UPDATE_COMMAND_UI_REFLECT(memberFxn) afx_msg voidmemberFxn( CCmdUIpCmdUI*);
ON_WM_CTLCOLOR_REFLECT( ) afx_msg HBRUSH CtlColor (CDCpDC*, UINTnCtlColor);
ON_WM_DRAWITEM_REFLECT( ) afx_msg void DrawItem (LPDRAWITEMSTRUCTlpDrawItemStruct);
ON_WM_MEASUREITEM_REFLECT( ) afx_msg mengukur 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, UINTnIndex);
ON_WM_VKEYTOITEM_REFLECT( ) afx_msg int VKeyToItem ( UINTnKey, UINTnIndex);
ON_WM_HSCROLL_REFLECT( ) afx_msg void HScroll (UINTnSBCode, UINTnPos);
ON_WM_VSCROLL_REFLECT( ) afx_msg void VScroll (UINTnSBCode, UINTnPos);
ON_WM_PARENTNOTIFY_REFLECT( ) afx_msg void ParentNotify (UINTmessage, LPARAMlParam);

Makro ON_NOTIFY_REFLECT dan ON_CONTROL_REFLECT memiliki variasi yang memungkinkan lebih dari satu objek (seperti kontrol dan induknya) untuk menangani pesan tertentu.

Entri peta Prototipe fungsi
ON_NOTIFY_REFLECT_EX(wNotifyCode,)memberFxn afx_msg BOOLmemberFxn( NMHDRpNotifyStruct*, hasil LRESULT*);
ON_CONTROL_REFLECT_EX(wNotifyCode,)memberFxn afx_msg BOOLmemberFxn( );

Menangani Pesan tercermin: Contoh kontrol yang dapat digunakan kembali

Contoh sederhana ini membuat kontrol yang dapat digunakan kembali yang disebut CYellowEdit. Kontrol bekerja sama dengan kontrol edit reguler kecuali menampilkan teks hitam pada latar belakang kuning. Akan mudah untuk menambahkan fungsi anggota yang akan memungkinkan CYellowEdit kontrol untuk menampilkan warna yang berbeda.

Untuk mencoba contoh yang membuat kontrol yang dapat digunakan kembali

  1. Buat kotak dialog baru di aplikasi yang sudah ada. Untuk informasi selengkapnya, lihat topik editor dialog.

    Anda harus memiliki aplikasi untuk mengembangkan kontrol yang dapat digunakan kembali. Jika Anda tidak memiliki aplikasi yang sudah ada untuk digunakan, buat aplikasi berbasis dialog menggunakan AppWizard.

  2. Dengan proyek Anda dimuat ke Visual C++, gunakan ClassWizard untuk membuat kelas baru yang disebut CYellowEdit berdasarkan CEdit.

  3. Tambahkan tiga variabel anggota ke kelas Anda CYellowEdit . Dua yang pertama adalah variabel COLORREF untuk menahan warna teks dan warna latar belakang. Yang ketiga akan menjadi CBrush objek yang akan memegang kuas untuk melukis latar belakang. Objek ini CBrush memungkinkan Anda untuk membuat kuas sekali, hanya merujuknya setelah itu, dan untuk menghancurkan kuas secara otomatis ketika CYellowEdit kontrol dihancurkan.

  4. Inisialisasi variabel anggota dengan menulis konstruktor sebagai berikut:

    CYellowEdit::CYellowEdit()
    {
        m_clrText = RGB(0, 0, 0);
        m_clrBkgnd = RGB(255, 255, 0);
        m_brBkgnd.CreateSolidBrush(m_clrBkgnd);
    }
    
  5. Menggunakan ClassWizard, tambahkan handler untuk pesan WM_CTLCOLOR yang tercermin ke kelas Anda CYellowEdit . Perhatikan bahwa masuk yang sama di depan nama pesan dalam daftar pesan yang dapat Anda tangani menunjukkan bahwa pesan tercermin. Ini dijelaskan dalam Mendefinisikan Handler Pesan untuk Pesan Tercermin.

    ClassWizard menambahkan fungsi makro dan kerangka peta pesan berikut untuk Anda:

    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. Ganti isi fungsi dengan kode berikut. Kode menentukan warna teks, warna latar belakang teks, dan warna latar belakang untuk kontrol lainnya.

    pDC->SetTextColor(m_clrText);   // text
    pDC->SetBkColor(m_clrBkgnd);    // text bkgnd
    return m_brBkgnd;               // ctl bkgnd
    
  7. Buat kontrol edit dalam kotak dialog Anda, lalu lampirkan ke variabel anggota dengan mengklik dua kali kontrol edit sambil menahan tombol kontrol. Dalam kotak dialog Tambahkan Variabel Anggota, selesaikan nama variabel dan pilih "Kontrol" untuk kategori, lalu "CYellowEdit" untuk jenis variabel. Jangan lupa untuk mengatur urutan tab dalam kotak dialog. Selain itu, pastikan untuk menyertakan file header untuk CYellowEdit kontrol dalam file header kotak dialog Anda.

  8. Buat dan jalankan aplikasi Anda. Kontrol edit akan memiliki latar belakang kuning.

Baca juga

Catatan Teknis menurut Angka
Catatan Teknis menurut Kategori