首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

淺析 Windows 訊息機制:從訊息結構到訊息迴圈

     編輯:VC 教學

前言

Windows 是典型的「訊息驅動」作業系統。所有使用者輸入(鍵盤、滑鼠)、系統事件(計時器、電源狀態變更)、應用程式間通訊,最終都轉化為一個個訊息投遞到目標視窗。深入理解訊息結構、派發流程與訊息迴圈,是撰寫高效、穩定 Windows 程式的基石。

一、訊息的組成

一個訊息由三個核心欄位組成:

  • UINT message:訊息識別碼(如 WM_PAINT、WM_LBUTTONDOWN)。
  • WPARAM wParam:32 位元參數,通常承載鍵盤鍵碼、控制項 ID、通知碼高位等。
  • LPARAM lParam:32 位元參數,通常承載滑鼠座標、指標位址、通知碼低位等。

開發者亦可自訂訊息(建議從 WM_USER + 100 或 RegisterWindowMessage 取得唯一值),用於執行緒/進程間通訊。

二、誰接收訊息?

每個訊息必須指定目標視窗控制代碼(HWND)。系統依 HWND 找到對應的視窗程序(WndProc),呼叫該函式處理訊息。同一視窗類別的所有實例共用同一 WndProc,但透過 HWND 區分具體實例。

三、未處理的訊息去哪裡?

若應用程式在 WndProc 中未處理某訊息,應呼叫 DefWindowProc 交給系統預設視窗程序處理。這確保視窗仍具備標準行為(拖曳、最小化、繪製邊框等),開發者只需關注業務邏輯相關訊息。

四、視窗控制代碼(HWND)的角色

HWND 是系統內核中視窗物件的唯一識別子。PostMessage/SendMessage 必須提供目標 HWND,系統才能將訊息投遞到正確的訊息佇列。兩個視窗即使共用同一 WndProc,因 HWND 不同,訊息也不會混淆。

五、訊息處理範例

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_PAINT:
            OnPaint(hWnd); break;
        case WM_LBUTTONDOWN:
            OnLButtonDown(hWnd, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break;
        case WM_DESTROY:
            PostQuitMessage(0); break;
        default:
            return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0;
}

六、訊息機制核心:訊息佇列與訊息迴圈

1. 系統訊息佇列

系統為每個執行緒維護一個訊息佇列(16 位元 Windows 僅有一個全系統佇列)。所有針對該執行緒建立視窗的訊息,皆先放入此佇列。

2. 應用程式訊息迴圈

MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
    TranslateMessage(&msg);   // 處理鍵盤訊息產生 WM_CHAR
    DispatchMessage(&msg);    // 依 HWND 呼叫對應 WndProc
}
  • GetMessage:佇列為空時阻塞,釋放 CPU 時間片,實現多工協作。
  • PeekMessage:非阻塞檢查,適合遊戲迴圈或需輪詢的場合。

七、協作式 vs. 搶先式多工

特性16 位元 (Win 3.x)32/64 位元 (Win95+)
訊息佇列單一全系統佇列每執行緒一個佇列
多工模型協作式:前景程式不讓出控制權,系統卡死搶先式:OS 依優先級調度 CPU,單一程式死循環不影響其他
訊息派發系統輪詢分派執行緒自行 GetMessage/Dispatch

八、實務建議

  1. 耗時運算移出 UI 執行緒:使用 Worker Thread + PostMessage 回報進度,避免訊息迴圈阻塞導致介面凍結。
  2. 善用 SendMessageTimeout:跨進程送訊息時設定逾時,防止目標進程掛起造成發送端死等。
  3. 自訂訊息用 RegisterWindowMessage:保證系統全域唯一,避免衝突。
  4. 訊息撰寫:WM_COPYDATA 可跨進程傳遞結構化資料,配合 SendMessage 同步投遞。

結語

Windows 訊息機制雖歷經數十年演進,核心概念——訊息佇列、視窗程序、訊息迴圈——始終未變。熟練掌握這套機制,不僅能寫出回應迅速的 GUI 程式,更能從根本上理解 MFC、WTL、Qt 等框架的底層運作,事半功倍。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved