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

C++Builder 響應系統訊息與自訂訊息:完整範本與跨進程通訊實例

     編輯:VC 教學

核心模式:BEGIN_MESSAGE_MAP + 專用訊息結構

標頭檔完整範本

// 自訂訊息 ID
#define WM_MY_OPEN_CMDLINE_FILE (WM_USER + 1)  // 命令列檔案傳遞
#define WM_MY_SEARCH_NODE       (WM_USER + 2)  // 內部搜尋觸發

class TSomeForm : public TForm
{
__published: ...
protected:
    // 1. 訊息處理函數宣告(參數採 const 參考或值傳遞)
    void __fastcall OpenCmdLineFile(TMessage &Message);
    void __fastcall SearchDocumentNode(TMessage &Message);
    void __fastcall GetWindowMinMaxInfo(TWMGetMinMaxInfo &Message);

    // 2. 訊息映射表
    BEGIN_MESSAGE_MAP
        MESSAGE_HANDLER(WM_MY_OPEN_CMDLINE_FILE, TMessage, OpenCmdLineFile)
        MESSAGE_HANDLER(WM_MY_SEARCH_NODE,       TMessage, SearchDocumentNode)
        MESSAGE_HANDLER(WM_GETMINMAXINFO,        TWMGetMinMaxInfo, GetWindowMinMaxInfo)
    END_MESSAGE_MAP(TForm)
public:
    __fastcall TSomeForm(TComponent* Owner);
};

實作檔:參數提取與業務邏輯

// 1. 處理命令列檔案傳遞 (LPARAM 傳遞 char*)
void __fastcall TSomeForm::OpenCmdLineFile(TMessage &Message)
{
    LPSTR lpCmdLine = (LPSTR)Message.LParam; // 取得指標
    HandleCmdLineFile(lpCmdLine);            // 交由業務函數
}

// 2. 觸發搜尋 (無額外參數)
void __fastcall TSomeForm::SearchDocumentNode(TMessage &Message)
{
    SearchNode(); // 直接呼叫
}

// 3. 設定視窗最小尺寸 (系統訊息,專用結構)
void __fastcall TSomeForm::GetWindowMinMaxInfo(TWMGetMinMaxInfo &Message)
{
    MINMAXINFO *mmi = Message.MinMaxInfo;
    mmi->ptMinTrackSize.x = 400;
    mmi->ptMinTrackSize.y = 300;
}

自訂訊息結構設計指南

參考 $(BCB)\Include\Vcl\Messages.hpp 中的定義風格:

// 範例:帶兩個整數參數的自訂訊息
struct TMySearchMsg : public TMessage
{
    int NodeId;
    int FilterType;
};

// 發送端
TMySearchMsg msg;
msg.Msg = WM_MY_SEARCH_NODE;
msg.NodeId = 123;
msg.FilterType = 2;
PostMessage(TargetWnd, WM_MY_SEARCH_NODE, (WPARAM)&msg, 0); // 指標傳遞

// 接收端映射
MESSAGE_HANDLER(WM_MY_SEARCH_NODE, TMySearchMsg, OnMySearch)

void __fastcall TForm1::OnMySearch(TMySearchMsg &Msg)
{
    // 直接存取 Msg.NodeId, Msg.FilterType
    DoSearch(Msg.NodeId, Msg.FilterType);
}

跨進程通訊實戰:單一實例應用

場景:使用者雙擊關聯檔案 → 第二個實例啟動 → 傳遞檔案路徑給第一個實例 → 第二個實例退出。

第一個實例(主實例)註冊訊息

// 全域唯一訊息 ID
UINT WM_MY_INSTANCE_MSG = RegisterWindowMessage("MyApp_InstanceMessage_{GUID}");

// 主表單建構子
__fastcall TMainForm::TMainForm(TComponent* Owner) : TForm(Owner)
{
    // 掛鉤訊息
    BEGIN_MESSAGE_MAP
        MESSAGE_HANDLER(WM_MY_INSTANCE_MSG, TMessage, OnInstanceMessage)
    END_MESSAGE_MAP(TForm)
}

void __fastcall TMainForm::OnInstanceMessage(TMessage &Msg)
{
    // LPARAM 傳遞檔案路徑指標 (需共享記憶體或 WM_COPYDATA)
    // 此處示範 WM_COPYDATA 更安全
}

第二個實例發送 WM_COPYDATA

// WinMain 入口點檢測
HANDLE hMutex = CreateMutex(NULL, TRUE, "MyApp_SingleInstance_Mutex");
if (GetLastError() == ERROR_ALREADY_EXISTS) {
    // 找到主視窗
    HWND hMain = FindWindow("TMainForm", NULL);
    if (hMain) {
        COPYDATASTRUCT cds;
        cds.dwData = 1; // 命令:開啟檔案
        cds.cbData = (lstrlen(lpCmdLine) + 1) * sizeof(TCHAR);
        cds.lpData = (void*)lpCmdLine;
        SendMessage(hMain, WM_COPYDATA, 0, (LPARAM)&cds);
    }
    return 0; // 直接退出
}

主實例處理 WM_COPYDATA

BEGIN_MESSAGE_MAP
    MESSAGE_HANDLER(WM_COPYDATA, TWMCopyData, OnCopyData)
END_MESSAGE_MAP(TForm)

void __fastcall TMainForm::OnCopyData(TWMCopyData &Msg)
{
    COPYDATASTRUCT *cds = Msg.CopyDataStruct;
    if (cds->dwData == 1) {
        String filePath = (TCHAR*)cds->lpData;
        OpenFileInEditor(filePath);
        BringToFront(); // 激活視窗
    }
    Msg.Result = 1; // 表示已處理
}

訊息結構定義參考位置

$(BCB)\Include\Vcl\Messages.hpp
// 包含 TMessage, TWMMouse, TWMKey, TWMGetMinMaxInfo, TWMCopyData 等

最佳實踐清單

  • ✅ 訊息 ID:視窗私有用 WM_USER+,跨進程用 RegisterWindowMessage。
  • ✅ 參數傳遞:簡單值用 WParam/LParam,複雜結構用 WM_COPYDATA 或共享記憶體。
  • ✅ 結構繼承 TMessage 以利映射宏展開。
  • ✅ 處理函數參數採 const TMsg& 或 TMsg&,避免拷貝。
  • ✅ 跨進程務必驗證來源進程可信度(GetWindowThreadProcessId + 簽名驗證)。

自訂訊息傳遞流程圖

這套模式涵蓋了 90% 的訊息響應需求,從簡單通知到跨進程協作皆適用。

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