是的,这年头还有人在面MFC,问的我一问三不知,真的脚趾抠地太尬了,平时开发的时候还真没思考过这些问题,面完我反手记录面试问题整理答案,面试虽败,但是博文素材有啦,分享给需要的朋友们。

 MFC面经系列:

MFC 面经系列(二):刷新机制、消息流程与控件使用-CSDN博客

MFC 面经系列(三):消息传递函数深度解析-CSDN博客


在 Windows 桌面开发领域,MFC(Microsoft Foundation Classes)作为经典框架,始终是面试中的高频考点。本文整理了 4 个核心面试问题,涵盖 MFC 类层次结构、绘图机制差异及框架对比,帮助开发者深入理解 MFC 的设计思想与实践应用。

一、MFC 类层次结构

MFC 通过面向对象思想对 Win32 API 进行封装,形成了层次清晰的类体系,核心类及其关系如下:

  • 根类:CObject
    MFC 中绝大多数类的基类,提供了序列化、运行时类型信息(RTTI)、动态创建等基础功能。

  • 应用程序类:CWinApp
    派生自 CWinThread,代表整个应用程序,负责程序的初始化、消息循环管理和退出。核心函数InitInstance()是程序入口点。

  • 窗口类:CWnd
    封装了 Win32 窗口的核心功能(句柄、消息处理等),是所有窗口类的基类。派生类包括:

    • CFrameWnd:框架窗口类(如主窗口);
    • CDialog:对话框类;
    • CView:视图类(负责数据显示)。
  • 文档 / 视图类:CDocument 与 CView
    遵循 MVC 模式,CDocument管理数据,CView负责数据可视化,二者通过文档模板(CDocTemplate)关联。

  • 设备上下文类:CDC
    封装了 GDI 绘图功能,派生类CPaintDC(用于WM_PAINT消息)、CClientDC(客户端区域绘图)等简化了绘图操作。

类层次简化示意图
CObject → CCmdTarget → CWinThread → CWinApp
CObject → CCmdTarget → CWnd → CFrameWnd/CDialog/CView

二、OnPaint 与 OnDraw 的区别

MFC 中OnPaintOnDraw是绘图相关的核心函数,二者分工明确但易混淆,关键区别如下:

维度OnPaint()OnDraw()
所属类CWnd及其派生类(窗口类)CView及其派生类(视图类)
功能响应WM_PAINT消息的处理函数实际执行绘图逻辑的虚函数
调用关系主动调用OnDraw()OnPaint()调用,无法直接响应消息
设备上下文通过CPaintDC获取 DC接收CDC*参数直接操作
重载影响若重载需手动调用OnDraw()直接重载即可实现自定义绘图

代码示例

// CView派生类中的默认实现
void CMyView::OnPaint() {
    CPaintDC dc(this);  // 自动管理BeginPaint/EndPaint
    OnDraw(&dc);       // 委托OnDraw执行绘图
}

// 实际绘图逻辑
void CMyView::OnDraw(CDC* pDC) {
    // 从文档获取数据并绘制
    CMyDoc* pDoc = GetDocument();
    pDC->TextOut(10, 10, pDoc->GetData());  // 绘制文本
}

关键点

  • OnPaint是窗口级别的消息处理入口,负责准备绘图环境(如 DC);
  • OnDraw是视图级别的绘图实现,专注于数据可视化;
  • 若手动重载OnPaint而未调用OnDraw,会导致OnDraw失效。

三、OnDraw 的作用机制

OnDraw是 MFC 视图类绘图的核心函数,其工作流程与设计思想如下:

  1. 触发流程

    窗口无效(如被遮挡、大小改变)→ 系统发送`WM_PAINT` → 
    `OnPaint()`被调用 → 创建`CPaintDC` → 调用`OnDraw(CDC*)` → 完成绘图
    
  2. 设备上下文(DC)
    OnDraw通过CDC*参数操作绘图接口(如TextOutLineToBitBlt),无需关注 DC 的创建与释放(由CPaintDC自动管理)。

  3. 与文档的交互
    遵循文档 - 视图分离原则,OnDraw通常从关联的CDocument对象获取数据并渲染,实现 “数据与显示分离”:

    void CMyView::OnDraw(CDC* pDC) {
        CMyDoc* pDoc = GetDocument();  // 获取关联文档
        if (pDoc) {
            // 绘制文档中的数据
            CString data = pDoc->m_strData;
            pDC->TextOut(0, 0, data);
        }
    }
    
  4. 绘图优化
    OnDraw仅需绘制无效区域(由CPaintDC自动限定),减少不必要的绘制操作,提升性能。

四、MFC 与 Duilib 的区别

MFC 和 Duilib 是 Windows 平台下两种不同设计理念的 UI 框架,核心差异如下:

维度MFCDuilib
技术原理封装 Win32 API,基于句柄(HWND)控件基于 DirectUI 理念,无句柄设计,统一绘制
界面布局依赖.rc 资源文件,可视化设计弱基于 XML 配置,支持标签式布局,逻辑与 UI 分离
自定义能力受系统主题限制,重绘成本高完全自定义,支持皮肤、动画、透明效果
资源消耗较高(多窗口句柄)较低(无句柄开销)
适用场景系统工具、工业软件、遗留项目客户端软件(如聊天工具、播放器)、高自定义 UI 场景
开发效率需手动处理消息循环,代码繁琐简化消息处理,XML 布局可实时预览

总结
MFC 适合需深度集成系统功能、对界面要求不高的场景;Duilib 专注于高效开发精美、自定义程度高的 UI,更符合现代桌面应用的视觉需求。

结语

本文整理了 MFC 类层次、绘图机制及框架对比的核心知识点,后续将继续分享 Win32 刷新机制、MFC 消息响应全流程及控件使用等问题。掌握这些基础原理,不仅能应对面试,更能在实际开发中合理选择框架、优化程序性能。


MFC面经系列:

MFC 面经系列(二):刷新机制、消息流程与控件使用-CSDN博客

MFC 面经系列(三):消息传递函数深度解析-CSDN博客

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐