MFC笔记

项目文件配置

.h 放 inc/、.cpp 放 src/,并让编译器正确找到头文件、生成目标文件(.obj)到指定目录,按以下步骤配置(C++ 项目):

目录结构

在项目根目录(.vcxproj 所在文件夹)新建:

1
2
3
4
你的项目/
├── inc/ # 放所有 .h
├── src/ # 放所有 .cpp
└── 项目.vcxproj

常用宏(方便写路径)

  • $(ProjectDir):项目文件夹(.vcxproj 所在)
  • $(SolutionDir):解决方案文件夹
  • $(Configuration):Debug/Release
  • $(Platform):Win32/x64
  • %(Filename):源文件名(不含扩展名)
  • $(IntDir):中间文件的输出目录 $(IntDir)
  • $(TargetName):生成的主输出文件的基名称

项目配置

检查中间目录设置

  • 确保路径格式为:$(SolutionDir)自定义目录\$(Configuration)\

预编译头输出路径

  • 在 ‌配置属性 → C/C++ → 预编译头 中→ 预编译头输出文件‌:

    • 预编译头输出文件‌ → 修改为:$(IntDir)$(TargetName).pch
    • 预编译头文件‌ → 保持默认pch.h(或检查是否与项目实际名称匹配)
      (关键步骤,确保.pch生成路径与中间目录一致,避免路径冲突)

预编译头使用配置(源文件配置)

  • 打开生成预编译头的源文件(通常是pch.cpp):

    • 右键文件 → ‌属性‌ → ‌预编译头‌ → 选择 ‌创建 (/Yc)‌
  • 其他源文件需设置为 ‌使用 (/Yu)‌

  • (确保仅一个文件创建预编译头,其余文件复用‌)

路径宏必须规范‌:

$(IntDir) 必须包含配置名(如\Release\),否则多配置编译会冲突

项目新建筛选器

右键点击源文件或头文件→添加→新建筛选器,如下图所示,其中inc和src就是筛选器:

新建筛选器”(New Filter)是一种‌逻辑分类工具‌,用于在解决方案资源管理器中按功能或模块组织项目文件(如源代码、头文件等),但‌不改变物理磁盘的目录结构‌。

  • 筛选器仅在项目配置文件(.vcxproj.filters)中记录分类关系,不会在磁盘创建实际文件夹。
‌配置项位置‌ ‌作用范围‌ ‌核心功能‌ ‌推荐设置‌ ‌关联文件‌
‌VC++目录 → 包含目录‌ 解决方案全局 所有项目共享的头文件搜索路径 $(WindowsSdkDir)Include$(ProjectDir)ThirdParty\Include 第三方库头文件(*.h)
‌C/C++ → 常规 → 附加包含目录‌ 当前项目 项目专属头文件搜索路径 $(ProjectDir)include$(OutDir)GeneratedHeaders 项目私有头文件版本特定头文件
‌资源 → 常规 → 附加包含目录‌ 资源编译器 资源文件(.rc/.rc2)的头文件搜索 .\resources%(AdditionalIncludeDirectories) .rc2resource.h
‌链接器 → 输入 → 模块定义文件‌ 当前项目 指定模块定义文件路径 $(ProjectDir)linker\test.def .def(DLL导出定义)
‌VC++目录 → 库目录‌ 解决方案全局 所有项目共享的库文件搜索 $(WindowsSdkDir)Lib$(ProjectDir)ThirdParty\Lib .lib(静态库)
‌链接器 → 常规 → 附加库目录‌ 当前项目 项目专属库文件搜索 $(ProjectDir)lib$(Configuration) 配置特定的.lib
‌文件类型‌ ‌作用‌ ‌路径配置要求‌ ‌典型位置‌ ‌注意事项‌
‌.rc2‌ 附加资源脚本(共享对话框/图标等) 必须在‌资源附加包含目录‌中配置路径 /resources
/res
需在主.rc文件中包含:#include “resources/test.rc2”
#include “res/test.rc2”
‌.def‌ DLL导出函数定义 需在‌链接器→模块定义文件‌显式声明 /linker 路径需用宏:$(ProjectDir)linker\test.def
‌resource.h‌ 资源ID定义(对话框/字符串等) 需在‌C/C++附加包含目录‌或‌资源附加包含目录‌配置 /include 多文件时划分ID范围:#define IDD_MAIN 1000-1999
‌.pdb‌ 调试符号文件 通过‌输出目录‌控制:$(SolutionDir)bin$(Platform)$(Configuration)\ /bin 不可手动包含路径
‌.dll‌ 动态链接库 通过‌环境变量‌配置运行时路径:PATH=$(ProjectDir)bin;%PATH% /bin 需与.lib匹配
组合 必须一起放的文件 推荐放哪里 说明
1 xxx.rc resource.h 项目根目录 资源编辑器强制要求,不能分开,全项目只能 1 个 resource.h
2 pch.h pch.cpp 项目根目录 预编译头必须成对
3 对话框.h 对话框.cpp 任意子目录(如 Dialog/) 类的头文件和源文件必须同目录
4 xxx.rc2 + 图标 / 图片资源 推荐放 res/ 文件夹 rc2 不强制和 rc 同目录
设置位置 配置项 填写内容 作用
项目属性 → C/C++ → 常规 附加包含目录 $(ProjectDir) 让编译器找到根目录的 resource.h、pch.h
项目属性 → C/C++ → 常规 附加包含目录 $(ProjectDir)res 找到 res 目录里的 rc2、图片
文件 必须写 作用
pch.h #include “resource.h” 全局生效,所有 cpp 自动找到资源 ID
对话框.h(如 CXLinkDugDlg.h) #include “resource.h” 让对话框类识别 IDD_DIALOG1
xxx.rc #include “resource.h” 资源编辑器自动加,你不用管
对象 设置位置 选项值
整个项目 项目属性 → C/C++ → 预编译头 使用 (/Yu) 头文件:pch.h
pch.cpp 单独 右键 pch.cpp → 属性 → 预编译头 创建 (/Yc)

MFC中与WIN32

窗口 = HWND(句柄)

一切控件都是窗口,都有 HWND。

窗口过程 & 消息机制

父子窗口关系

窗口创建流程

句柄和指针的区别

头文件

MFC类库常用的头文件
afx.h-将各种MFC头文件包含在内
afxwin.h-包含了各种MFC窗口类。包含了afx.h和windows.h。
afxext.h-提供了扩展窗口类的支持,例如工具栏,状态栏等。

MFC控制台程序

和win32的控制台程序的差别
main函数不同于普通的控制台程序
CWinApptheApp;多了一个全局对象
经验之谈:
以Afx开头可以确定为MFC库中的全局函数。
以::开头可以确定为win32的API函数。

MFC窗口类命名规范

类名和资源ID的命名需遵循特定规范,但非绝对强制要求。

类名命名规范

  1. 前缀惯例
    MFC类名通常以大写字母C开头(如CMyViewCMainFrame),这是MFC框架的推荐风格。虽非技术强制,但遵循此惯例可提升代码可读性及与MFC内置类的一致性。
  2. 自定义类名
    创建新类时(如通过‌MFC添加类向导‌),可自由命名,但建议保留C前缀以符合MFC生态习惯。

资源ID命名规则与范围约束

  1. 前缀分类
    MFC通过前缀区分资源类型,例如:
    • IDR_:主框架资源(菜单/图标/快捷键)
    • IDD_:对话框模板
    • IDC_:控件或光标
    • IDS_:字符串资源
      此约定为开发社区广泛采用的标准。
  2. ID数值范围
    为避免冲突,需遵守ID分配区间:
    • 命令ID:0x8000–0xDFFF(如菜单命令)
    • 控件ID:8–0xDFFF(对话框控件)
    • 避免使用MFC保留段:0x7000–0x7FFF0xE000–0xEFFF

默认ID vs 自定义ID的选择

‌场景‌ ‌推荐方案‌
‌简单功能‌ 使用默认ID(如IDOK、IDCANCEL)可节省时间。
‌复杂或协作项目‌ ‌强烈建议自定义语义化ID‌(如IDC_USERNAME_INPUT),便于维护和定位资源。
‌需扩展性‌ 自定义ID更易支持多语言、动态控件等进阶需求。

调试

call statck 查看函数调用关系 MSDN

MFC 控件 ID

对话框控件的查找:GetDlgItem的底层

GetDlgItem(nID)是 MFC 最常用的 ID 查找函数,它的底层逻辑是:

对于对话框(CDialog/CPropertyPage),Windows 系统会维护一个对话框控件列表(内部链表 / 数组结构)

MFC 调用 Windows API GetDlgItem,由系统在该列表中按 ID 匹配查找,返回对应 HWND

MFC 再将 HWND 映射到CWnd对象(通过CWnd::FromHandlePermanent等内部函数)

说明

HWND 窗口句柄(一个 32/64 位整数) 唯一标识一个窗口 / 控件
CWnd MFC 包装类,一个窗口

字符串

写法 含义 字符集 适用场景
"abc" ANSI 字符串 多字节 老项目、不推荐
L"abc" Unicode 字符串 宽字符 Windows API
_T("abc") 自动适配 自动切换 MFC 首选
TCHAR 自动适应字节(条件编译)

L"字符串"

L = Long → 宽字符(Unicode)

  • 每个字符占 2 字节;一个字符两个字节
  • 全世界语言都能显示(中文、日文、韩文)
  • Windows 内核本身就是 Unicode
1
2
3
4
wchar_t* str = L"我是中文";
CString str = L"Hello";
TCHAR *P = L"ABC";
wcslen(p);//这里计算几个字节

_T("字符串")TEXT("xxx")

_T = 自动适配宏(最常用在 MFC)

  • 项目用 Unicode → 自动变成 L"xxx"
  • 项目用 多字节 → 自动变成 "xxx"
  • MFC 标准写法,99% 都用这个
  • TEXT("xxx")_T("xxx") 完全一样
1
CString str = _T("我是MFC标准字符串");

"字符串"(不加任何东西)

ANSI 多字节字符集

  • 中文占 2 字节,英文占 1 字节
  • 不推荐在 MFC 里用
  • 容易出现中文乱码
1
CString str = "我是MFC标准字符串";

_W("xxx")

强制宽字符,很少用

_A("xxx")

强制 ANSI 字符串,很少用

字符转换

3 种核心字符串

"abc" → char*(多字节 / ANSI)

L"abc" → wchar_t*(宽字符 / Unicode)

_T("abc") → 自动适配(项目 Unicode 则 = L””, 多字节则 =””)

句柄: 结构体变量,窗口句柄HWND,图标句柄:HICO

消息队列,消息,消息处理win

LPSTR