簡析Windows消息機制

Windows消息機制

窗口程序特徵
一個Windows上的窗口程序,包含外層的窗口,客戶區,菜單欄,標題欄以及按鈕,編輯框等!而窗口,控件以及音頻,視頻,圖片等文件統稱爲資源文件(Resource.h),每個資源文件都對應一個句柄,通過句柄我們可以操控該資源文件

消息機制
Windows窗口程序的運行全靠消息驅動,那什麼是消息呢?

消息,從字面理解就是要傳遞給對方的某個東西, 在Windows上我們的任何行爲比如單擊鼠標,雙擊鼠標,輸入文字都會產生一條對應的消息

注意:消息也稱爲事件

誰會最先接收到這個消息呢?

操作系統

誰會去處理這個消息呢?

操作系統雖然最先接收到消息,但是它不會立馬處理,它會把這條消息先放到系統消息隊列中,再根據句柄等標識將其拷貝到對應的應用程序消息隊列中。然後該應用程序的消息循環會不斷檢索自己的消息隊列,並使用回調函數處理每一條消息

注意:當應用程序第一次調用GDI函數時系統纔給程序創建一個應用程序消息隊列,也稱爲線程消息隊列

操作系統是如何知道消息是由哪一個程序產生的呢?

typedef struct tagMSG{
    HWND hwnd; //接收該消息的窗口句柄
    UINT message; //消息常量標識符,也就是消息號
    WPARAM wParam; //附加信息
    LPARAM lParam; //附加信息
    DWORD time; //當前時間
    POINT pt; //鼠標座標
}MSG;
就是由上面的 MSG 結構體中的窗口句柄決定的,並且 message 變量標識該消息的類型,具體如下:

WM_NULL---0x0000 空消息
0x0001----0x0087 窗口消息
0x00A0----0x00A9 非客戶區消息
0x0100----0x0108 鍵盤消息
0x0111----0x0126 菜單消息
0x0132----0x0138 顏色控制消息
0x0200----0x020A 鼠標消息
0x0211----0x0213 菜單循環消息
0x0220----0x0230 多文檔消息
0x03E0----0x03E8 DDE消息
0x0400----0x7FFF WM_USER自定義消息

由於上面這些數值不容易記憶,所以Windows就定義了很多的宏來標識這些消息,比如:鼠標左鍵按下消息是WM_LBUTTONDOWN,鍵盤按下消息是WM_KEYDOWN

發送消息
發送消息的函數有SendMessage,SendMessageCallback,SendNotifyMessage,SendMessageTimeout
寄送消息的函數主要有PostMessage,PostThreadMessage,PostQuitMessage
廣播消息的函數有BroadcastSystemMessage,BroadcastSystemMessageEx

發送和寄送最大的區別就是:發送的消息不會被放到應用程序消息隊列中,寄送的消息會被放到應用程序消息隊列中,導致SendMessage必須等消息處理後才返回,PostMessage將消息放到消息隊列後立馬返回

WM_PAINT
WM_PAINT 消息表示繪製窗口的客戶區,窗口經常會收到這個消息,第一條 WM_PAINT 通常發生在 WinMain 中調用 UpdateWindow 時。WM_PAINT 消息在哪些情況下會產生呢?

該窗口的某些部分被遮擋
該窗口的大小被調整
客戶區的滾動條滾動

注意:窗口類的 style 字段爲 CS_HREDRAW 和 CS_VREDRAW,才能重繪

WM_PAINT 是個特殊的消息,它會合並多個 WM_PAINT,目的是方便將多個無效區域合併成一個大的無效區域以及減少刷新窗口的次數。具體實現:等到應用消息隊列爲空時才發送WM_PAINT消息

WM_PAINT 的具體處理流程:

  • BeginPaint 獲取 DC 設備環境句柄(HDC hdc = BeginPaint(hwnd,&paintstruct))
  • GetClientRect 獲取客戶區矩形區域(GetClientRect(hwnd,&rect))
  • DrawText 重新顯示
  • EndPaint 釋放設備上下文句柄(EndPaint(hwnd,&paintstruct))

注意:BeginPaint的一個作用就是把Update Region置爲空

END

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