MFC歷經十餘年仍是VC++核心,但面臨:無RAD設計器、缺乏.NET互操作、UI控件生態落後。解法:**開啟托管擴展 (/clr)**,在MFC專案中引入.NET世界,實現「對偶物件」模式與.NET控件宿主。
專案屬性 → C/C++ → General → Common Language Runtime Support:/clr (非純粹/安全模式)
[ MFC物件 ] ←→ [ 托管包裝物件 ] ←→ [ 其他.NET物件 ]
↑ ↑
持有指標 持有指標
gcroot指向托管包裝物件MFCClass*指向原生物件
// 專案加入「Managed C++ Component」→ 修改基類為Object → 清理程式碼
namespace MyProject {
public ref class CDocWrapper { // ref class = 托管參考型別
public:
CDocWrapper() {}
// 包裝MFC文檔操作方法
};
}
#include // gcroot定義
class CMyDoc : public CDocument {
public:
gcroot m_pWrapper; // 型別安全包裝
BOOL Initialize() {
#pragma push_macro("new")
#undef new // 避開MFC DEBUG_NEW巨集干擾托管new
m_pWrapper = gcnew MyProject::CDocWrapper();
#pragma pop_macro("new")
m_pWrapper->SetNativeDoc(this); // 建立反向指標
return TRUE;
}
};
關鍵點:托管物件必須用gcnew在CLR堆配置,不能用MFC的new (本地堆)。#pragma push/pop_macro("new")暫時移除DEBUG_NEW干擾。
差別僅在註冊方式:ActiveX寫註冊表 (全域),.NET控件放GAC或本地目錄。捕獲.NET控件資訊後,可用MFC ActiveX宿主機制 (COleControlSite) 載入。
class CWFControlSite : public COleControlSite {
public:
CWFControlSite(COleControlContainer* pCnt) : COleControlSite(pCnt) {}
// 覆寫必要虛擬函數支援.NET控件特性
};
class CWFControlWrapper : public CWnd {
public:
IUnknown* m_pUnkControl; // .NET控件的IUnknown
IUnknown* GetManagedControl() { return m_pUnkControl; }
void SetControlSite(COleControlSite* pSite) { m_pCtrlSite = pSite; }
};
class CUserCtrlView : public CView {
CWFControlWrapper m_Control;
protected:
// 關鍵:對話框訊息預處理 (解決Tab鍵導航問題)
virtual BOOL PreTranslateMessage(MSG* pMsg) {
if (m_Control.m_pUnkControl) {
CComQIPtr spInPlace(m_Control.m_pUnkControl);
if (spInPlace && spInPlace->TranslateAccelerator(pMsg) == S_OK)
return TRUE;
}
return CView::PreTranslateMessage(pMsg);
}
// 建立/銷毀控件邏輯...
};
PreTranslateMessage轉發訊息給IOleInPlaceActiveObject::TranslateAccelerator,解決.NET控件在MFC視圖中Tab鍵無法導航的經典問題。
/clr支援ref class),定義雙向介面gcroot,gcnew建立,#pragma push_macro("new")保護CWFControlSite + CWFControlWrapper + CUserCtrlView宿主鏈PreTranslateMessage轉發TranslateAccelerator支援鍵盤導航using namespace#undef new[STAThread]或AfxOleInit確保gcroot自動追蹤,但循環參考 (MFC↔Managed) 需手動切斷透過/clr、gcroot對偶物件模式與自訂COleControlSite宿主鏈,MFC專案可無縫整合.NET Framework豐富類庫與現代控件生態。這不僅延續MFC既有資產壽命,更為遷移至純.NET架構提供平滑過渡路徑。關鍵在於:托管/非托管邊界清晰劃分、CLR堆與本地堆正確配置、ActiveX宿主機制複用、訊息迴路正確轉發。