ActiveX 控制項本身是無視窗或有視窗的 COM 物件。複雜 UI (設定面板、精靈、資料輸入) 直接在 OnDraw 繪製極其困難。MFC CDialog 提供完整的**資源編輯器設計、DDX/DDV、訊息映射、控制項管理**,將對話框作為控制項的**子視窗**或**獨立彈出視窗**嵌入,是標準做法。
IDD_MYDIALOG。CMyDialog : public CDialog。CMyCtrl : public COleControl 成員加入 CMyDialog m_dlg; (或指標)。
void CMyCtrl::DoModalDialog()
{
// 直接呼叫 DoModal,阻塞直到使用者關閉
m_dlg.DoModal(); // 此處可檢查返回值 IDOK/IDCANCEL
}
注意:m_dlg 為成員變數,生命週期隨控制項。DoModal 內部會建立臨時視窗,銷毀時自動清理。
CMyDialog m_dlg; 成員。OnCreate 中建立對話框視窗:
int CMyCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (COleControl::OnCreate(lpCreateStruct) == -1) return -1;
// 建立非模態對話框 (WS_CHILD | WS_VISIBLE)
if (!m_dlg.Create(IDD_MYDIALOG, this)) // this 為父視窗 (控制項視窗)
return -1;
return 0;
}
void CMyCtrl::ShowDialog()
{
m_dlg.ShowWindow(SW_SHOW); // 顯示
m_dlg.SetFocus(); // 可選:取得焦點
}
void CMyCtrl::HideDialog()
{
m_dlg.ShowWindow(SW_HIDE);
}
關鍵點:
Create 而非 DoModal,返回 BOOL 而非阻塞。this (控制項視窗),確保 Z-Order、剪裁、銷毀連動。OnDestroy) 需 m_dlg.DestroyWindow() 釋放視窗資源。| 屬性頁 | 設定值 | 原因 |
|---|---|---|
| Styles → Style | Child | 作為子視窗嵌入,無標題列、邊框 |
| Styles → Border | None (或 Dialog Frame 視需求) | 無邊框 |
| Styles → Title Bar | Unchecked | 無標題列 |
| More Styles → Visible | Checked | 建立即顯示 |
| More Styles → Control | Checked | 支援 Tab 鍵導航、Dialog 鍵盤介面 |
| Extended Styles → Static Edge | Checked (可選) | 輕微 3D 邊框效果 |
| 方向 | 機制 | 範例 |
|---|---|---|
| 控制項 → 對話框 | 直接呼叫對話框 public 方法 / 設定 public 成員 | m_dlg.SetData(pData); |
| 對話框 → 控制項 | 對話框建構時傳 CMyCtrl* pCtrl,或 GetParent() 轉型 | ((CMyCtrl*)GetParent())->FireEvent(...); |
| 對話框控制項事件 | 對話框類別內正常訊息映射 (ON_BN_CLICKED 等) | 按鈕點擊 → 對話框處理 → 通知控制項觸發事件 |
void CMyCtrl::OnDestroy()
{
if (m_dlg.GetSafeHwnd())
m_dlg.DestroyWindow(); // 先銷毀子視窗
COleControl::OnDestroy();
}
// 或在非模態模式下,對話框成員為指標
CMyDialog* m_pDlg = nullptr;
int OnCreate(...) {
m_pDlg = new CMyDialog;
m_pDlg->Create(IDD, this);
return 0;
}
void OnDestroy() {
if (m_pDlg) { m_pDlg->DestroyWindow(); delete m_pDlg; m_pDlg = nullptr; }
COleControl::OnDestroy();
}
IOleInPlaceActiveObject::TranslateAccelerator 轉發鍵盤訊息 (MFC COleControl 預設已處理)。OnSize 調用 MoveWindow。AFX_MANAGE_STATE 確保正確載入 DLL 資源。ActiveX 控制項整合對話框三大模式:**模態** (同步阻塞、簡單)、**非模態** (並存、工具面板)、**子視窗嵌入** (無框架、控制項即表單)。核心在於對話框範本屬性正確設定 (Child/No Border/Control)、父視窗關係正確 (控制項視窗)、生命週期同步 (Create/DestroyWindow)、鍵盤導航支援。掌握此技術,可將複雜 MFC 對話框 UI 封裝為可重用、跨容器部署的 ActiveX 控制項。