首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C++ MFC 消息映射一對多分發:函數指針陣列實現觀察者模式

     編輯:程式設計疑難解答

MFC 消息映射機制預設一條消息對應一個處理函數。若需實現「一條消息觸發多個類的處理邏輯」(如插件系統、模組解耦),可採用函數指針陣列 + 動態註冊模式,實現輕量級觀察者模式。

核心思路

  1. 定義統一的消息處理函數簽名
  2. 維護全局/單例的函數指針容器
  3. 提供註冊/註銷介面供各模組調用
  4. 消息處理入口函數遍歷調用所有註冊函數

完整實現代碼

1. 定義處理器類型與註冊中心

// MsgHandler.h
#pragma once
#include 
#include 
#include 

// 統一處理器簽名:WPARAM, LPARAM 為標準消息參數
using MsgHandlerFunc = std::function;

class CMsgDispatcher {
public:
    static CMsgDispatcher& Instance() {
        static CMsgDispatcher inst;
        return inst;
    }
    
    // 註冊處理器,返回唯一 ID 供後續註銷
    UINT RegisterHandler(MsgHandlerFunc handler) {
        std::lock_guard lock(m_mutex);
        m_handlers.push_back(handler);
        return (UINT)m_handlers.size(); // 簡易 ID
    }
    
    // 註銷處理器
    void UnregisterHandler(UINT id) {
        std::lock_guard lock(m_mutex);
        if (id > 0 && id <= m_handlers.size()) {
            m_handlers[id - 1] = nullptr; // 標記失效
        }
    }
    
    // 分發消息
    void Dispatch(WPARAM wParam, LPARAM lParam) {
        std::lock_guard lock(m_mutex);
        for (auto& handler : m_handlers) {
            if (handler) handler(wParam, lParam);
        }
    }
    
private:
    std::vector m_handlers;
    std::mutex m_mutex;
};

2. 各業務類註冊處理邏輯

// ModuleA.cpp
class CModuleA {
public:
    CModuleA() {
        // 構造時註冊,使用 Lambda 捕獲 this
        m_handlerId = CMsgDispatcher::Instance().RegisterHandler(
            [this](WPARAM w, LPARAM l) { OnCustomMsg(w, l); }
        );
    }
    
    ~CModuleA() {
        CMsgDispatcher::Instance().UnregisterHandler(m_handlerId);
    }
    
    void OnCustomMsg(WPARAM w, LPARAM l) {
        // 模組 A 的具體處理邏輯
        TRACE(_T("ModuleA received: %d, %d\n"), w, l);
    }
    
private:
    UINT m_handlerId = 0;
};

3. 消息入口統一分發

// MainFrame.cpp 或 View.cpp
LRESULT CMainFrame::OnCustomMessage(WPARAM wParam, LPARAM lParam) {
    // 核心:一條消息分發給所有註冊處理器
    CMsgDispatcher::Instance().Dispatch(wParam, lParam);
    return 0;
}

// 發送消息觸發
PostMessage(WM_USER_CUSTOM, param1, param2);

進階優化建議

  • 優先級分發:std::map> 按優先級排序調用
  • 異步分發:投遞至線程池避免阻塞 UI 線程
  • 消息過濾:註冊時指定關注的消息 ID 範圍,分發時精準路由
  • MFC 原生替代:CCmdTarget 派生類重寫 OnCmdMsg 實現命令路由鏈

適用場景

  • 插件架構:核心程序廣播事件,插件動態響應
  • 多視圖同步:數據變更通知所有打開的視圖更新
  • 跨模組解耦:發送方無需知曉接收方具體類型

此模式打破 MFC 單一消息映射限制,以現代 C++ 風格實現靈活的多播機制,且零侵入原有消息循環。

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