Tentang Pesan dan Antrean Pesan

Tidak seperti aplikasi berbasis MS-DOS, aplikasi berbasis Windows digerakkan oleh peristiwa. Mereka tidak melakukan panggilan fungsi eksplisit (seperti panggilan pustaka run-time C) untuk mendapatkan input. Sebaliknya, mereka menunggu sistem untuk meneruskan input kepada mereka.

Sistem meneruskan semua input untuk aplikasi ke berbagai jendela dalam aplikasi. Setiap jendela memiliki fungsi, yang disebut prosedur jendela, yang dipanggil sistem setiap kali memiliki input untuk jendela. Prosedur jendela memproses input dan mengembalikan kontrol ke sistem. Untuk informasi selengkapnya tentang prosedur jendela, lihat Prosedur Jendela.

Jika jendela tingkat atas berhenti merespons pesan selama lebih dari beberapa detik, sistem menganggap jendela tidak merespons. Dalam hal ini, sistem menyembunyikan jendela dan menggantinya dengan jendela hantu yang memiliki urutan Z, lokasi, ukuran, dan atribut visual yang sama. Ini memungkinkan pengguna untuk memindahkannya, mengubah ukurannya, atau bahkan menutup aplikasi. Namun, ini adalah satu-satunya tindakan yang tersedia karena aplikasi sebenarnya tidak merespons. Ketika dalam mode debugger, sistem tidak menghasilkan jendela hantu.

Bagian ini membahas topik berikut:

Pesan Windows

Sistem meneruskan input ke prosedur jendela dalam bentuk pesan. Pesan dihasilkan oleh sistem dan aplikasi. Sistem menghasilkan pesan di setiap peristiwa input—misalnya, saat pengguna mengetik, memindahkan mouse, atau mengklik kontrol seperti bilah gulir. Sistem ini juga menghasilkan pesan sebagai respons terhadap perubahan dalam sistem yang dibawa oleh aplikasi, seperti ketika aplikasi mengubah kumpulan sumber daya font sistem atau mengubah ukuran salah satu jendelanya. Aplikasi dapat menghasilkan pesan untuk mengarahkan jendelanya sendiri untuk melakukan tugas atau berkomunikasi dengan jendela di aplikasi lain.

Sistem mengirim pesan ke prosedur jendela dengan sekumpulan empat parameter: handel jendela, pengidentifikasi pesan, dan dua nilai yang disebut parameter pesan. Handel jendela mengidentifikasi jendela yang pesannya dimaksudkan. Sistem menggunakannya untuk menentukan prosedur jendela mana yang harus menerima pesan.

Pengidentifikasi pesan adalah konstanta bernama yang mengidentifikasi tujuan pesan. Saat prosedur jendela menerima pesan, prosedur ini menggunakan pengidentifikasi pesan untuk menentukan cara memproses pesan. Misalnya, pengidentifikasi pesan WM_PAINT memberi tahu prosedur jendela bahwa area klien jendela telah berubah dan harus dicat ulang.

Parameter pesan menentukan data atau lokasi data yang digunakan oleh prosedur jendela saat memproses pesan. Arti dan nilai parameter pesan bergantung pada pesan. Parameter pesan dapat berisi bilangan bulat, bendera bit yang dikemas, penunjuk ke struktur yang berisi data tambahan, dan sebagainya. Ketika pesan tidak menggunakan parameter pesan, pesan biasanya diatur ke NULL. Prosedur jendela harus memeriksa pengidentifikasi pesan untuk menentukan cara menginterpretasikan parameter pesan.

Jenis pesan

Bagian ini menjelaskan dua jenis pesan:

Pesan System-Defined

Sistem mengirim atau memposting pesan yang ditentukan sistem saat berkomunikasi dengan aplikasi. Ini menggunakan pesan-pesan ini untuk mengontrol operasi aplikasi dan untuk memberikan input dan informasi lain untuk diproses aplikasi. Aplikasi juga dapat mengirim atau memposting pesan yang ditentukan sistem. Aplikasi umumnya menggunakan pesan ini untuk mengontrol pengoperasian jendela kontrol yang dibuat dengan menggunakan kelas jendela yang telah terdaftar sebelumnya.

Setiap pesan yang ditentukan sistem memiliki pengidentifikasi pesan unik dan konstanta simbolis yang sesuai (ditentukan dalam file header kit pengembangan perangkat lunak (SDK) yang menyatakan tujuan pesan. Misalnya, WM_PAINT permintaan konstan yang dicat jendela isinya.

Konstanta simbolis menentukan kategori tempat pesan yang ditentukan sistem berada. Awalan konstanta mengidentifikasi jenis jendela yang dapat menginterpretasikan dan memproses pesan. Berikut ini adalah awalan dan kategori pesan terkait.

Prefiks Kategori pesan Dokumentasi
ABM dan ABN Toolbar desktop aplikasi Pesan dan Pemberitahuan Shell
ACM dan ACN Kontrol animasi Pesan Kontrol Animasi dan Pemberitahuan Kontrol Animasi
BCM, BCN, BM, dan BN Kontrol tombol Tombol Kontrol Pesan dan Pemberitahuan Kontrol Tombol
CB dan CBN Kontrol ComboBox Pesan Kontrol ComboBox dan Pemberitahuan Kontrol Kotak Kombo
CBEM dan CBEN Kontrol ComboBoxEx Pesan ComboBoxEx dan Pemberitahuan ComboBoxEx
CCM Kontrol umum Mengontrol Pesan
CDM Kotak dialog umum Pesan Kotak Dialog Umum
DFM Menu konteks default Pesan dan Pemberitahuan Shell
DL Seret kotak daftar Seret Pemberitahuan Kotak Daftar
DM Kontrol tombol dorong default Pesan Kotak Dialog
DTM dan DTN Kontrol pemilih tanggal dan waktu Pesan Pemilih Tanggal dan Waktu serta Pemberitahuan Pemilih Tanggal dan Waktu
EM dan EN Edit kontrol Edit Pesan Kontrol, Edit Pemberitahuan Kontrol, Pesan Edit Kaya, dan Pemberitahuan Edit Kaya
HDM dan HDN Kontrol header Pesan Kontrol Header dan Pemberitahuan Kontrol Header
HKM Kontrol kunci panas Pesan Kontrol Kunci Panas
IPM dan IPN Kontrol alamat IP Pesan Alamat IP dan Pemberitahuan Alamat IP
LB dan LBN Kontrol kotak daftar Pesan Kotak Daftar dan Pemberitahuan Kotak Daftar
LM Kontrol SysLink Pesan Kontrol SysLink
LVM dan LVN Kontrol tampilan daftar Tampilan Daftar Pesan dan Pemberitahuan Tampilan Daftar
MCM dan MCN Kontrol kalender bulan Pesan Kalender Bulan dan Pemberitahuan Kalender Bulan
PBM Bilah kemajuan Pesan Bilah Kemajuan
PGM dan PGN Kontrol pager Pesan Kontrol Pager dan Pemberitahuan Kontrol Pager
PSM dan PSN Lembar properti Pesan Lembar Properti dan Pemberitahuan Lembar Properti
RB dan RBN Kontrol bilah ulang Pesan Kontrol Bilah Ulang dan Pemberitahuan Kontrol Bilah Ulang
SB dan SBN Jendela bilah status Pesan Bilah Status dan Pemberitahuan Bilah Status
MBS Kontrol bilah gulir Pesan Bilah Gulir
SMC Menu shell Pesan dan Pemberitahuan Shell
STM dan STN Kontrol statis Pesan Kontrol Statis dan Pemberitahuan Kontrol Statis
TB dan TBN Toolbar Pesan Kontrol Bilah Alat dan Pemberitahuan Kontrol Bilah Alat
TBM dan TRBN Kontrol bilah trek Trackbar Control Messages dan Trackbar Control Notifications
TCM dan TCN Kontrol tab Pesan Kontrol Tab dan Pemberitahuan Kontrol Tab
TDM dan TDN Dialog tugas Pesan Dialog Tugas dan Pemberitahuan Dialog Tugas
TTM dan TTN Kontrol tipsalat Pesan Kontrol TipsAlat dan Pemberitahuan Kontrol TipsAlat
TVM dan TVN Kontrol tampilan pohon Pesan Tampilan Pohon dan Pemberitahuan Tampilan Pohon
UDM dan UDN Kontrol naik turun Pesan Naik danPemberitahuan Naik Turun
WM Umum
Pesan Clipboard
Pemberitahuan Clipboard
Pemberitahuan Kotak Dialog Umum
Pemberitahuan Kursor
Pesan Salin Data
Pesan Manajer Jendela Desktop
pesan Manajemen Perangkat
Pemberitahuan Kotak Dialog
Pesan Pertukaran Data Dinamis
Pemberitahuan Pertukaran Data Dinamis
Pemberitahuan Hook
Pesan Akselerator Keyboard
Pemberitahuan Akselerator Keyboard
Pesan Input Keyboard
Pemberitahuan Input Keyboard
Menu Pemberitahuan
Pemberitahuan Input Mouse
Beberapa Pesan Antarmuka Dokumen
Pemberitahuan Input Mentah
Pemberitahuan Bilah Gulir
Pemberitahuan Timer
Pesan Jendela
Pemberitahuan Jendela

Pesan jendela umum mencakup berbagai informasi dan permintaan, termasuk pesan untuk input mouse dan keyboard, input menu dan kotak dialog, pembuatan dan manajemen jendela, dan Dynamic Data Exchange (DDE).

Pesan Application-Defined

Aplikasi dapat membuat pesan yang akan digunakan oleh jendelanya sendiri atau untuk berkomunikasi dengan jendela dalam proses lain. Jika aplikasi membuat pesannya sendiri, prosedur jendela yang menerimanya harus menafsirkan pesan dan memberikan pemrosesan yang sesuai.

Nilai pengidentifikasi pesan digunakan sebagai berikut:

  • Sistem mencadangkan nilai pengidentifikasi pesan dalam rentang 0x0000 melalui 0x03FF (nilai WM_USER – 1) untuk pesan yang ditentukan sistem. Aplikasi tidak dapat menggunakan nilai-nilai ini untuk pesan privat.
  • Nilai dalam rentang 0x0400 (nilai WM_USER) melalui 0x7FFF tersedia untuk pengidentifikasi pesan untuk kelas jendela privat.
  • Jika aplikasi Anda ditandai versi 4.0, Anda dapat menggunakan nilai pengidentifikasi pesan dalam rentang 0x8000 (WM_APP) melalui 0xBFFF untuk pesan privat.
  • Sistem mengembalikan pengidentifikasi pesan dalam rentang 0xC000 melalui 0xFFFF saat aplikasi memanggil fungsi RegisterWindowMessage untuk mendaftarkan pesan. Pengidentifikasi pesan yang dikembalikan oleh fungsi ini dijamin unik di seluruh sistem. Penggunaan fungsi ini mencegah konflik yang dapat muncul jika aplikasi lain menggunakan pengidentifikasi pesan yang sama untuk tujuan yang berbeda.

Perutean pesan

Sistem ini menggunakan dua metode untuk merutekan pesan ke prosedur jendela: memposting pesan ke antrean first-in dan first-out yang disebut antrean pesan, objek memori yang ditentukan sistem yang untuk sementara menyimpan pesan, dan mengirim pesan langsung ke prosedur jendela.

Pesan yang diposting ke antrean pesan disebut pesan antrean. Ini terutama hasil input pengguna yang dimasukkan melalui mouse atau keyboard, seperti pesan WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_KEYDOWN, dan WM_CHAR . Pesan antrean lainnya termasuk timer, cat, dan pesan keluar: WM_TIMER, WM_PAINT, dan WM_QUIT. Sebagian besar pesan lain, yang dikirim langsung ke prosedur jendela, disebut pesan yang tidak diantrekan.

Pesan Antrean

Sistem dapat menampilkan sejumlah jendela pada satu waktu. Untuk merutekan input mouse dan keyboard ke jendela yang sesuai, sistem menggunakan antrean pesan.

Sistem mempertahankan antrean pesan sistem tunggal dan satu antrean pesan khusus utas untuk setiap utas GUI. Untuk menghindari overhead pembuatan antrean pesan untuk utas non-GUI, semua utas dibuat awalnya tanpa antrean pesan. Sistem membuat antrean pesan khusus utas hanya ketika utas melakukan panggilan pertamanya ke salah satu fungsi pengguna tertentu; tidak ada panggilan fungsi GUI yang menghasilkan pembuatan antrean pesan.

Setiap kali pengguna menggerakkan mouse, mengklik tombol mouse, atau jenis pada keyboard, driver perangkat untuk mouse atau keyboard mengonversi input menjadi pesan dan menempatkannya dalam antrean pesan sistem. Sistem menghapus pesan, satu per satu, dari antrean pesan sistem, memeriksanya untuk menentukan jendela tujuan, lalu mempostingnya ke antrean pesan utas yang membuat jendela tujuan. Antrean pesan utas menerima semua pesan mouse dan keyboard untuk jendela yang dibuat oleh utas. Utas menghapus pesan dari antreannya dan mengarahkan sistem untuk mengirimnya ke prosedur jendela yang sesuai untuk diproses.

Dengan pengecualian pesan WM_PAINT , pesan WM_TIMER , dan pesan WM_QUIT , sistem selalu memposting pesan di akhir antrean pesan. Ini memastikan bahwa jendela menerima pesan inputnya dalam urutan first in, first out (FIFO) yang tepat. Pesan WM_PAINT , pesan WM_TIMER , dan pesan WM_QUIT , namun, disimpan dalam antrean dan diteruskan ke prosedur jendela hanya ketika antrean tidak berisi pesan lain. Selain itu, beberapa pesan WM_PAINT untuk jendela yang sama digabungkan ke dalam satu pesan WM_PAINT , mengonsolidasikan semua bagian area klien yang tidak valid ke dalam satu area. Menggabungkan pesan WM_PAINT mengurangi berapa kali jendela harus menggambar ulang konten area kliennya.

Sistem memposting pesan ke antrean pesan utas dengan mengisi struktur MSG lalu menyalinnya ke antrean pesan. Informasi dalam MSG meliputi: handel jendela tempat pesan dimaksudkan, pengidentifikasi pesan, dua parameter pesan, waktu pesan diposting, dan posisi kursor mouse. Utas dapat memposting pesan ke antrean pesannya sendiri atau ke antrean utas lain dengan menggunakan fungsi PostMessage atau PostThreadMessage .

Aplikasi dapat menghapus pesan dari antreannya dengan menggunakan fungsi GetMessage . Untuk memeriksa pesan tanpa menghapusnya dari antreannya, aplikasi dapat menggunakan fungsi PeekMessage . Fungsi ini mengisi MSG dengan informasi tentang pesan.

Setelah menghapus pesan dari antreannya, aplikasi dapat menggunakan fungsi DispatchMessage untuk mengarahkan sistem untuk mengirim pesan ke prosedur jendela untuk diproses. DispatchMessage mengambil pointer ke MSG yang diisi oleh panggilan sebelumnya ke fungsi GetMessage atau PeekMessage . DispatchMessage meneruskan handel jendela, pengidentifikasi pesan, dan dua parameter pesan ke prosedur jendela, tetapi tidak melewati waktu pesan diposting atau posisi kursor mouse. Aplikasi dapat mengambil informasi ini dengan memanggil fungsi GetMessageTime dan GetMessagePos saat memproses pesan.

Utas dapat menggunakan fungsi WaitMessage untuk menghasilkan kontrol ke utas lain ketika tidak memiliki pesan dalam antrean pesannya. Fungsi menangguhkan utas dan tidak kembali sampai pesan baru ditempatkan dalam antrean pesan utas.

Anda dapat memanggil fungsi SetMessageExtraInfo untuk mengaitkan nilai dengan antrean pesan utas saat ini. Kemudian panggil fungsi GetMessageExtraInfo untuk mendapatkan nilai yang terkait dengan pesan terakhir yang diambil oleh fungsi GetMessage atau PeekMessage .

Pesan Yang Tidak Diantrekan

Pesan yang tidak diantrekan dikirim segera ke prosedur jendela tujuan, melewati antrean pesan sistem dan antrean pesan utas. Sistem biasanya mengirim pesan tanpa antrean untuk memberi tahu jendela peristiwa yang memengaruhinya. Misalnya, ketika pengguna mengaktifkan jendela aplikasi baru, sistem mengirimkan serangkaian pesan ke jendela, termasuk WM_ACTIVATE, WM_SETFOCUS, dan WM_SETCURSOR. Pesan-pesan ini memberi tahu jendela bahwa jendela telah diaktifkan, bahwa input keyboard diarahkan ke jendela, dan bahwa kursor mouse telah dipindahkan di dalam batas jendela. Pesan yang tidak diantrekan juga dapat mengakibatkan ketika aplikasi memanggil fungsi sistem tertentu. Misalnya, sistem mengirim pesan WM_WINDOWPOSCHANGED setelah aplikasi menggunakan fungsi SetWindowPos untuk memindahkan jendela.

Beberapa fungsi yang mengirim pesan tanpa antrean adalah BroadcastSystemMessage, BroadcastSystemMessageEx, SendMessage, SendMessageTimeout, dan SendNotifyMessage.

Penanganan Pesan

Aplikasi harus menghapus dan memproses pesan yang diposting ke antrean pesan utasnya. Aplikasi satu utas biasanya menggunakan perulangan pesan dalam fungsi WinMain-nya untuk menghapus dan mengirim pesan ke prosedur jendela yang sesuai untuk diproses. Aplikasi dengan beberapa utas dapat menyertakan perulangan pesan di setiap utas yang membuat jendela. Bagian berikut menjelaskan cara kerja perulangan pesan dan menjelaskan peran prosedur jendela:

Perulangan Pesan

Perulangan pesan sederhana terdiri dari satu panggilan fungsi ke masing-masing dari tiga fungsi ini: GetMessage, TranslateMessage, dan DispatchMessage. Perhatikan bahwa jika ada kesalahan, GetMessage mengembalikan -1, sehingga kebutuhan untuk pengujian khusus.

MSG msg;
BOOL bRet;

while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{ 
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    }
}

Fungsi GetMessage mengambil pesan dari antrean dan menyalinnya ke struktur jenis MSG. Ini mengembalikan nilai bukan nol, kecuali jika menemukan pesan WM_QUIT , dalam hal ini mengembalikan FALSE dan mengakhiri perulangan. Dalam aplikasi satu utas, mengakhiri perulangan pesan sering kali merupakan langkah pertama dalam menutup aplikasi. Aplikasi dapat mengakhiri perulangannya sendiri dengan menggunakan fungsi PostQuitMessage , biasanya sebagai respons terhadap pesan WM_DESTROY dalam prosedur jendela jendela jendela utama aplikasi.

Jika Anda menentukan handel jendela sebagai parameter kedua GetMessage, hanya pesan untuk jendela yang ditentukan yang diambil dari antrean. GetMessage juga dapat memfilter pesan dalam antrean, hanya mengambil pesan yang termasuk dalam rentang tertentu. Untuk informasi selengkapnya tentang pemfilteran pesan, lihat Pemfilteran Pesan.

Perulangan pesan utas harus menyertakan TranslateMessage jika utas menerima input karakter dari keyboard. Sistem menghasilkan pesan kunci virtual (WM_KEYDOWN dan WM_KEYUP) setiap kali pengguna menekan tombol. Pesan kunci virtual berisi kode kunci virtual yang mengidentifikasi tombol mana yang ditekan, tetapi bukan nilai karakternya. Untuk mengambil nilai ini, perulangan pesan harus berisi TranslateMessage, yang menerjemahkan pesan kunci virtual ke dalam pesan karakter (WM_CHAR) dan menempatkannya kembali ke dalam antrean pesan aplikasi. Pesan karakter kemudian dapat dihapus pada perulangan berikutnya dari perulangan pesan dan dikirim ke prosedur jendela.

Fungsi DispatchMessage mengirimkan pesan ke prosedur jendela yang terkait dengan handel jendela yang ditentukan dalam struktur MSG . Jika handel jendela HWND_TOPMOST, DispatchMessage mengirimkan pesan ke prosedur jendela semua jendela tingkat atas dalam sistem. Jika handel jendela NULL, DispatchMessage tidak melakukan apa pun dengan pesan.

Utas utama aplikasi memulai perulangan pesannya setelah menginisialisasi aplikasi dan membuat setidaknya satu jendela. Setelah dimulai, perulangan pesan terus mengambil pesan dari antrean pesan utas dan untuk mengirimkannya ke jendela yang sesuai. Perulangan pesan berakhir saat fungsi GetMessage menghapus pesan WM_QUIT dari antrean pesan.

Hanya satu perulangan pesan yang diperlukan untuk antrean pesan, bahkan jika aplikasi berisi banyak jendela. DispatchMessage selalu mengirimkan pesan ke jendela yang tepat; ini karena setiap pesan dalam antrean adalah struktur MSG yang berisi handel jendela tempat pesan berada.

Anda dapat memodifikasi perulangan pesan dengan berbagai cara. Misalnya, Anda dapat mengambil pesan dari antrean tanpa mengirimkannya ke jendela. Ini berguna untuk aplikasi yang memposting pesan yang tidak menentukan jendela. Anda juga dapat mengarahkan GetMessage untuk mencari pesan tertentu, meninggalkan pesan lain dalam antrean. Ini berguna jika Anda harus melewati urutan ANTREAN pesan FIFO yang biasa untuk sementara waktu.

Aplikasi yang menggunakan tombol akselerator harus dapat menerjemahkan pesan keyboard ke dalam pesan perintah. Untuk melakukan ini, perulangan pesan aplikasi harus menyertakan panggilan ke fungsi TranslateAccelerator . Untuk informasi selengkapnya tentang tombol akselerator, lihat Akselerator Keyboard.

Jika utas menggunakan kotak dialog tanpa mode, perulangan pesan harus menyertakan fungsi IsDialogMessage sehingga kotak dialog dapat menerima input keyboard.

Prosedur Jendela

Prosedur jendela adalah fungsi yang menerima dan memproses semua pesan yang dikirim ke jendela. Setiap kelas jendela memiliki prosedur jendela, dan setiap jendela yang dibuat dengan kelas tersebut menggunakan prosedur jendela yang sama untuk merespons pesan.

Sistem mengirim pesan ke prosedur jendela dengan meneruskan data pesan sebagai argumen ke prosedur. Prosedur jendela kemudian melakukan tindakan yang sesuai untuk pesan; ini memeriksa pengidentifikasi pesan dan, saat memproses pesan, menggunakan informasi yang ditentukan oleh parameter pesan.

Prosedur jendela biasanya tidak mengabaikan pesan. Jika tidak memproses pesan, pesan harus mengirim pesan kembali ke sistem untuk pemrosesan default. Prosedur jendela melakukan ini dengan memanggil fungsi DefWindowProc , yang melakukan tindakan default dan mengembalikan hasil pesan. Prosedur jendela kemudian harus mengembalikan nilai ini sebagai hasil pesannya sendiri. Sebagian besar prosedur jendela hanya memproses beberapa pesan dan meneruskan yang lain ke sistem dengan memanggil DefWindowProc.

Karena prosedur jendela dibagikan oleh semua jendela milik kelas yang sama, prosedur ini dapat memproses pesan untuk beberapa jendela yang berbeda. Untuk mengidentifikasi jendela tertentu yang terpengaruh oleh pesan, prosedur jendela dapat memeriksa handel jendela yang diteruskan dengan pesan. Untuk informasi selengkapnya tentang prosedur jendela, lihat Prosedur Jendela.

Pemfilteran Pesan

Aplikasi dapat memilih pesan tertentu untuk diambil dari antrean pesan (saat mengabaikan pesan lain) dengan menggunakan fungsi GetMessage atau PeekMessage untuk menentukan filter pesan. Filter adalah rentang pengidentifikasi pesan (ditentukan oleh pengidentifikasi pertama dan terakhir), handel jendela, atau keduanya. GetMessage dan PeekMessage menggunakan filter pesan untuk memilih pesan mana yang akan diambil dari antrean. Pemfilteran pesan berguna jika aplikasi harus mencari antrean pesan untuk pesan yang telah tiba nanti dalam antrean. Ini juga berguna jika aplikasi harus memproses pesan input (perangkat keras) sebelum memproses pesan yang diposting.

Konstanta WM_KEYFIRST dan WM_KEYLAST dapat digunakan sebagai nilai filter untuk mengambil semua pesan keyboard; konstanta WM_MOUSEFIRST dan WM_MOUSELAST dapat digunakan untuk mengambil semua pesan mouse.

Aplikasi apa pun yang memfilter pesan harus memastikan bahwa pesan yang memenuhi filter pesan dapat diposting. Misalnya, jika aplikasi memfilter pesan WM_CHAR di jendela yang tidak menerima input keyboard, fungsi GetMessage tidak kembali. Ini secara efektif "menggantung" aplikasi.

Memposting dan Mengirim Pesan

Aplikasi apa pun dapat memposting dan mengirim pesan. Seperti sistem, aplikasi memposting pesan dengan menyalinnya ke antrean pesan dan mengirim pesan dengan meneruskan data pesan sebagai argumen ke prosedur jendela. Untuk memposting pesan, aplikasi menggunakan fungsi PostMessage . Aplikasi dapat mengirim pesan dengan memanggil fungsi SendMessage, BroadcastSystemMessage, SendMessageCallback, SendMessageTimeout, SendNotifyMessage, atau SendDlgItemMessage .

Memposting Pesan

Aplikasi biasanya memposting pesan untuk memberi tahu jendela tertentu untuk melakukan tugas. PostMessage membuat struktur MSG untuk pesan dan menyalin pesan ke antrean pesan. Perulangan pesan aplikasi akhirnya mengambil pesan dan mengirimkannya ke prosedur jendela yang sesuai.

Aplikasi dapat memposting pesan tanpa menentukan jendela. Jika aplikasi menyediakan handel jendela NULL saat memanggil PostMessage, pesan diposting ke antrean yang terkait dengan utas saat ini. Karena tidak ada handel jendela yang ditentukan, aplikasi harus memproses pesan dalam perulangan pesan. Ini adalah salah satu cara untuk membuat pesan yang berlaku untuk seluruh aplikasi, bukan ke jendela tertentu.

Terkadang, Anda mungkin ingin memposting pesan ke semua jendela tingkat atas dalam sistem. Aplikasi dapat memposting pesan ke semua jendela tingkat atas dengan memanggil PostMessage dan menentukan HWND_TOPMOST dalam parameter hwnd .

Kesalahan pemrograman umum adalah mengasumsikan bahwa fungsi PostMessage selalu memposting pesan. Ini tidak benar ketika antrean pesan penuh. Aplikasi harus memeriksa nilai pengembalian fungsi PostMessage untuk menentukan apakah pesan telah diposting dan, jika belum, repost.

Mengirim Pesan

Aplikasi biasanya mengirim pesan untuk memberi tahu prosedur jendela untuk segera melakukan tugas. Fungsi SendMessage mengirimkan pesan ke prosedur jendela yang sesuai dengan jendela yang diberikan. Fungsi menunggu hingga prosedur jendela selesai diproses lalu mengembalikan hasil pesan. Jendela induk dan anak sering berkomunikasi dengan mengirim pesan satu sama lain. Misalnya, jendela induk yang memiliki kontrol edit karena jendela turunannya dapat mengatur teks kontrol dengan mengirim pesan ke dalamnya. Kontrol dapat memberi tahu jendela induk tentang perubahan pada teks yang dilakukan oleh pengguna dengan mengirim pesan kembali ke induk.

Fungsi SendMessageCallback juga mengirim pesan ke prosedur jendela yang sesuai dengan jendela yang diberikan. Namun, fungsi ini segera kembali. Setelah prosedur jendela memproses pesan, sistem memanggil fungsi panggilan balik yang ditentukan. Untuk informasi selengkapnya tentang fungsi panggilan balik, lihat fungsi SendAsyncProc .

Terkadang, Anda mungkin ingin mengirim pesan ke semua jendela tingkat atas dalam sistem. Misalnya, jika aplikasi mengubah waktu sistem, aplikasi harus memberi tahu semua jendela tingkat atas tentang perubahan dengan mengirim pesan WM_TIMECHANGE . Aplikasi dapat mengirim pesan ke semua jendela tingkat atas dengan memanggil SendMessage dan menentukan HWND_TOPMOST dalam parameter hwnd . Anda juga dapat menyiarkan pesan ke semua aplikasi dengan memanggil fungsi BroadcastSystemMessage dan menentukan BSM_APPLICATIONS dalam parameter lpdwRecipients .

Dengan menggunakan fungsi InSendMessage atau InSendMessageEx , prosedur jendela dapat menentukan apakah sedang memproses pesan yang dikirim oleh utas lain. Kemampuan ini berguna ketika pemrosesan pesan tergantung pada asal pesan.

Kebuntuan Pesan

Utas yang memanggil fungsi SendMessage untuk mengirim pesan ke utas lain tidak dapat melanjutkan eksekusi hingga prosedur jendela yang menerima pesan kembali. Jika utas penerima menghasilkan kontrol saat memproses pesan, utas pengirim tidak dapat terus dieksekusi, karena menunggu SendMessage kembali. Jika utas penerima dilampirkan ke antrean yang sama dengan pengirim, itu dapat menyebabkan kebuntuan aplikasi terjadi. (Perhatikan bahwa kait jurnal melampirkan utas ke antrean yang sama.)

Perhatikan bahwa utas penerima tidak perlu menghasilkan kontrol secara eksplisit; memanggil salah satu fungsi berikut dapat menyebabkan utas menghasilkan kontrol secara implisit.

Untuk menghindari potensi kebuntuan dalam aplikasi Anda, pertimbangkan untuk menggunakan fungsi SendNotifyMessage atau SendMessageTimeout . Jika tidak, prosedur jendela dapat menentukan apakah pesan yang diterimanya dikirim oleh utas lain dengan memanggil fungsi InSendMessage atau InSendMessageEx . Sebelum memanggil salah satu fungsi dalam daftar sebelumnya saat memproses pesan, prosedur jendela harus terlebih dahulu memanggil InSendMessage atau InSendMessageEx. Jika fungsi ini mengembalikan TRUE, prosedur jendela harus memanggil fungsi ReplyMessage sebelum fungsi apa pun yang menyebabkan utas menghasilkan kontrol.

Menyiarkan Pesan

Setiap pesan terdiri dari pengidentifikasi pesan dan dua parameter, wParam dan lParam. Pengidentifikasi pesan adalah nilai unik yang menentukan tujuan pesan. Parameter memberikan informasi tambahan yang khusus untuk pesan, tetapi parameter wParam umumnya adalah nilai jenis yang menyediakan informasi lebih lanjut tentang pesan.

Siaran pesan hanyalah pengiriman pesan ke beberapa penerima dalam sistem. Untuk menyiarkan pesan dari aplikasi, gunakan fungsi BroadcastSystemMessage , yang menentukan penerima pesan. Daripada menentukan penerima individual, Anda harus menentukan satu atau beberapa jenis penerima. Jenis-jenis ini adalah aplikasi, driver yang dapat diinstal, driver jaringan, dan driver perangkat tingkat sistem. Sistem mengirim pesan siaran ke semua anggota dari setiap jenis yang ditentukan.

Sistem biasanya menyiarkan pesan sebagai respons terhadap perubahan yang terjadi dalam driver perangkat tingkat sistem atau komponen terkait. Driver atau komponen terkait menyiarkan pesan ke aplikasi dan komponen lain untuk memberi tahu mereka tentang perubahan tersebut. Misalnya, komponen yang bertanggung jawab atas disk drive menyiarkan pesan setiap kali driver perangkat untuk disk drive floppy mendeteksi perubahan media seperti ketika pengguna memasukkan disk di drive.

Sistem menyiarkan pesan kepada penerima dalam urutan ini: driver perangkat tingkat sistem, driver jaringan, driver yang dapat diinstal, dan aplikasi. Ini berarti bahwa driver perangkat tingkat sistem, jika dipilih sebagai penerima, selalu mendapatkan kesempatan pertama untuk merespons pesan. Dalam jenis penerima tertentu, tidak ada driver yang dijamin menerima pesan tertentu sebelum driver lain. Ini berarti bahwa pesan yang ditujukan untuk driver tertentu harus memiliki pengidentifikasi pesan yang unik secara global sehingga tidak ada driver lain yang secara tidak sengaja memprosesnya.

Anda juga dapat menyiarkan pesan ke semua jendela tingkat atas dengan menentukan HWND_BROADCAST di fungsi SendMessage, SendMessageCallback, SendMessageTimeout, atau SendNotifyMessage .

Aplikasi menerima pesan melalui prosedur jendela jendela tingkat atasnya. Pesan tidak dikirim ke jendela anak. Layanan dapat menerima pesan melalui prosedur jendela atau penangan kontrol layanan mereka.

Catatan

Driver perangkat tingkat sistem menggunakan fungsi tingkat sistem terkait untuk menyiarkan pesan sistem.

Pesan Kueri

Anda dapat membuat pesan kustom Anda sendiri dan menggunakannya untuk mengoordinasikan aktivitas antara aplikasi Anda dan komponen lain dalam sistem. Ini sangat berguna jika Anda telah membuat driver yang dapat diinstal sendiri atau driver perangkat tingkat sistem. Pesan kustom Anda dapat membawa informasi ke dan dari driver Anda dan aplikasi yang menggunakan driver.

Untuk melakukan polling penerima izin untuk melakukan tindakan tertentu, gunakan pesan kueri. Anda dapat membuat pesan kueri Anda sendiri dengan mengatur nilai BSF_QUERY dalam parameter dwFlags saat memanggil BroadcastSystemMessage. Setiap penerima pesan kueri harus mengembalikan TRUE agar fungsi dapat mengirim pesan ke penerima berikutnya. Jika ada penerima yang mengembalikan BROADCAST_QUERY_DENY, siaran segera berakhir dan fungsi mengembalikan nol.