Bagikan melalui


TN061: pesan ON_NOTIFY dan WM_NOTIFY

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 menyediakan informasi latar belakang tentang pesan WM_NOTIFY baru dan menjelaskan cara penanganan pesan WM_NOTIFY yang direkomendasikan (dan paling umum) di aplikasi MFC Anda.

Pesan Pemberitahuan di Windows 3.x

Di Windows 3.x, kontrol memberi tahu induk peristiwa mereka seperti klik mouse, perubahan konten dan pilihan, dan mengontrol lukisan latar belakang dengan mengirim pesan ke induk. Pemberitahuan sederhana dikirim sebagai pesan WM_COMMAND khusus, dengan kode pemberitahuan (seperti BN_CLICKED) dan ID kontrol yang dikemas ke wParam dan handel kontrol di lParam. Perhatikan bahwa karena wParam dan lParam penuh, tidak ada cara untuk meneruskan data tambahan — pesan ini hanya dapat berupa pemberitahuan sederhana. Misalnya, dalam pemberitahuan BN_CLICKED, tidak ada cara untuk mengirim informasi tentang lokasi kursor mouse saat tombol diklik.

Ketika kontrol di Windows 3.x perlu mengirim pesan pemberitahuan yang menyertakan data tambahan, mereka menggunakan berbagai pesan tujuan khusus, termasuk WM_CTLCOLOR, WM_VSCROLL, WM_HSCROLL, WM_DRAWITEM, WM_MEASUREITEM, WM_COMPAREITEM, WM_DELETEITEM, WM_CHARTOITEM, WM_VKEYTOITEM, dan sebagainya. Pesan-pesan ini dapat direfleksikan kembali ke kontrol yang mengirimnya. Untuk informasi selengkapnya, lihat TN062: Refleksi Pesan untuk Kontrol Windows.

Pesan Pemberitahuan di Win32

Untuk kontrol yang ada di Windows 3.1, API Win32 menggunakan sebagian besar pesan pemberitahuan yang digunakan di Windows 3.x. Namun, Win32 juga menambahkan sejumlah kontrol kompleks yang canggih ke kontrol yang didukung di Windows 3.x. Sering kali, kontrol ini perlu mengirim data tambahan dengan pesan pemberitahuan mereka. Daripada menambahkan pesan WM_* baru untuk setiap pemberitahuan baru yang membutuhkan data tambahan, perancang API Win32 memilih untuk menambahkan hanya satu pesan, WM_NOTIFY, yang dapat meneruskan sejumlah data tambahan dengan cara standar.

WM_NOTIFY pesan berisi ID kontrol yang mengirim pesan di wParam dan pointer ke struktur di lParam. Struktur ini adalah struktur NMHDR atau beberapa struktur yang lebih besar yang memiliki struktur NMHDR sebagai anggota pertamanya. Perhatikan bahwa karena anggota NMHDR adalah yang pertama, penunjuk ke struktur ini dapat digunakan sebagai penunjuk ke NMHDR atau sebagai penunjuk ke struktur yang lebih besar tergantung pada cara Anda mentransmisikannya.

Dalam kebanyakan kasus, pointer akan menunjuk ke struktur yang lebih besar dan Anda harus melemparkannya saat Anda menggunakannya. Hanya dalam beberapa pemberitahuan, seperti pemberitahuan umum (yang namanya dimulai dengan NM_) dan TTN_SHOW kontrol tip alat dan pemberitahuan TTN_POP, adalah struktur NMHDR yang benar-benar digunakan.

Struktur NMHDR atau anggota awal berisi handel dan ID kontrol yang mengirim pesan dan kode pemberitahuan (seperti TTN_SHOW). Format struktur NMHDR ditunjukkan di bawah ini:

typedef struct tagNMHDR {
    HWND hwndFrom;
    UINT idFrom;
    UINT code;
} NMHDR;

Untuk pesan TTN_SHOW, anggota kode akan diatur ke TTN_SHOW.

Sebagian besar pemberitahuan meneruskan penunjuk ke struktur yang lebih besar yang berisi struktur NMHDR sebagai anggota pertamanya. Misalnya, pertimbangkan struktur yang digunakan oleh pesan pemberitahuan LVN_KEYDOWN kontrol tampilan daftar, yang dikirim saat tombol ditekan dalam kontrol tampilan daftar. Pointer menunjuk ke struktur LV_KEYDOWN , yang didefinisikan seperti yang ditunjukkan di bawah ini:

typedef struct tagLV_KEYDOWN {
    NMHDR hdr;
    WORD wVKey;
    UINT flags;
} LV_KEYDOWN;

Perhatikan bahwa karena anggota NMHDR pertama kali dalam struktur ini, penunjuk yang Anda lewati dalam pesan pemberitahuan dapat dilemparkan ke penunjuk ke NMHDR atau penunjuk ke LV_KEYDOWN.

Pemberitahuan Umum untuk Semua Kontrol Windows Baru

Beberapa pemberitahuan umum untuk semua kontrol Windows baru. Pemberitahuan ini meneruskan penunjuk ke struktur NMHDR .

Kode pemberitahuan Dikirim karena
NM_CLICK Tombol mouse kiri yang diklik pengguna di kontrol
NM_DBLCLK Tombol mouse kiri yang diklik ganda pengguna di kontrol
NM_RCLICK Tombol mouse kanan yang diklik pengguna di kontrol
NM_RDBLCLK Tombol mouse kanan yang diklik ganda pengguna di kontrol
NM_RETURN Pengguna menekan tombol ENTER saat kontrol memiliki fokus input
NM_SETFOCUS Kontrol telah diberikan fokus input
NM_KILLFOCUS Kontrol telah kehilangan fokus input
NM_OUTOFMEMORY Kontrol tidak dapat menyelesaikan operasi karena tidak tersedia cukup memori

ON_NOTIFY: Menangani Pesan WM_NOTIFY di Aplikasi MFC

Fungsi CWnd::OnNotify ini menangani pesan pemberitahuan. Implementasi defaultnya memeriksa peta pesan untuk dipanggil oleh penangan pemberitahuan. Secara umum, Anda tidak mengambil alih OnNotify. Sebagai gantinya, Anda menyediakan fungsi handler dan menambahkan entri peta pesan untuk handler tersebut ke peta pesan kelas jendela pemilik Anda.

ClassWizard, melalui lembar properti ClassWizard, dapat membuat entri peta pesan ON_NOTIFY dan memberi Anda fungsi handler kerangka. Untuk informasi selengkapnya tentang menggunakan ClassWizard untuk mempermudah ini, lihat Memetakan Pesan ke Fungsi.

Makro ON_NOTIFY peta pesan memiliki sintaks berikut:

ON_NOTIFY(wNotifyCode, id, memberFxn)

dengan parameter:

wNotifyCode
Kode untuk pesan pemberitahuan yang akan ditangani, seperti LVN_KEYDOWN.

id
Pengidentifikasi anak kontrol tempat pemberitahuan dikirim.

memberFxn
Fungsi anggota yang akan dipanggil ketika pemberitahuan ini dikirim.

Fungsi anggota Anda harus dideklarasikan dengan prototipe berikut:

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

dengan parameter:

pNotifyStruct
Penunjuk ke struktur pemberitahuan, seperti yang dijelaskan di bagian di atas.

result
Penunjuk ke kode hasil yang akan Anda tetapkan sebelum kembali.

Contoh

Untuk menentukan bahwa Anda ingin fungsi OnKeydownList1 anggota menangani pesan LVN_KEYDOWN dari CListCtrl ID-nya IDC_LIST1, Anda akan menggunakan ClassWizard untuk menambahkan yang berikut ini ke peta pesan Anda:

ON_NOTIFY(LVN_KEYDOWN, IDC_LIST1, OnKeydownList1)

Dalam contoh di atas, fungsi yang disediakan oleh ClassWizard adalah:

void CMessageReflectionDlg::OnKeydownList1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;

    // TODO: Add your control notification handler
    //       code here

    *pResult = 0;
}

Perhatikan bahwa ClassWizard menyediakan penunjuk jenis yang tepat secara otomatis. Anda dapat mengakses struktur pemberitahuan melalui pNMHDR atau pLVKeyDow.

ON_NOTIFY_RANGE

Jika Anda perlu memproses pesan WM_NOTIFY yang sama untuk serangkaian kontrol, Anda dapat menggunakan ON_NOTIFY_RANGE daripada ON_NOTIFY. Misalnya, Anda mungkin memiliki sekumpulan tombol yang ingin Anda lakukan tindakan yang sama untuk pesan pemberitahuan tertentu.

Saat Anda menggunakan ON_NOTIFY_RANGE, Anda menentukan rentang pengidentifikasi anak yang berdampingan untuk menangani pesan pemberitahuan dengan menentukan pengidentifikasi anak awal dan akhir rentang.

ClassWizard tidak menangani ON_NOTIFY_RANGE; untuk menggunakannya, Anda perlu mengedit peta pesan Anda sendiri.

Entri peta pesan dan prototipe fungsi untuk ON_NOTIFY_RANGE adalah sebagai berikut:

ON_NOTIFY_RANGE(wNotifyCode, id, idLast, memberFxn)

dengan parameter:

wNotifyCode
Kode untuk pesan pemberitahuan yang akan ditangani, seperti LVN_KEYDOWN.

id
Pengidentifikasi pertama dalam rentang pengidentifikasi yang berdampingan.

idLast
Pengidentifikasi terakhir dalam rentang pengidentifikasi yang berdampingan.

memberFxn
Fungsi anggota yang akan dipanggil ketika pemberitahuan ini dikirim.

Fungsi anggota Anda harus dideklarasikan dengan prototipe berikut:

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

dengan parameter:

id
Pengidentifikasi anak kontrol yang mengirim pemberitahuan.

pNotifyStruct
Penunjuk ke struktur pemberitahuan, seperti yang dijelaskan di atas.

result
Penunjuk ke kode hasil yang akan Anda tetapkan sebelum kembali.

ON_NOTIFY_EX, ON_NOTIFY_EX_RANGE

Jika Anda ingin lebih dari satu objek dalam perutean pemberitahuan menangani pesan, Anda dapat menggunakan ON_NOTIFY_EX (atau ON_NOTIFY_EX_RANGE) daripada ON_NOTIFY (atau ON_NOTIFY_RANGE). Satu-satunya perbedaan antara versi EX dan versi reguler adalah bahwa fungsi anggota yang dipanggil untuk versi EX mengembalikan BOOL yang menunjukkan apakah pemrosesan pesan harus dilanjutkan atau tidak. Mengembalikan FALSE dari fungsi ini memungkinkan Anda memproses pesan yang sama di lebih dari satu objek.

ClassWizard tidak menangani ON_NOTIFY_EX atau ON_NOTIFY_EX_RANGE; jika Anda ingin menggunakan salah satunya, Anda perlu mengedit peta pesan Anda sendiri.

Entri peta pesan dan prototipe fungsi untuk ON_NOTIFY_EX dan ON_NOTIFY_EX_RANGE adalah sebagai berikut. Arti parameter sama dengan untuk versi non-EX.

ON_NOTIFY_EX(nCode, id, memberFxn)
ON_NOTIFY_EX_RANGE(wNotifyCode, id, idLast, memberFxn)

Prototipe untuk kedua hal di atas sama:

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

Dalam kedua kasus, id memegang pengidentifikasi anak dari kontrol yang mengirim pemberitahuan.

Fungsi Anda harus mengembalikan TRUE jika pesan pemberitahuan telah sepenuhnya ditangani atau FALSE jika objek lain dalam perutean perintah harus memiliki kesempatan untuk menangani pesan.

Baca juga

Catatan Teknis menurut Angka
Catatan Teknis menurut Kategori