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

深入 VCL 訊息機制 (三):TApplication 級訊息攔截與預處理

     編輯:VC 教學

TApplication:VCL 應用程式的中樞神經

TApplication、TScreen、TForm 構成 BCB GUI 程式的三大支柱。TApplication 封裝了標準 Windows 程式行為:

  1. Windows 訊息處理(核心)
  2. 線上說明系統
  3. 選單快捷鍵與鍵盤事件
  4. 例外處理
  5. 主視窗、視窗類別等 OS 基礎設施管理

為什麼在 TApplication 層攔截訊息?

  • 最早收到: 系統訊息泵先送達 TApplication,再分派給 TForm。此處攔截可實現全域熱鍵、全域滑鼠手勢、訊息日誌、安全過濾等。
  • 全域範圍: 不受特定表單生命週期限制,適用於跨表單、無表單(服務型)場景。
  • 預處理能力: 可在訊息到達目標視窗前修改、吞噬、重導向。

TApplication 訊息處理流程

// 簡化版 Application->ProcessMessage 流程
function TApplication.ProcessMessage: Boolean;
var
    Msg: TMsg;
begin
    Result := False;
    if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then begin
        // 1. 前置過濾:OnMessage 事件
        if Assigned(OnMessage) then OnMessage(Msg, Handled);
        if Handled then Exit(True);

        // 2. 內部預處理:快捷鍵、Hint、MDI 等
        if IsHintMsg(Msg) then ...;
        if IsMDIMsg(Msg) then ...;
        if ProcessShortCut(Msg) then ...; // 選單快捷鍵

        // 3. 標準分派
        TranslateMessage(Msg);
        DispatchMessage(Msg); // 送達目標視窗程序
        Result := True;
    end;
end;

三種掛鉤 TApplication 訊息的方法

方法一:Application.OnMessage 事件(最簡單)

// 在專案主檔或表單建構子
Application->OnMessage = AppMessageHandler;

void __fastcall TForm1::AppMessageHandler(tagMSG &Msg, bool &Handled)
{
    if (Msg.message == WM_HOTKEY) { // 全域熱鍵
        Handled = true; // 吞噬訊息
        // 處理邏輯...
    }
}

方法二:TApplicationEvents 元件(設計時期綁定)

  • 從元件面板放置 TApplicationEvents 到表單。
  • 雙擊 OnMessage 編寫處理器,效果同方法一,但支援設計時期屬性設定。

方法三:子類別化 TApplication 重寫虛擬方法(最強控制)

class TMyApplication : public TApplication
{
protected:
    virtual void __fastcall WndProc(TMessage &Message) override;
};

void __fastcall TMyApplication::WndProc(TMessage &Message)
{
    // 攔截 WM_COPYDATA 實現進程間通訊
    if (Message.Msg == WM_COPYDATA) {
        // 處理...
        return; // 不傳給基類
    }
    TApplication::WndProc(Message); // 必須呼叫基類
}

// 專案主檔替換 Application 實例
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    Application = new TMyApplication(NULL);
    Application->Initialize();
    Application->CreateForm(__classid(TForm1), &Form1);
    Application->Run();
    return 0;
}

實戰場景對比

場景推薦方法理由
全域熱鍵OnMessage簡單、無需修改專案結構
訊息日誌/審計OnMessage集中記錄,Handled=false 繼續分派
攔截 WM_COPYDATA子類別化需在分派前處理,OnMessage 可能過晚
自訂訊息泵子類別化完全控制 PeekMessage/DispatchMessage
MDI 子視窗協調TApplicationEvents設計時期可視化,支援多事件

注意事項

  • OnMessage 中 Handled=true 將阻止後續分派,謹慎使用。
  • 子類別化 TApplication 需在 Application->Initialize() 前替換實例。
  • 訊息處理器中嚴禁執行耗時操作(資料庫、網路、Sleep),會凍結整個應用程式訊息泵。
  • 多執行緒環境下,TApplication 訊息泵僅運行於主執行緒。

TApplication 訊息處理流程圖

善用 TApplication 層訊息攔截,能實現許多表單層面無法達到的全域行為控制。

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