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

VC++ 對話框間通信:事件機制解耦替代直接調用 OnTimer

     編輯:程式設計綜合問答

問題場景

對話框 A 包含儀表控件,在 OnTimer 中啟動動畫。需在對話框 B 的按鈕點擊時控制 A 的儀表。直接調用 A 的 OnTimer 或訪問其控件 ID 會導致類強耦合,且 B 中無法識別 A 的控件 ID。

反模式:直接調用(不推薦)

// B.cpp 中 - 強耦合、難維護
void CBDlg::OnButtonClick() {
    CADlg* pA = (CADlg*)AfxGetMainWnd();  // 假設 A 是主窗口
    if (pA) pA->OnTimer(1);  // 直接調用 A 的定時器
}

缺點:B 依賴 A 的內部實現;A 修改定時器邏輯會破壞 B;多實例場景無法區分。

最佳實踐:事件/委托模式

步驟 1:定義接口(抽象層)

// IInstrumentControl.h
#pragma once
class IInstrumentControl {
public:
    virtual ~IInstrumentControl() {}
    virtual void StartAnimation() = 0;
    virtual void StopAnimation() = 0;
    virtual void SetValue(double val) = 0;
};

步驟 2:對話框 A 實現接口


// ADlg.h
class CADlg : public CDialogEx, public IInstrumentControl {
    // ...
    void StartAnimation() override { /* 啟動定時器 */ }
    void SetValue(double val) override { m_ctrlMeter.SetValue(val); }
};

步驟 3:對話框 B 持有接口指針


// BDlg.h
class CBDlg : public CDialogEx {
    IInstrumentControl* m_pInstrument;  // 弱引用,不擁有生命週期
public:
    void SetInstrumentController(IInstrumentControl* p) { m_pInstrument = p; }
    void OnButtonClick() { 
        if (m_pInstrument) m_pInstrument->StartAnimation(); 
    }
};

步驟 4:上層協調者綁定(如主框架或應用類)


// CMainFrame 或 App 初始化時
CADlg dlgA;
CBDlg dlgB;
dlgB.SetInstrumentController(&dlgA);  // 依賴倒置

替代方案:Windows 消息機制

若不想引入接口,可使用自定義消息:


// 定義消息
#define WM_USER_CONTROL_METER (WM_USER + 100)

// A 中處理
ON_MESSAGE(WM_USER_CONTROL_METER, OnControlMeter)
LRESULT CADlg::OnControlMeter(WPARAM wParam, LPARAM lParam) {
    // wParam: 命令類型, lParam: 參數
    if (wParam == 1) StartAnimation();
    return 0;
}

// B 中發送
::PostMessage(hWndA, WM_USER_CONTROL_METER, 1, 0);

核心原則

「針對接口編程,不針對實現編程。」—— 通過抽象層解耦,實現對話框間低耦合、高內聚協作。

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