MFC完整架构与功能详解 前言 Microsoft Foundation Classes(MFC)是微软在1992年推出的基于C++的Windows应用程序框架。作为Windows桌面开发的重要里程碑,MFC封装了复杂的Windows API,提供了面向对象的编程模型。本文将全面解析MFC的架构体系、核心原理,并通过创建自定义控件的实践,帮助开发者深入理解MFC的底层工作机制。
一、MFC整体架构概览 1.1 MFC层次结构总览 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 CObject (根类) ├── 文件类 (CFile系列) ├── 异常类 (CException系列) ├── 数据结构类 (CString, CArray等) ├── 同步类 (CSyncObject系列) └── CCmdTarget (命令目标基类) ├── CWinThread (线程类) │ ├── CWinApp (应用程序类) │ └── 用户线程类 ├── CWnd (窗口类) │ ├── CFrameWnd (框架窗口) │ │ ├── CMDIFrameWnd (MDI主框架) │ │ ├── CMDIChildWnd (MDI子窗口) │ │ └── CMinFrameWnd (最小化框架) │ ├── CDialog (对话框) │ │ ├── CCommonDialog (通用对话框) │ │ │ ├── CFileDialog │ │ │ ├── CFontDialog │ │ │ ├── CColorDialog │ │ │ ├── CPrintDialog │ │ │ ├── CPageSetupDialog │ │ │ └── CFindReplaceDialog │ │ ├── CPropertySheet (属性表) │ │ ├── CPropertyPage (属性页) │ │ └── COleDialog (OLE对话框) │ ├── CView (视图类) │ │ ├── CScrollView (滚动视图) │ │ ├── CFormView (表单视图) │ │ ├── CEditView (编辑视图) │ │ ├── CListView (列表视图) │ │ ├── CTreeView (树形视图) │ │ ├── CRichEditView (富文本视图) │ │ ├── CHtmlView (HTML视图) │ │ └── CRecordView (记录视图) │ ├── 控件类 │ │ ├── CStatic │ │ ├── CButton │ │ ├── CEdit │ │ ├── CListBox │ │ ├── CComboBox │ │ ├── CScrollBar │ │ ├── CProgressCtrl │ │ ├── CSliderCtrl │ │ ├── CSpinButtonCtrl │ │ ├── CAnimateCtrl │ │ ├── CDateTimeCtrl │ │ ├── CMonthCalCtrl │ │ ├── CHeaderCtrl │ │ ├── CHotKeyCtrl │ │ ├── CTabCtrl │ │ ├── CToolTipCtrl │ │ ├── CTreeCtrl │ │ ├── CListCtrl │ │ └── CRichEditCtrl │ └── 控制栏类 │ ├── CControlBar │ │ ├── CToolBar │ │ ├── CStatusBar │ │ └── CDialogBar │ └── CReBar ├── CDocument (文档类) │ ├── COleDocument (OLE文档) │ │ ├── COleServerDoc │ │ └── COleLinkingDoc │ └── CRichEditDoc ├── COleDispatchDriver (OLE调度驱动) └── COleDropTarget (OLE拖放目标)
1.2 MFC应用程序启动流程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 Windows 系统启动 ↓WinMain () (Windows 入口点) ↓AfxWinMain () (MFC 封装入口) ↓CWinApp ::InitApplication () ↓CWinApp ::InitInstance () ← 用户重写 │ ├── 注册窗口类 ├── 创建主框架窗口 ├── 创建视图和文档 ├── 初始化文档模板 └── 显示主窗口 ↓ CWinApp ::Run () │ ├── 消息循环 │ ├── PumpMessage () (获取消息) │ ├── PreTranslateMessage () (预处理) │ ├── TranslateMessage () (翻译消息) │ └── DispatchMessage () (分发消息) │ ├── OnIdle () (空闲处理) └── ExitInstance () (退出时调用)
二、MFC核心功能模块 2.1 应用程序框架模块 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class CWinApp : public CWinThread { virtual BOOL InitInstance () ; virtual int ExitInstance () ; virtual BOOL OnIdle (LONG lCount) ; virtual BOOL PreTranslateMessage (MSG* pMsg) ; void AddDocTemplate (CDocTemplate* pTemplate) ; CString m_pszAppName; CString m_pszRegistryKey; CString m_pszProfileName; CWinThread* m_pMainWnd; };
2.2 文档/视图架构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 文档/视图架构关系图 CDocument (数据管理) ↑ 文档模板 (CDocTemplate) ↓ CFrameWnd (框架窗口) ↓ CView (数据显示和交互) 工作流程:1. 用户操作 → 视图接收 → 更新文档 → 更新所有视图2. 文档修改 → 通知所有视图 → 视图更新显示3. 文件操作 → 文档序列化 → 保存/加载数据
2.3 消息映射系统 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class CCmdTarget : public CObject { virtual BOOL OnCmdMsg (UINT nID, int nCode, void * pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) ; };1. AfxWndProc () (全局窗口过程)2. AfxCallWndProc () (调用窗口过程)3. CWnd::WindowProc () (窗口过程)4. CWnd::OnWndMsg () (消息分发)5. CCmdTarget::OnCmdMsg () (命令处理)6. 查找消息映射表7. 调用对应的消息处理函数
2.4 运行时类型信息(RTTI) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 struct CRuntimeClass { LPCSTR m_lpszClassName; int m_nObjectSize; UINT m_wSchema; CObject* (PASCAL* m_pfnCreateObject)(); CRuntimeClass* m_pBaseClass; };DECLARE_DYNCREATE (class_name) ↓IMPLEMENT_DYNCREATE (class_name, base_class_name) ↓CRuntimeClass* class_name::GetRuntimeClass () const ↓ CObject* PASCAL class_name::CreateObject ()
三、MFC核心类详细解析 3.1 CObject类体系 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class CObject {public : CObject (); virtual ~CObject (); virtual CRuntimeClass* GetRuntimeClass () const ; BOOL IsKindOf (const CRuntimeClass* pClass) const ; static CObject* PASCAL CreateObject (LPCSTR lpszClassName) ; virtual void Serialize (CArchive& ar) ; virtual void AssertValid () const ; virtual void Dump (CDumpContext& dc) const ; };
3.2 CWnd窗口类体系 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class CWnd : public CCmdTarget {public : virtual BOOL Create (LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL ) ; virtual LRESULT DefWindowProc (UINT message, WPARAM wParam, LPARAM lParam) ; BOOL ShowWindow (int nCmdShow) ; BOOL UpdateWindow () ; BOOL DestroyWindow () ; CDC* GetDC () ; BOOL Invalidate (BOOL bErase = TRUE) ; DWORD GetStyle () const ; DWORD GetExStyle () const ; BOOL ModifyStyle (DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0 ) ; };
3.3 CDC设备上下文类体系 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 CDC设备上下文继承关系 CDC (基类) ├── CPaintDC (用于OnPaint) ├── CClientDC (客户区DC) ├── CWindowDC (整个窗口DC) ├── CMetaFileDC (图元文件DC) └── CPrintDC (打印DC) 主要功能:1 . 绘制图形 (线、矩形、椭圆等)2 . 文本输出 (TextOut, DrawText)3 . 位图操作 (BitBlt, StretchBlt)4 . 坐标映射 (SetMapMode)5 . 区域操作 (SelectClipRgn)6 . 路径操作 (BeginPath, EndPath)
3.4 GDI对象类体系 1 2 3 4 5 6 7 8 9 10 11 12 13 class CGdiObject : public CObject { };class CPen : public CGdiObject class CBrush : public CGdiObject class CFont : public CGdiObject class CBitmap : public CGdiObject class CPalette : public CGdiObject class CRgn : public CGdiObject
四、MFC高级功能模块 4.1 OLE/ActiveX支持 1 2 3 4 5 6 7 8 9 10 COleClientItem (OLE客户端项)COleServerItem (OLE服务器项)COleDocument (OLE文档)COleServerDoc (OLE服务器文档)COleIPFrameWnd (OLE在位编辑框架)COleResizeBar (OLE调整大小栏)COleDropSource (OLE拖放源)COleDropTarget (OLE拖放目标)COleControl (ActiveX控件基类)
4.2 数据库支持(ODBC/DAO) 1 2 3 4 5 6 7 8 9 10 11 12 CDatabase (数据库连接)CRecordset (记录集)CRecordView (记录视图)CFieldExchange (字段交换) CDaoDatabase CDaoRecordset CDaoTableDef CDaoQueryDef CDaoWorkspace
4.3 多线程支持 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class CWinThread : public CCmdTarget { virtual BOOL InitInstance () ; virtual int ExitInstance () ; virtual int Run () ; virtual BOOL PreTranslateMessage (MSG* pMsg) ; BOOL CreateThread (DWORD dwCreateFlags = 0 , UINT nStackSize = 0 , LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL ) ; void PostThreadMessage (UINT message, WPARAM wParam, LPARAM lParam) ; };CSyncObject (同步对象基类) ├── CSemaphore (信号量) ├── CMutex (互斥量) ├── CEvent (事件) └── CCriticalSection (临界区)
4.4 网络编程支持 1 2 3 4 5 6 7 8 9 10 11 12 CAsyncSocket (异步套接字)CSocket (同步套接字)CSocketFile (套接字文件)CInternetSession (Internet会话)CInternetConnection (Internet连接) ├── CFtpConnection (FTP连接) ├── CHttpConnection (HTTP连接) └── CGopherConnection (Gopher连接)CInternetFile (Internet文件)
4.5 自动化支持 1 2 3 4 5 6 7 8 9 10 11 COleDispatchDriver (调度驱动)COleVariant (VARIANT封装)COleCurrency (货币类型)COleDateTime (日期时间)COleSafeArray (安全数组)CTypedPtrArray (类型化指针数组)CTypedPtrList (类型化指针列表)CTypedPtrMap (类型化指针映射)
五、MFC内部机制详解 5.1 消息处理机制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 LRESULT AfxWndProc (HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam) { CWnd* pWnd = CWnd::FromHandlePermanent (hWnd); return AfxCallWndProc (pWnd, hWnd, nMsg, wParam, lParam); }BOOL CWnd::OnWndMsg (UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult) { if (message == WM_COMMAND) return OnCommand (wParam, lParam); if (message == WM_NOTIFY) return OnNotify (wParam, lParam, pResult); const AFX_MSGMAP* pMessageMap = GetMessageMap (); const AFX_MSGMAP_ENTRY* lpEntry; for (; pMessageMap != NULL ; pMessageMap = pMessageMap->pBaseMap) { lpEntry = pMessageMap->lpEntries; while (lpEntry->nSig != AfxSig_end) { if (lpEntry->nMessage == message) { union MessageMapFunctions mmf; mmf.pfn = lpEntry->pfn; LRESULT lResult = (this ->*mmf.pfn_lwl)(wParam, lParam); if (pResult != NULL ) *pResult = lResult; return TRUE; } lpEntry++; } } return FALSE; }
5.2 文档/视图架构内部机制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class CDocTemplate : public CCmdTarget { virtual CDocument* CreateNewDocument () ; virtual CFrameWnd* CreateNewFrame (CDocument* pDoc, CFrameWnd* pOther) ; virtual void AddDocument (CDocument* pDoc) ; virtual void RemoveDocument (CDocument* pDoc) ; virtual BOOL GetDocString (CString& rString, enum DocStringIndex index) const ; };void CDocument::UpdateAllViews (CView* pSender, LPARAM lHint, CObject* pHint) { POSITION pos = GetFirstViewPosition (); while (pos != NULL ) { CView* pView = GetNextView (pos); if (pView != pSender) pView->OnUpdate (pSender, lHint, pHint); } }
5.3 序列化机制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class CArchive {public : CArchive& operator <<(BYTE by); CArchive& operator <<(WORD w); CArchive& operator <<(LONG l); CArchive& operator <<(DWORD dw); CArchive& operator <<(float f); CArchive& operator <<(double d); CArchive& operator >>(BYTE& by); void WriteObject (const CObject* pOb) ; CObject* ReadObject (const CRuntimeClass* pClassRef) ; CFile* GetFile () const ; void Flush () ; };#define DECLARE_SERIAL(class_name) \ DECLARE_DYNAMIC(class_name) \ friend CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb); #define IMPLEMENT_SERIAL(class_name, base_class_name, wSchema) \ CObject* PASCAL class_name::CreateObject() \ { return new class_name; } \ _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, \ class_name::CreateObject, NULL) \ CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb) \ { pOb = (class_name*) ar.ReadObject(RUNTIME_CLASS(class_name)); \ return ar; } \ void class_name::Serialize (CArchive& ar) \ { \ base_class_name::Serialize (ar); \ if (ar.IsStoring ()) \ \ else \ \ }
六、MFC辅助类和实用功能 6.1 集合类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 CTypedPtrArray<CPtrArray, TYPE*> CTypedPtrList<CPtrList, TYPE*> CTypedPtrMap<CMapPtrToPtr, KEY, VALUE> CObArray (对象指针数组)CPtrArray (void 指针数组)CStringArray (字符串数组)CByteArray (字节数组)CWordArray (字数组)CDWordArray (双字数组)CObList (对象指针列表)CPtrList (void 指针列表)CStringList (字符串列表)
6.2 文件类体系 1 2 3 4 5 6 7 8 9 10 CFile (文件基类) ├── CMemFile (内存文件) ├── CSharedFile (共享内存文件) ├── COleStreamFile (OLE流文件) ├── CSocketFile (套接字文件) ├── CStdioFile (标准I/O文件) ├── CInternetFile (Internet文件) │ ├── CHttpFile (HTTP文件) │ └── CGopherFile (Gopher文件) └── CMirrorFile (镜像文件)
6.3 异常处理类 1 2 3 4 5 6 7 8 9 10 11 12 CException (异常基类) ├── CArchiveException (归档异常) ├── CDaoException (DAO异常) ├── CDBException (数据库异常) ├── CFileException (文件异常) ├── CMemoryException (内存异常) ├── CNotSupportedException (不支持异常) ├── COleException (OLE异常) ├── COleDispatchException (OLE调度异常) ├── CResourceException (资源异常) ├── CUserException (用户异常) └── CInternetException (Internet异常)
6.4 日期和时间类 1 2 3 4 5 CTime (绝对时间) ├── COleDateTime (OLE日期时间) └── COleDateTimeSpan (OLE时间跨度)CTimeSpan (相对时间)
七、MFC高级架构特性 7.1 命令路由机制 1 2 3 4 5 6 7 8 9 10 命令路由路径:1. 活动视图 (Active View)2. 视图所属的框架窗口3. 应用程序对象 (CWinApp)4. 默认窗口过程 (DefWindowProc) 特殊路由:- MDI文档:文档→框架→MDI主框架→应用- OLE在位编辑:OLE服务器→容器
7.2 空闲处理机制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 int CWinThread::Run () { while (::PeekMessage (&m_msgCur, NULL , NULL , NULL , PM_NOREMOVE)) { if (!PumpMessage ()) break ; } while (OnIdle (m_nIdleCount++)) ; m_nIdleCount = 0 ; }BOOL CWinApp::OnIdle (LONG lCount) { if (lCount == 1 ) { UpdateAllViews (NULL ); } else if (lCount == 10 ) { CleanupTempFiles (); return FALSE; } return TRUE; }
7.3 状态管理机制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class CCommandLineInfo : public CObject { enum ShellCommand { FileNew, FileOpen, FilePrint, FilePrintTo, FileDDE, FileNothing = -1 }; };class CRecentFileList : public CObject { virtual void UpdateMenu (CCmdUI* pCmdUI) ; virtual void ReadList () ; virtual void WriteList () ; };
八、MFC扩展和自定义 8.1 自定义消息映射 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 BEGIN_MESSAGE_MAP (CMyWnd, CWnd) ON_WM_PAINT () ON_WM_CREATE () ON_COMMAND (ID_FILE_OPEN, OnFileOpen) ON_UPDATE_COMMAND_UI (ID_FILE_SAVE, OnUpdateFileSave) ON_BN_CLICKED (IDC_BUTTON1, OnButtonClicked) ON_MESSAGE (WM_MYMESSAGE, OnMyMessage) ON_REGISTERED_MESSAGE (WM_MYREGISTERED, OnMyRegistered) ON_EVENT (CMyCtrl, IDC_MYCTRL, 1 , OnMyEvent, VTS_NONE)END_MESSAGE_MAP ()
8.2 自定义运行时类信息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 class CMyCustomClass : public CObject { DECLARE_DYNCREATE (CMyCustomClass) DECLARE_SERIAL (CMyCustomClass) public : CMyCustomClass (); virtual ~CMyCustomClass (); virtual void Serialize (CArchive& ar) ; virtual void AssertValid () const ; virtual void Dump (CDumpContext& dc) const ; CString m_strData; int m_nValue; };IMPLEMENT_DYNCREATE (CMyCustomClass, CObject)IMPLEMENT_SERIAL (CMyCustomClass, CObject, VERSIONABLE_SCHEMA | 1 )void CMyCustomClass::Serialize (CArchive& ar) { CObject::Serialize (ar); if (ar.IsStoring ()) { ar << m_strData; ar << m_nValue; } else { ar >> m_strData; ar >> m_nValue; } }
九、MFC与现代开发 9.1 MFC与ATL集成 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class CMyMFCApp : public CWinApp {public : virtual BOOL InitInstance () { _Module.Init (NULL , AfxGetInstanceHandle ()); } virtual int ExitInstance () { _Module.Term (); return CWinApp::ExitInstance (); } };class CMyDialog : public CDialog { CComControl<CAxWindow> m_axWindow; };
9.2 MFC与.NET互操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #using <System.Windows.Forms.dll> using namespace System;using namespace System::Windows::Forms;class CMyMFCWnd : public CWnd {private : gcroot<Form^> m_dotNetForm; public : void CreateDotNetControl () { m_dotNetForm = gcnew Form (); m_dotNetForm->Text = "嵌入的.NET窗体" ; HWND hWnd = (HWND)m_dotNetForm->Handle.ToPointer (); ::SetParent (hWnd, m_hWnd); } };
十、MFC架构总结 10.1 设计模式应用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 MFC中应用的设计模式:1. 文档/视图模式 (Document/View Pattern)2. 模板方法模式 (Template Method Pattern) - CWinApp::InitInstance() - CDocument::Serialize()3. 观察者模式 (Observer Pattern) - CDocument更新通知所有视图4. 命令模式 (Command Pattern) - 消息映射和命令路由5. 单例模式 (Singleton Pattern) - CWinApp应用程序对象6. 工厂模式 (Factory Pattern) - CDocTemplate创建文档、视图和框架7. 组合模式 (Composite Pattern) - 窗口父子关系管理
10.2 MFC架构优势
完整的Windows API封装 :简化了复杂的Windows编程
成熟的文档/视图架构 :提供了清晰的应用结构
强大的消息映射系统 :简化了消息处理
丰富的控件库 :包含所有标准Windows控件
良好的向后兼容性 :支持老版本代码
10.3 MFC架构局限性
学习曲线较陡 :需要理解复杂的类层次
与现代C++标准有一定差距 :早期设计限制
对新技术的支持有限 :需要额外集成工作
内存管理相对原始 :缺乏现代智能指针
10.4 学习建议
理解Windows编程基础 :掌握消息循环、窗口过程等
深入文档/视图架构 :这是MFC的核心
掌握消息映射机制 :理解MFC的消息处理
实践自定义控件开发 :深入理解MFC工作原理
学习与现代技术集成 :了解MFC与ATL、.NET的互操作
MFC作为Windows桌面开发的经典框架,虽然在现代开发中不再是首选,但理解其设计原理对于深入理解Windows编程、维护遗留代码以及学习框架设计思想仍然具有重要价值。通过创建自定义控件等实践,可以更深入地理解MFC的底层工作机制,为掌握更现代的Windows开发技术打下坚实基础。