對於windows程式設計,這裡有幾個關鍵詞需要注意:訊息,訊息迴圈,視窗過程。
所謂的Windows訊息傳遞機制就類似於生活中的物流公司。當寄件人(例如滑鼠、鍵盤)將包裹(訊息)交給物流公司(Windows系統)時,物流公司(Windows系統)會進行整理並且派發(整理及派發主要由訊息迴圈完成),交給相應的快遞員(視窗過程)來處理。快遞員(視窗過程)拿到包裹(訊息)後則有多種方式來處理,如立馬交給收件者,等一天交給收件者,或轉交給其他快遞派發,這就需要在視窗過程中用swich/case來區分。
訊息迴圈:
當初始化完成後,WinMain主函數就進入訊息迴圈:
While(GetMessage(&msg,...)){TranslateMessage(&msg);//轉換鍵盤訊息DispatchMessage(&msg);//指派訊息}
視窗過程:
LRESULT CALLBACK WndProc(...){...switch( msg ){case 1:...case 2:...Default:...}return 0;}
下面以兩個問題的方式進行具體概要。
問題1:訊息有哪幾種分類方法?
(1) 隊列訊息和非隊列訊息
隊列訊息會被送到系統訊息佇列,然後到線程訊息佇列。Windows維護一個系統訊息佇列,每個GUI線程也有一個線程訊息佇列。其中包括鍵盤滑鼠訊息,WM_PAINT、WM_TIMER、WM_QUIT。
這些隊列訊息以外的訊息絕大多數都是非隊列訊息。
此處注意:訊息佇列中放置的訊息是以MSG結構的形式存在,MSG包括:視窗控制代碼、訊息標識、訊息的兩個參數(WPARAM和LPARAM)、訊息發送(POST)的時間以及滑鼠的位置。此外,可以利用::GetMessage函數和::PeekMessage函數來儲存獲得的訊息資訊。
非隊列訊息直接送給目的視窗過程。
(2) 系統訊息和應用程式訊息
系統訊息ID範圍 0X8000~0XBFFF
應用程式消ID範圍0XC000~0XFFFF
為了應用程式訊息的ID唯一性,可以使用::RegisterWindowMessage來得到特定的ID。
問題2:訊息是如何進行傳遞、接收、處理的?
Windows應用程式的輸入由Windows系統以訊息的形式發送給應用程式的視窗,這些視窗通過視窗過程來接收和處理訊息,然後把控制返還給Windows。
此處注意:非隊列訊息直接送給目的視窗的視窗過程,隊列訊息由::DispatchMessage派發給目的視窗的視窗過程。視窗過程被調用時接收四個參數:視窗控制代碼、訊息標識、兩個32位的訊息參數。在視窗過程裡,用switch/case分支處理語句來識別和處理訊息。
每個GDI應用程式在主視窗建立之後,都會進入訊息迴圈,接受使用者輸入、解釋和處理訊息。訊息迴圈從訊息佇列中得到訊息,如果不是快速鍵訊息或對話方塊訊息,就進行訊息轉換和派發,讓目的視窗的視窗過程來處理。當得到訊息WM_QUIT,或者::GetMessage出錯時,退出訊息迴圈。