對話框 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;多實例場景無法區分。
// IInstrumentControl.h
#pragma once
class IInstrumentControl {
public:
virtual ~IInstrumentControl() {}
virtual void StartAnimation() = 0;
virtual void StopAnimation() = 0;
virtual void SetValue(double val) = 0;
};
// ADlg.h
class CADlg : public CDialogEx, public IInstrumentControl {
// ...
void StartAnimation() override { /* 啟動定時器 */ }
void SetValue(double val) override { m_ctrlMeter.SetValue(val); }
};
// 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();
}
};
// CMainFrame 或 App 初始化時
CADlg dlgA;
CBDlg dlgB;
dlgB.SetInstrumentController(&dlgA); // 依賴倒置
若不想引入接口,可使用自定義消息:
// 定義消息
#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);
「針對接口編程,不針對實現編程。」—— 通過抽象層解耦,實現對話框間低耦合、高內聚協作。