亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

windows消息和消息隊列實(shí)例詳解

 更新時間:2014年10月24日 11:50:53   投稿:shichen2014  
這篇文章主要介紹了windows消息和消息隊列實(shí)例詳解,詳細(xì)講述了Windows的消息機(jī)制與原理,對于深入理解和學(xué)習(xí)Windows應(yīng)用程序設(shè)計有不錯的借鑒價值,需要的朋友可以參考下

本文詳細(xì)講述了windows消息和消息隊列的原理與應(yīng)用方法。分享給大家供大家參考。具體分析如下:

與基于MS - DOS的應(yīng)用程序不同,Windows的應(yīng)用程序是事件(消息)驅(qū)動的。它們不會顯式地調(diào)用函數(shù)(如C運(yùn)行時庫調(diào)用)來獲取輸入,而是等待windows向它們傳遞輸入。 windows系統(tǒng)把應(yīng)用程序的輸入事件傳遞給各個窗口,每個窗口有一個函數(shù),稱為窗口消息處理函數(shù)。窗口消息處理函數(shù)處理各種用戶輸入,處理完成后再將控制權(quán)交還給系統(tǒng)。窗口消息處理函數(shù)一般是在注冊一個窗口的時候指定的。你可以從典型的SDK程序中窗口消息處理函數(shù)是怎么聲明和實(shí)現(xiàn)的。

對于Windows XP系統(tǒng):如果頂層窗口停止響應(yīng)消息超過幾秒鐘,系統(tǒng)會認(rèn)為窗口無回應(yīng)。在這種情況下,系統(tǒng)將隱藏這個窗口,然后生成一個影子(ghost)窗口覆蓋在它上面。這個影子窗口具有著相同的Z軸順序,位置,大小,顯示屬性。影子窗口允許用戶將其移動,調(diào)整大小,甚至關(guān)閉(關(guān)閉的是停止響應(yīng)的window)。此時只有這幾個動作是被允許的,在調(diào)試模式下,系統(tǒng)不會生成影子窗口。

本節(jié)討論以下主題:

Windows消息

 1.  消息類型

 2.  消息傳遞

 3.  消息處理

 4.  消息過濾

 5.  post message和send message

 6.  消息死鎖

 7.  廣播消息

 8.  查詢消息

現(xiàn)分述如下:

1. Windows消息

windows通過消息的形式向窗口傳遞用戶輸入。消息可以由系統(tǒng)和應(yīng)用程序生成。該系統(tǒng)會為每個輸入事件產(chǎn)生相應(yīng)的消息,

例如,用戶點(diǎn)擊鼠標(biāo),移動鼠標(biāo)或滾動條,或是應(yīng)用程序改變了系統(tǒng)的某些屬性,比如說系統(tǒng)更改了字體資源,改變了某個窗口的

大小。 不僅如此,應(yīng)用程序可以生成消息,通告發(fā)送消息指定它的窗體去執(zhí)行某些任務(wù)或者是與其他的應(yīng)用程序交互。

windows系統(tǒng)將消息發(fā)送到一個窗口消息處理函數(shù)時傳遞四個參數(shù):窗口句柄,消息標(biāo)識符,兩個DWORD值(消息參數(shù))。

窗口句柄標(biāo)識了該消息的目的窗口。windows使用它來確定是哪個窗口的的窗口消息處理函數(shù)收到該消息。

一個消息標(biāo)識符是一個有名字的常量,用來表明消息的意義。當(dāng)一個窗口處理函數(shù)收到一條消息,它根據(jù)判斷消息標(biāo)識符來決定如何處理該消息,例如,消息標(biāo)識符WM_PAINT消息告訴窗口程序窗口的客戶區(qū)已發(fā)生變化,必須重繪。 消息參數(shù)(DWORD值)指定傳遞的數(shù)據(jù)或是數(shù)據(jù)的地址。消息參數(shù)可以是一個整型值,一個指針值。也可以為NULL。

一個窗口過程必須根據(jù)消息標(biāo)識符來確定如何解釋消息參數(shù)。

2. windows 消息類型

本節(jié)描述消息的兩種類型:

(1) 系統(tǒng)定義的消息

(2) 應(yīng)用程序定義的消息

系統(tǒng)定義的消息

操作系統(tǒng)向應(yīng)用程序發(fā)送消息來和應(yīng)用程序通訊。操作系統(tǒng)通過消息控制應(yīng)用程序的運(yùn)行,向應(yīng)用程序傳遞用戶輸入以及一些其他有用的信息。

應(yīng)用程序也可以發(fā)送系統(tǒng)定義的消息,應(yīng)用程序通過這些消息去控制使用注冊窗口類創(chuàng)建的控件的窗口的運(yùn)行。

每個系統(tǒng)定義的消息都有一個唯一的消息標(biāo)識符和相應(yīng)的符號常量(在windows SDK的頭文件里定義)。符號常量通常會表明系統(tǒng)定義的消息所屬的類別。不同的前綴表明不同的類別。一下是常見的分類:

    Prefix Message category

    WM        General window(一般的窗口)

    ABM        Application desktop toolbar (應(yīng)用程序桌面工具條)

    BM        Button control (按鈕控件)

    CB        Combo box control (組合框控件)

    CBEM Extended combo box control(擴(kuò)展的組合框控件)

    CDM        Common dialog box (普通的對話框)

    DBT        Device (設(shè)備)

    DL        Drag list box (下拉列表)

    DM        Default push button control (默認(rèn)按鈕控件)

    DTM        Date and time picker control(日期和時間選擇控件)

    EM        Edit control (編輯控件)

    HDM        Header control (表頭控件)

    HKM        Hot key control (熱鍵控件)

    IPM        IP address control (IP地址控件)

    LB        List box control  (列表框控件)

    LVM        List view control (列表視圖控件)

    MCM        Month calendar control (數(shù)學(xué)日歷控件)

    PBM        Progress bar (進(jìn)度條控件)

    PGM        Pager control ()

    PSM        Property sheet (屬性頁)

    RB        Rebar control (分隔條控件)

    SB        Status bar window (狀態(tài)條控件)

    SBM        Scroll bar control (滾動條控件)

    STM        Static control (靜態(tài)控件)

    TB        Toolbar (工具條)

    TBM        Trackbar (跟蹤欄)

    TCM        Tab control (選項(xiàng)卡控件)

    TTM        Tooltip control ()

    TVM        Tree-view control ()

    UDM        Up-down control ()

應(yīng)用程序可以通過創(chuàng)建自定義的消息,用來和自己的窗口和其他進(jìn)程通訊。如果應(yīng)用程序創(chuàng)建了自己的消息,窗口處理函數(shù)可以解析這些信息,并作出相應(yīng)的處理。

消息標(biāo)識符值的取值范圍:

該系統(tǒng)保留了一個消息范圍,從0x0000到0x03FF(0x03FF等于WM_USER -1)范圍. 這個范圍內(nèi)的值為系統(tǒng)定義的消息。應(yīng)用程序不能使用這些值作為自己的自定義消息。

從0x0400(數(shù)值WM_USER)到0x7FFF的值是為應(yīng)用程序保留的。應(yīng)用程序可以使用這個范圍內(nèi)的值來定義自己的消息。

如果你的操作系用的版本(windows version)主版本為4.0版,你還可以使用0x8000(WM_APP)到0xBFF之間的值來定義自己的消息。

除此之外,應(yīng)用程序還可以調(diào)用RegisterWindowMessage函數(shù)注冊一個消息時,操作系統(tǒng)會返回一個介于0xC000和0xFFFF之間的一個消息標(biāo)識符。并且保證這個返回值是系統(tǒng)唯一的。因此,可以避免和其他應(yīng)用程序使用的消息相沖突。

3. 消息派發(fā)

windows使用兩種方法將消派發(fā)到一個窗口消息處理函數(shù):一是將消息放到消息隊列(先進(jìn)先出隊列),二是不放到消息隊列,直接發(fā)送到窗口消息處理函數(shù),讓窗口處理函數(shù)來處理消息。

派發(fā)到消息隊列的消息被稱為排隊消息(Queued messages)。它們主要是用戶輸入事件,比如說鼠標(biāo)或鍵盤消息盤,有WM_MOUSEMOVE消息,WM_LBUTTONDOWN,WM_KEYDOWN,和WM_CHAR消息。還有一些其他的,包括WM_TIMER,WM_PAINT,以及WM_QUIT。大多數(shù)其他的消息息,這是直接發(fā)送到窗口過程,被稱為非隊列消息(non queued messages)。

(1) 隊列(Queued)消息

windows可同時顯示任意數(shù)量的窗口。此時,系統(tǒng)使用消息隊列來將鍵盤和鼠標(biāo)事件正確的派發(fā)到正確的窗口。

windows維護(hù)著一個系統(tǒng)消息隊列,以及分別為每個GUI線程維護(hù)一個各自的線程消息隊列。為了避免非GUI線程的創(chuàng)建線程消息隊列的開銷,所有線程創(chuàng)建初始化時,均不創(chuàng)建消息隊列。只有當(dāng)線程第一次調(diào)用GDI函數(shù)時,系統(tǒng)才會為線程創(chuàng)建消息隊列。所以那些非GUI線程是沒有消息隊列的。

每當(dāng)用戶移動鼠標(biāo),點(diǎn)擊按鈕或鍵盤時,鼠標(biāo)或鍵盤的設(shè)備驅(qū)動程序會將輸入轉(zhuǎn)換成消息,并將消息放在系統(tǒng)消息隊列里。刪windows會檢查自己的消息隊列,如果消息隊列不為空,則每次取出并刪除一個消息,然后確定消息的目標(biāo)窗口,然后把消息放到創(chuàng)建這個窗口的線程的線程消息隊列里。線程的消息隊列接收由線程創(chuàng)建的窗口的所有的鼠標(biāo)和鍵盤消息。然后線程會從隊列中刪除信息,并告訴系統(tǒng)把它們派發(fā)到對應(yīng)的窗口消息處理函數(shù)。

除了WM_PAINT, WM_TIMER和WM_QUIT消息以外,系統(tǒng)總是派發(fā)放在在消息隊列的末尾的消息。這將保證讓一個窗口以first-in, first-out的順序接收消息。WM_PAINT,WM_TIMER,和WM_QUIT消息,會一直被保存在隊列中,只有在隊列中沒有其他消息時才會被派發(fā)到窗口消息處理函數(shù)。此外,同一個窗口的多個WM_PAINT消息被合并成一個WM_PAINT消息,客戶區(qū)的所有無效部分也會被合并。這樣是為了減少窗口重繪客戶區(qū)的次數(shù)。

windows向線程消息隊列傳遞消息時,首先會填充一個MSG結(jié)構(gòu),然后將這個MSG結(jié)構(gòu)復(fù)制到消息隊列。MSG中的信息包括:目標(biāo)窗口,消息標(biāo)識符,兩個消息參數(shù),消息派發(fā)時的時間,鼠標(biāo)光標(biāo)位置。一個線程可以使用PostMessage或PostThreadMessage功能向自己的消息隊列或者是其他線程的消息隊列發(fā)送消息。

應(yīng)用程序可以使用GetMessage函數(shù)從自己的消息隊列中刪除消息。查看而不刪除消息,用的是PeekMessage函數(shù)。

PeekMessage函數(shù)會返回一個帶有消息信息的MSG結(jié)構(gòu)。

從消息隊列中刪除消息后,應(yīng)用程序可以使用DispatchMessage函數(shù)指示系統(tǒng)將消息發(fā)送到一個窗口消息處理函數(shù)。 DispatchMessage的參數(shù)是是前一次調(diào)用GetMessage或PeekMessage獲得的MSG結(jié)構(gòu)的指針。 DispatchMessage會傳遞窗口句柄,消息標(biāo)識符,這兩個消息參數(shù)這些信息給窗口消息處理函數(shù),它不會傳遞消息派發(fā)時間以及鼠標(biāo)光標(biāo)位置。應(yīng)用程序可以在處理消息時調(diào)用的GetMessageTime和GetMessagePos來獲得這些信息。

線程可以使用WaitMessage函數(shù),交出自己的控制權(quán),當(dāng)它的消息隊列中沒有消息時,調(diào)用WaitMessage函數(shù)會掛起線程,直到自己的消息隊列里有消息時才返回。

您可以調(diào)用SetMessageExtraInfo函數(shù)來關(guān)聯(lián)一個值給當(dāng)前線程的消息隊列。然后調(diào)用GetMessageExtraInfo函數(shù)來獲取由GetMessage或PeekMessage函數(shù)得到的最后一條消息相關(guān)聯(lián)的值。你可以去msdn上看更多的關(guān)于這幾個函數(shù)的信息。

(2) 非隊列(Nonqueued)消息

Nonqueued消息被立即送往目的地的窗口消息處理函數(shù),繞過了系統(tǒng)的消息隊列和線程消息隊列。系統(tǒng)通常會發(fā)送nonqueued消息,來通知那些會影響窗口的事件。例如,當(dāng)用戶激活一個新的應(yīng)用程序窗口時,系統(tǒng)會發(fā)送一些列消息到窗口,包括WM_ACTIVATE,WM_SETFOCUS,WM_SETCURSOR。這些消息通知窗口被激活,鍵盤輸入被定向到窗口,并且鼠標(biāo)光標(biāo)也移到窗口的邊界內(nèi)。

Nonqueued消息也有可能來源于應(yīng)用程序調(diào)用系統(tǒng)函數(shù)。例如,系統(tǒng)調(diào)用SetWindowPos函數(shù)移動一個窗口后會發(fā)送WM_WINDOWPOSCHANGED消息。 一些函數(shù)也發(fā)送nonqueued消息, 有BroadcastSystemMessage,BroadcastSystemMessageEx,SendMessage,SendMessageTimeout,和SendNotifyMessage。 關(guān)于這些函數(shù)的詳細(xì)信息,你可以查閱MSDN。

消息處理

應(yīng)用程序必須刪除并處理發(fā)送到它的線程消息隊列的消息。單線程應(yīng)用程序通常在它的WinMain函數(shù)的消息循環(huán),刪除和分發(fā)消息到適當(dāng)?shù)拇翱谶M(jìn)行處理。多線程應(yīng)用程序可以在每一個線程創(chuàng)建一個窗口的消息循環(huán)。以下章節(jié)描述了一個消息

循環(huán)如何工作,并講述窗口消息處理函數(shù)的作用:

(1)消息循環(huán)

(2)窗口處理函數(shù)

消息循環(huán)

一個簡單的消息循環(huán)包含調(diào)用以下三個函數(shù):GetMessage,TranslateMessage,和DispatchMessage。請注意,如果有一個錯誤,GetMessage返回-1 -因此,需要測試它的返回值,來判斷為-1的情況

代碼片段:

復(fù)制代碼 代碼如下:
...

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);
    }
}

GetMessage函數(shù)從隊列中獲取消息,并將消息內(nèi)容復(fù)制到一個MSG結(jié)構(gòu)。它返回一個非零值,除非遇到WM_QUIT消息,此種返回FALSE并結(jié)束消息循環(huán)。在一個單線程應(yīng)用程序,結(jié)束消息循環(huán)往往是在關(guān)閉應(yīng)用程序的第一步。應(yīng)用程序可以調(diào)用PostQuitMessage函數(shù)來響應(yīng)WM_DESTROY,結(jié)束消息循環(huán)。

如果您指定一個窗口句柄作為GetMessage的第二個參數(shù),那么GetMessage只獲取在消息隊列里和這個窗口有關(guān)的消息。 GetMessage也可以在隊列中篩選消息,只獲取指定范圍內(nèi)的消息。如需有關(guān)消息過濾的詳細(xì)信息,請參考消息過濾。

線程的消息循環(huán)必須包括TranslateMessage,如果線程需要接受鍵盤字符的輸入。每次用戶按下一個鍵,該系統(tǒng)產(chǎn)生相應(yīng)的虛擬鍵消息(WM_KEYDOWN和WM_KEYUP)。虛擬鍵消息包含一個虛擬鍵碼,標(biāo)識的是被按下的鍵,而不是它相關(guān)的字符值。要獲得此值,消息循環(huán)必須包含TranslateMessage,用來將虛擬鍵消息翻譯成字符消息(WM_CHAR)的并放到應(yīng)用程序的消息隊列里。經(jīng)過若干次循環(huán)后,WM_CHAR消息會被并派發(fā)到一個窗口。

DispatchMessage函數(shù)將消息發(fā)送到到與MSG結(jié)構(gòu)中的窗口句柄關(guān)聯(lián)的窗口。如果窗口句柄是HWND_TOPMOST,DispatchMessage則將消息發(fā)送到操作系統(tǒng)所有的頂層窗口。如果窗口句柄是NULL,DispatchMessage不做任何事。

一個應(yīng)用程序的主線程初始化后,系統(tǒng)就啟動應(yīng)用程序的消息循環(huán),并創(chuàng)造至少一個窗口。一旦啟動,消息循環(huán)持續(xù)從該線程的消息隊列中刪除消息,并派發(fā)他們到相應(yīng)的窗口。GetMessage函數(shù)從消息列表中獲取到WM_QUIT消息時,消息循環(huán)結(jié)束。

一個消息隊列只需要一個消息循環(huán),即使一個應(yīng)用程序包含有多個窗口。 DispatchMessage總是調(diào)度消息到正確的窗口,這是因?yàn)槊總€隊列中的消息是MSG結(jié)構(gòu),它包含著消息所屬的窗口的句柄。

您可以以多種方式來修改消息循環(huán)。例如,您可以從隊列中刪除消息,但是不派發(fā)他們。當(dāng)發(fā)送有些不帶有目的地窗口的消息時這非常有用。您也可以使用GetMessage只獲取指定的消息,這是有用的,如果你必須你暫時繞過正常的消息隊列FIFO順序。

應(yīng)用程序使用快捷鍵時,必須能夠?qū)㈡I盤消息轉(zhuǎn)換為命令消息。因此,應(yīng)用程序的消息循環(huán)必須包括TranslateAccelerator函數(shù)調(diào)用。關(guān)于快捷鍵的更多信息,請參見鍵盤加速器。

如果一個線程使用一個無模式對話框,那么消息循環(huán)必須包括IsDialogMessage函數(shù),以便該對話框可以接收鍵盤輸入。

(3)窗口消息處理函數(shù)

窗口消息函數(shù)接收和處理的所有發(fā)送到窗口的消息。每個窗口類有一個窗口消息處理函數(shù),用該類創(chuàng)建的每個窗口使用同一窗口消息處理函數(shù)。

該系統(tǒng)將消息發(fā)送到一個窗口的程序,并傳遞消息的相關(guān)信息到窗口消息處理函數(shù),窗口消息處理函數(shù)檢查消息標(biāo)識符,根據(jù)傳過來的參數(shù)識別并處理不同的消息,

一個窗口過程通常不會忽略一個消息。如果消息沒有被處理,必須被發(fā)送給系統(tǒng)默認(rèn)的窗口消息處理函數(shù),這是否通過調(diào)用DefWindowProc函數(shù),來執(zhí)行一個默認(rèn)的處理,并返回一個處理的結(jié)果。窗口程序必須然后返回該值作為自己的消息處理的結(jié)果。大多數(shù)窗口消息處理函數(shù)只處理一少部分消息,并將其他的返回給系統(tǒng)默認(rèn)的窗口消息處理函數(shù)。

因?yàn)榇翱谙⑻幚砗瘮?shù)被所有屬于同一個窗口類的窗口共享,它可以處理幾個不同的窗口的消息。要確定具體的窗口消息,窗口消息處理函數(shù)可以檢查消息結(jié)構(gòu)里的窗口句柄。

希望本文所述對大家的Windows應(yīng)用程序設(shè)計有所幫助。

相關(guān)文章

  • C語言數(shù)據(jù)結(jié)構(gòu)算法基礎(chǔ)之循環(huán)隊列示例

    C語言數(shù)據(jù)結(jié)構(gòu)算法基礎(chǔ)之循環(huán)隊列示例

    這篇文章主要為大家介紹了C語言數(shù)據(jù)結(jié)構(gòu)算法基礎(chǔ)之循環(huán)隊列,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • OpenCV實(shí)現(xiàn)圖像拼接案例

    OpenCV實(shí)現(xiàn)圖像拼接案例

    這篇文章主要介紹了OpenCV實(shí)現(xiàn)圖像拼接案例,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下
    2022-08-08
  • 使用C語言實(shí)現(xiàn)12種排序方法

    使用C語言實(shí)現(xiàn)12種排序方法

    這篇文章主要介紹了用C語言完整實(shí)現(xiàn)12種排序方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-12-12
  • C++中set/multiset容器詳解(附測試用例與結(jié)果圖)

    C++中set/multiset容器詳解(附測試用例與結(jié)果圖)

    set/multiset屬于關(guān)聯(lián)式容器,底層結(jié)構(gòu)是用二叉樹實(shí)現(xiàn),下面這篇文章主要給大家介紹了關(guān)于C++中set/multiset容器的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • 淺析C++中的函數(shù)與指針

    淺析C++中的函數(shù)與指針

    這篇文章主要介紹了淺析C++中的函數(shù)與指針,是C++入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-09-09
  • C語言中關(guān)于庫函數(shù) qsort 的模擬實(shí)現(xiàn)過程

    C語言中關(guān)于庫函數(shù) qsort 的模擬實(shí)現(xiàn)過程

    庫函數(shù)的模擬實(shí)現(xiàn)有利于我們?nèi)ド钊肓私膺@個函數(shù)內(nèi)部是怎樣實(shí)現(xiàn)的,以及學(xué)習(xí)它的算法,使我們更加了解這個函數(shù)該怎樣去使用,接下來我將詳細(xì)的介紹qsort的應(yīng)用及用法,并且用代碼模擬實(shí)現(xiàn)它們的功能
    2021-09-09
  • C++實(shí)現(xiàn)LeetCode(136.單獨(dú)的數(shù)字)

    C++實(shí)現(xiàn)LeetCode(136.單獨(dú)的數(shù)字)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(136.單獨(dú)的數(shù)字),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C++ 異常的詳細(xì)介紹

    C++ 異常的詳細(xì)介紹

    這篇文章主要介紹了C++ 異常的詳細(xì)介紹的相關(guān)資料,希望通過本文大家能夠掌握C++異常的使用方法,需要的朋友可以參考下
    2017-09-09
  • C++中的六個函數(shù)

    C++中的六個函數(shù)

    本文給大家介紹了C++中的六個函數(shù),非常不錯,具有一定的參考借鑒價值,需要的朋友參考下吧
    2018-05-05
  • C語言實(shí)現(xiàn)可保存的動態(tài)通訊錄的示例代碼

    C語言實(shí)現(xiàn)可保存的動態(tài)通訊錄的示例代碼

    這篇文章主要為大家詳細(xì)介紹了如何利用C語言實(shí)現(xiàn)一個簡單的可保存的動態(tài)通訊錄,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)C語言有一定幫助,需要的可以參考一下
    2022-07-07

最新評論