(VC)Windows 應用程序交互過程

應用程序

Windows的應用程序一般包含窗口(Window),它主要爲用戶提供一種可視化的交互方式,窗口是由線程(Thread)創建的.Windows系統通過消息機制來管理交互,消息(Message)被髮送,保存,處理,一個線程會維護自己的一套消息隊列(Message Queue),在發生輸入事件之後,Windows將事件轉換爲一個「消息」並將消息放入程序的消息隊列中.程序通過執行一塊稱之爲「消息循環」的程序代碼從消息隊列中取出消息並調用窗體的回調函數處理消息,這樣不僅保持線程間的獨佔性.而且隊列的以先進先出方式處理消息來實現異步通信.

但是一般來說不是所有的消息都是需要程序處理的.而是針對其中某些特定的消息進行處理.即程序只關心自己想關心的問題而不會多去處理其他不必要的信息.但是系統並不會知道什麼是程序所關心的消息,什麼是程序不關心的消息,所以它會把所有的消息都發送給程序.那麼程序便要從中塞選出自己想要處理的消息,然後把自己不想理會的消息過濾給系統,讓系統去幫助處理這些不需要的消息(即系統提供的默認的窗口過程函數 DefWindowProc).那麼一般程序的窗體過程具體流程如下:

上面可以看出窗體可以接收和處理消息的特性.然而控件其實也都是窗口.但是每個控件卻不一定都具有接收和處理消息的功能.因爲在系統中只有具有句柄(一個系統自動維護的32位的數值,是作爲系統對象的簡單的唯一性的標識)的窗口才具有處理消息的特性.因爲只有具有句柄的窗口才能獨立存在作爲一窗體存在.作爲其他控件的容器.而沒有句柄的控件,如Label,是不能獨立存在的,只能作爲窗口控件的子控件,它不能繪製自身,只能依靠父窗體將它繪製來.

 

消息

  1. 消息載體

    1. struct MSG  
    2. {  
    3. HWND hwnd;  
    4. UINT message;  
    5. WPARAM wParam;  
    6. LPARAM lParam;  
    7. DWORD time;  
    8. POINT pt;  
    9. };  
  2. 消息的簡單分類

    一般來說消息能夠被分爲「隊列化的」和「非隊列化的」.
    • 隊列化的消息是由Windows放入程序消息隊列中的.在程序的消息循環中,重新傳回並分配給窗口消息處理程序.即把消息發送給程序的消息隊列中,等帶消息處理函數取出並處理消息.隊列化消息基本上是使用者輸入的結果,以擊鍵(如WM_KEYDOWN和WM_KEYUP消息)、擊鍵產生的字符(WM_CHAR)、鼠標移動(WM_MOUSEMOVE)和鼠標按鈕(WM_LBUTTONDOWN)的形式給出.隊列化消息還包含時鐘消息(WM_TIMER)、更新消息(WM_PAINT)和退出消息(WM_QUIT).
    • 非隊列化的消息在Windows呼叫窗口時直接送給窗口消息處理程序.直接進行消息處理.非隊列化消息則是其它消息.在許多情況下,非隊列化消息來自呼叫特定的Windows函數.例如,當WinMain呼叫CreateWindow時,Windows將建立窗口並在處理中給窗口消息處理程序發送一個WM_CREATE消息.當WinMain呼叫ShowWindow時,Windows將給窗口消息處理程序發送WM_SIZE和WM_SHOWWINDOW消息.當WinMain呼叫UpdateWindow時,Windows將給窗口消息處理程序發送WM_PAINT消息.
    • 注意: 鍵盤或鼠標輸入時發出的隊列化消息信號,也能在非隊列化消息中出現.例如,用鍵盤或鼠標選擇了一個菜單項時,鍵盤或鼠標消息就是隊列化的,而說明菜單項已選中的WM_COMMAND消息則可能就是非隊列化的.
    • 任何情況下,窗口消息處理程序都將獲得窗口所有的消息--包括隊列化的和非隊列化的
  3. 消息隊列

    1. 系統隊列
      當操作系統啓動並初始化時,線程Raw Input Thread(RIT)就會啓動,並創系統硬件輸入隊列(System Hardware Input Queue)(SHIQ). 對於外部的硬件事件(鼠標或者鍵盤),硬件驅動會將事件轉換成消息,並存放到SHIQ中,而RIT線程就專門負責處理SHIQ中的消息,把消息分發到對應線程的消息隊列裏面.
    2. 線程隊列
    3.   
        1. 而對於線程來說,每個線程可以擁有自己的消息隊列,它和線程一一對應.在線程剛創建時,消息隊列並不會被創建,而是當GDI的函數調用發生時,Windows系統才認爲有必要爲線程創建消息隊列.系統會爲其維護一個THREADINFO結構.
          消息隊列包含在一個叫THREADINFO的結構中,有四個隊列:
          • Sent Message Queue 發送消息隊列 [該隊列保存其他程序通過SendMessage給該線程發送的消息]
          • Posted Message Queue 登記消息隊列 [該隊列保存其他隊列通過PostMessage給該線程發送的消息]
          • Visualized Input Queue 輸入消息隊列 [保存系統隊列分發過來的消息,比如鼠標或者鍵盤的消息]
          • Reply Message Queue 響應消息隊列 [保存向窗體發送消息後的結果,比如sendMessage操作結束後,接收消息方會發送一個Reply消息給發送方的Reply隊列中,以喚醒發送隊列]
          THREADINFO結構體定義如下圖所示:

       

      消息管理機制

      1. 消息源

         消息可以由Windows系統發送,也可以由應用程序本身;可以向線程內發送,也可以跨線程.主要是看發送函數的調用者.
      2. 附加參數:

        系統向窗口發送的消息通常包含3個參數,分別是:
        • 窗口句柄(a window handle):窗口句柄用來標識消息將要發送到的窗口對象,系統使用窗口句柄來確定哪一個窗口句柄應該接收該消息.
        • 消息標識符(a message identifier):消息標識符是用來區分不同消息的命名常量,當窗口過程接收到一個消息時,它使用消息標識符來確定如何處理該消息.例如,消息標識符WM_PAINT告訴窗口過程“窗口的客戶區已經發生變化,窗口必須進行重新繪製”.
        • 消息參數(message parameters):消息參數用來表述窗口過程處理消息時所使用的數據或數據的位置,通常用一對參數表示(即2個長整型的參數:WPARAM, LPARAM).消息參數的意義和取值取決於消息.當不需要使用消息參數時,通常將其設置爲NULL.窗口過程必須通過檢查消息標識符來確定如何對消息參數進行解釋.
      3. 傳遞過程:

        用戶在操作程序時對電腦的操作這個事件將會被系統捕獲到,然後把這個事件翻譯成一個消息並且把消息投遞到對應的消息隊列中.而程序發現自己的消息隊列中具有消息時它便會從自己的消息隊列中取出消息並處理消息.直至消息隊列爲空爲止.

      4. 三級結構

        Windows消息控制中心一般是三層結構,其頂端就是Windows內核.Windows內核維護着一個消息隊列,第二級控制中心從這個消息隊列中獲取屬於自己管轄的消息,後做出處理,有些消息直接處理掉,有些還要發送給下一級窗體(Window)或控件(Control).第二級控制中心一般是各Windows應用程序的Application對象.第三級控制中心就是Windows窗體對象,每一個窗體都有一個默認的窗體過程,這個過程負責處理各種接收到的消息.

       

      總結

      首先我們要了解 windows 系統下程序是以消息爲基礎,事件驅動之.首先用戶出發事件,然後系統把事件轉換爲對應的消息,然後把消息投遞到消息隊列中.應用程序通過消息循環獲得消息,然後把消息轉交個系統,有系統再把消息交給對應的窗口回調函數(系統通過以註冊的窗口類結構中的一個指向回調函數指針的成員找到窗體的回調函數,而這個窗體結構體是在窗體創建過程中設計窗體類時候通過定義一個 WNDCLASS 結構體設計窗體基本屬性是定義的),通過窗口回調函數來處理消息,處理消息結束後,應用回調函數把權限在交還給系統然後,系統在執行權限交給應用程序.程序繼續從消息隊列中取出消息並按上述方法去處理消息之.流程如下:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章