MFC(微软基础类库)相关控件详解
2025-07-22 07:05:28 拉莫斯世界杯
文章目录
1.MFC 入门1.1 为什么学习MFC1.2 Windows 消息机制1.2.1 基本概念解释1.2.2 Windows 编程模型1.2.3 钩子函数1.3 MFC 入门1.3.1 利用 MFC 创建窗口1.3.2 消息映射1.4 用向导生成一个MFC1.5 MFC 的库程序1.6 拓展知识点2.基于对话框编程2.1模态对话框2.2非模态对话框3.常用控件3.1 静态文本控件3.2 编辑框控件3.3 下拉框控件3.4 列表控件3.5 树控件3.6 页控件4. 实例项目
1.MFC 入门
1.1 为什么学习MFC
如果你是在Windows 平台上做GUI开发,MFC (微软基础类库)是一个很好的选择,毕竟Windows累计用户群庞大,市场接收程度高。
但是,学习MFC 不仅仅要学习用MFC,还要学习MFC的框架设计思想。
很多公司在一些做了很久的项目上,往往都是有自己的类库、自己的框架,我们只需要在其基础上不断的完善和扩展。如果你不了解类库,你是根本无从下手。这也是我们学习类库、框架设计的原因。
如果仅仅会用MFC的话,可能在找工作的时候,一旦工作内容离开了MFC,就什么也不会了。学习任何东西都是一样的,学的是方法,而不仅仅是某个技术本身,因为技术肯定不停地更新的,你今天学的现在能用上,但是谁也不能保证以后会怎么样,但是万变不离其宗,懂得了方法,学什么都一样。
1.2 Windows 消息机制
MFC六大关键技术包括: MFC Initialization —— MFC程序的初始化过程 RTTI(Runtime Type Information)—— 运行时类型识别 Dynamic Creation —— 动态创建 Persistence ——永久保存(串行化、序列化) Message Mapping —— 消息映射 Message Routing —— 消息传递
1.2.1 基本概念解释
要想熟练掌握Window 应用程序的开发,首先需要理解Windows 平台下程序运行的内部机制,如果想要更好的学习掌握MFC,必须要先了解Windows 程序的内部运行机制,为我们扫清学习路途中的第一个障碍,为进一步学习MFC 程序打下基础。
1)SDK 和 API SDK : 软件开发工具包(software development kit),第三方写好的东西 API 函数: Windows 操作系统提供给应用程序的接口(Application programming interface) 常用的头文件: afx.h 将各种mfc头文件包含在内 afwin.h 包含了各种mfc窗口类。包含了afx.h和windows.h afext.h 提供了扩展窗口类的支持,例如工具栏,状态栏等
2)窗口和句柄 窗口:标题栏、菜单栏、系统菜单、最小化框、最大化框、可调边框
句柄:就是各种各样的资源(窗口、图标、光标等),系统创建这些资源时,会为它们分配内存,并返回标识这些资源的标识号
3)消息与消息队列 操作系统-》消息队列-》应用程序-》分发消息-》操作系统-》窗口函数(回调函数) 消息映射
4) WinMain 函数(参数传递顺序, 从右至左,以此入栈) 当 Windows 操作系统启动一个程序时,它调用的就是该程序的WinMain 函数(实际是由插入到可执行文件中的启动代码调用的)。
WinMain 是 Windows 程序的入口函数,与DOS 程序的入口函数 main 的作用相同,当 WinMain 函数结束或者返回时,Windows 应用程序结束。
经验之谈: 以Afx开头可以确定为MFC 库中的全局函数 以 ::(匿名空间) 开头可以确定为win32 的API 函数, 库函数可以直接调
1.2.2 Windows 编程模型
一个完整的Win32 程序(#include
#include
//6、处理消息(窗口过程)
LRESULT CALLBACK WindowPro( HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
//传参的传递顺序,从右至左 以此入栈,并且在函数返回前 清空堆栈
int WINAPI WinMain(
HINSTANCE hInstance,//应用程序实例句柄
HINSTANCE hPrevInstance,//上一个应用程序句柄,在win32环境下,参数一般为NULL,不起作用了
LPSTR lpCmdLine, //char* argv[]
int nShowCmd)//显示命令 最大化,最小化
{
//1、设计窗口
WNDCLASS wc;
wc.cbClsExtra = 0;//类的额外的内存
wc.cbWndExtra = 0;//窗口额外的内存
wc.hbrBackgroud = (HBRUSH)GetStockObject(WHITE_BRUSH); // 设置背景
wc.hCursor = LoadCursor(NULL, IDC_HAND);//设置光标
wc.hIcon = LoadIcon(NULL, IDI_ERROR);//图标
wc.hInstance = hInstance;//应用程序实例句柄, 传入winMain中的形参即可
wc.lpfnWndProc = WindowProc;//回调函数 窗口过程
wc.lpszClassName = TEXT("WIN");//指定窗口类名称
wc.lpszMenuName = NULL;//菜单名称
wc.style = 0; //显示风格 0 代表默认风格
//2、注册窗口
RegisterClass(&wc);
//3、创建窗口
CreateWindow(wc.lpszClassName, TEXT("WINDOWS"), WS_OVERLAPPEDWINDOW);
//4、显示和更新
ShowWindow(hwnd, SW_SHOWNORNAL);
UpdateWindow(hwnd);
//5、通过循环取消息
MSG msg;
while (1)
{
if (GetMessage(&msg, NULL, 0, 0) == FALSE)
{
break;
}
//翻译消息
TranslateMessage(&msg);
//分发消息
DispatchMessage(&msg);
}
return 0;
}
1.2.3 钩子函数
创建钩子
HHOOK SetWindowsHookEx(
int idHook, //钩子类型(WH_CBT)窗口创建消息
HOOKPROC lpfn, //钩子处理函数
HINSTANCE hMod, // 应用程序实例句柄
DWORD dwThreadId //线程ID
);
钩子处理函数
LRESULT CALLBACK CBTProc(
int nCode, //钩子码(HCBT_CREATEWND)
WPARAM wParam, //刚刚创建成功窗口句柄
LPARAM lParam //...
);
更改窗口处理函数
LONG_PYR SetWindowLongPtr(
HWND hWnd, //窗口句柄
int nIndex, //GWLP_WNDPROC
LONG_PTR dwNewLong //新的窗口处理函数名(函数地址)
);
1.3 MFC 入门
1.3.1 利用 MFC 创建窗口
mfc 头文件 afxwin.h 自定义类 继承 与 CWinApp 应用程序类 MyApp app 应用程序对象,有且仅有一个 程序如果 InitInstance 入口里 创建窗口 窗口类 MyFrame 继承于 CFrameWnd MyFrame 构造中 Create (NULL, 标题) 创建窗口对象 显示 和 更新
单文档视图架构程序 CWinApp - 应用程序类,负责管理应用程序的流程 CFramWnd - 框架窗口类,负责管理框架窗口 CView - 视图窗口类, 负责显示数据 CDocument - 文档类, 负责管理数据
多文档视图架构程序 CWinApp - 应用程序类 CMDIFrameWnd - 多文档主框架窗口类 CMDChildWnd - 多文档子框架窗口类 CView - 视图窗口类,显示数据 CDocument - 文档类, 管理数据
对话框应用程序 CWinApp - 应用程序类 CDialog - 对话框窗口类
1.3.2 消息映射
消息映射是一个将消息和成员函数相互关联的表。比如,框架窗口接收到一个鼠标左击消息,MFC 将搜索该窗口的消息映射,如果存在一个处理 WM_LBUTTONDOWN 消息的处理程序,如果存在一个处理WM_LBUTTONDOWN 消息的处理程序,然后就调用OnLButtonDown。 类内声明宏 DECLARE_MESSAGE_MAP() 类外实现宏 BEGIN_MESSAGE_MAP()//开始 END_MESSAGE_MAP()//结束
CString str; str.Format(TEXT(“x = %d, y = %d”), point x, point y);
1.4 用向导生成一个MFC
5) 利用向导创建 Visual C++ -》 MFC 应用 -》单个文档,MFC 标准 创建生成四个文件: Cmfc_GuideView 显示 相片,覆盖相框 视类 Cmfc_GuideApp Cmfc_GuideDoc CMainFrame
视图-》类视图(上边框双击显示.h, 下边框双击显示.cpp) 1、添加事件: 上边框 选中 右键 属性(消息 、 事件) => 可添加可删除 左键点击: WM_LBUTTONDOWN
MainFrame 相当于相框 在这个里面添加消息 会被 View类 给覆盖掉 View 相当于相片
注释快捷键: 选中你要注释的内容 ctrl + k, ctrl + c 取消注释快捷键: 选中你要注释的内容 ctrl + k, ctrl + u
实例代码:显示编辑框坐标 CString str; str.Format(TEXT(“x = %d, y = %d”), point.x, point.y); MessageBox(str);
画图: view 类 里面有两个 OnDraw 、 OnPaint OnDraw: pDC->TextOutW(100, 100, TEXT(“为了部落”));//显示位置 + 内容
OnPaint: (消息创建) dc->TextOutW(100, 100, TEXT(“为了联盟”));//显示位置 + 内容
如果有了 OnDraw 不要再有OnPaint 了, 同时存在的话 OnPaint 会把OnDraw 覆盖掉
OnCreate 与 Create 的区别: Create() 负责注册并产生窗口, 像动态创建控件中的Create() 一样,窗口创建之后会向操作系统发送 WM_CREATE 消息。 OnCreate() 不产生窗口,只是在窗口显示前设置窗口的属性如风格、位置等。 OnCreate() 是消息WM_CREATE 的消息响应函数。
创建窗口:Create() -》 发送消息:WM_CREATE -》 响应消息:On_Create()
1.5 MFC 的库程序
使用MFC 制作自己的静态库程序MFC 的动态库 使用静态的MFC 库制作自己的动态库 使用动态的MFC 库制作自己的动态库MFC 扩展库 规则库可以被各种程序所调用扩展库只能被MFC 程序调用
1.6 拓展知识点
MFC 中后缀名为 Ex 的函数 都是扩展函数 在 MFC 中, 以 Afx 为前缀的函数都是全局函数, 可以在程序的任何地方调用它们。
复习: TEXT自适应编码的转换 统计字符串长度 strlen() 统计宽字节的字符串长度 wcslen()
char * 与 CString 之间的转换 char * p3 = “ccc”; CString str = CString(p3);
CStringA tmp; tmp = str; char* pp = tmp.GetBuffer();
==================================================
string 与 char* .c_str()
2.基于对话框编程
对话框是一种特殊类型的窗口,绝大多数Windows 程序都通过对话框与用户进行交互,在Visual C++中,对话框即可以单独组成一个简单的应用程序,又可以成为文档/视图结构程序的资源。
模态对话框:创建出来框之后,不能对其他的对话框进行出来(有关联) 非模态对话框:创建出来框之后,可以对其他对话框进行操作(之间没有关联)
2.1模态对话框
工程创建: 基于对话框-》 MFC 标准-》后续操作默认即可 生成两个文件: CMy01DiagApp 继承于 CVinApp 应用程序类 CMy01DiagDlg 对话框类 也是我们的视类
双击 .rc 文件 -》 资源视图 选择UI 界面 -》 右键 -》属性 Caption 对话框标题 Button 按钮 修改名称:1、右键属性 -》 Caption 2、直接修改(双击无法编辑按钮名称,会创建消息) 模态对话框 ID : IDD_EXEC 非模态对话框 ID : IDD_Show 再创建一个对话框:资源视图 -》 Diaglog -》 插入 Diaglog(E) -》 选择IDD_DIALOG2 -》 修改ID 现在还只是设计完成UI 界面, 还得添加 cpp, h 文件 一个总的对话框,两个按钮:模态对话框,非模态对话框
模块对话框 -》 UI 界面右键 -》添加类 -》类名: CDlgEXEC -》完成 会在类视图中,生成一个 CDlgExec 类 总的对话框:(添加事件的三种方式) 1、UI界面右键 属性-》 控件事件(闪电图标) -》BN_CLICKED 2、右键-》添加事件处理程序(A) 3、直接双击
//第一步,引用头文件 CDlgExec.h
//第二步,在处理事件中添加程序
CDlgExec dlg;//阻塞
dlg.DoModal();
2.2非模态对话框
也得将另一个非模态对话框 添加类 CDlgShow 双击主对话框中的,非模态对话框的按钮,添加处理事件:
//CDiaglogDlg.cpp 中 添加头文件
CDlgShow dlg;//局部变量,非阻塞,出现的现象是一闪而过
//解决方法:作为成员变量,或者new 一个
dlg.Create(IDD_Show);//创建窗口只能创建一次,多次会崩溃
//解决方法:放到构造函数中,或者初始化函数中CDialogDlg.cpp -》 OnInitDialog() -》 在此添加额外的初始化代码
dlg.ShowWindow(SW_SHOWNORMAL);//显示
3.常用控件
3.1 静态文本控件
***补充知识:设定项目启动项 解决方案01 CDiaglog -》 属性 -》 当前选定内容
静态文本控件:Static Text 修改标签文本:1、右键 属性 -》 Caption 2、直接写 UI界面布局: 1、添加一个标签,名称:呵呵 2、添加两个按钮: 一个命名为 哈哈, 另一个命名为 呵呵
标签: 添加变量,ID_STATIC 不能添加变量 需要改 ID名 ID_TEXT,不以 STATIC 结尾即可 两个按钮:添加处理事件
添加变量为 Control 访问权限 private 变量名:m_text
//设置标签文本内容:
m_text.SetWindowTextW(TEXT("呵呵"));
//获取标签文本内容:
CString str;
m_text.GetWindowTextW(str);
//用static text 设置图片
m_pic.ModifyStyle(0xf, ss_bitmap | ss_centerimage);
#define HBMP(filepath, height) (HBITMAP)LoadImage(AfxGetInstanceHandle(), filepath, IMAGE_BITMAP, width, height, LR_LOADFROMFILE | LR_CREATEDIBSECTION)
//宽高设置
CRect rect;
m_pic.GetWindowRect(rect);
//静态控件设置bitmap
m_pic.SetBitmap(HBMP(TEXT("./1.bmp"), m_pic.Width(), m_pic.Height()));
//设置点击状态
m_btn.EnableWindow(FALSE);//禁用
3.2 编辑框控件
编辑框:Edit Control 单行和多行都是这个控件 输入东西之后回车,会关闭窗口,这算是一个bug 解决方法:类视图 -》 属性 -》重写(添加On_OK)-》进行注释即可
设置多行: Multiline True 想要回车换行:Want Return True
水平无限输 Auto HScroll True 垂直无限输 Auto VScroll True
水平滚动条 Horizontal Scroll 垂直滚动条 Vertical Scroll
类向导: 可以查看所有变量的名称
exit(0); // 退出程序
//退出当前对话框 //CDiaglog::OnOK();
编辑框:使用方式2 编辑框 -》 右键属性 -》添加变量 -》 类别 Value 变量类型 CString 访问 Private //设置内容 m_text = TEXR(“哈哈”);
//将变量内容 同步到控件中 UpdateData(FALSE);
=============================== //将控件内容 同步到变量中 UpdateData(TRUE);
//获取内容 MessageBox(m_text);
3.3 下拉框控件
下拉框 Combo Box 添加选项:属性 Data 用分号进行分割 不允许编辑:属性 Type Drop List 排序: 属性 Sort 右键-》添加变量-》 Control CComBox 点击完成
初始化: m_cbx.AddString(TEXT(“唐僧”));//添加下拉框 m_cbx.AddString(TEXT(“猪八戒”)); m_cbx.AddString(TEXT(“沙僧”)); m_cbx.AddString(TEXT(“孙悟空”));
m_cbx.SetCurSel(0);//设置默认选项
m_cbx.InsertString(4, TEXT(“白龙马”));//插入 插到最后
m_cbx.DeleteString(2);//删除 删除沙僧
CString str; m_cbx.GetLBText(1, str);//获取下标索引值的具体内容 MessageBox(str);
//更换选项 触发事件 CBN_SELCHANGE
int index = m_cbx.GetCurSel();//获取当前索引位置
CString str;
m_cbx.GetLBText(index , str);//获取下标索引值的具体内容
MessageBox(str);
3.4 列表控件
列表 list control 显示方式: 属性 View Report(报表模式) 、Icon、List 添加变量 -》 control
CString str[] = {TEXT(“姓名”), TEXT(“性别”),TEXT(“年龄”)};
for(int i = 0; i < 3; ++i) { //设置表头 参数:1 索引 2 内容 3 对齐方式 4 列宽度 m_list.InsertColumn(i, str[1], LVCFMT_LEFT, 100); } //设置正文 //表头不算正文里的内容, 索引从0 开始 m_list.InsertItem(0, TEXT(“张三”)); //给这个Item 插入其他列的值 m_list.SetItemText(0, 1, Text(“男”)); m_list.SetItemText(0, 2, Text(“23”));
//设置属性 整行选中状态 显示网格 m_list.SetExtendedStyle(m_list.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES)
3.5 树控件
树控件 CTreeControl 类似于以前QQ 用户名的一个排列 Has Lines 有虚线连接 Has Buttons 有这个折叠的小按钮 Lines At Root 根节点也要有这个线
添加变量 -> control Icon ->添加资源 -》ICON -> 导入
//1、设置图标 HICON icons[4]; icons[0] = AfxGetApp()->LoadIconW(IDI_ICON1); icons[1] = AfxGetApp()->LoadIconW(IDI_ICON2); icons[2] = AfxGetApp()->LoadIconW(IDI_ICON3); icons[3] = AfxGetApp()->LoadIconW(IDI_ICON4);
CImageList list;//需要作为成员变量才能显示图片
//创建图片集合 list.Create(30 , 30, ILC_COLOR32, 4, 4); //添加具体图片 for(int i = 0; i < 4; ++i) { list.Add(icons[i]); } m_tree.SetImageList(&list, TVSIL_NORMAL);
//2、设置节点 HTREEITEM root = m_tree.InsertItem(TEXT(“根节点”), 0,0,NULL); HTREEITEM parent = m_tree.InsertItem(TEXT(“父节点”), 1,1,root ); HTREEITEM sub1= m_tree.InsertItem(TEXT(“子节点”), 2,2,parent ); HTREEITEM sub2= m_tree.InsertItem(TEXT(“子节点”), 3,3,parent );
//设置默认选项 m_tree.SelectItem(sub1);
//切换选项触发事件 UI 控件-》属性 -》控件事件-》TVN_SELCHANGED
//获取当前项 HTREEITEM item = m_tree.GetSelectedItem(); CString name = m_tree.GetItemText(item);
3.6 页控件
标签页 TabControl
创建 对话框 DIALOG1 取出边框 Border: None 显示方式 style: child 类似模态与非模态 ui 设计: 创建两个对话框,和一个tab 页 两个对话框 需要创建类,并且设置边框,以及出现方式 而tab 页是 创建变量
m_tab.AddPage(TEXT(“系统管理”), &dlg1, IDD_DLALOG1); m_tab.AddPage(TEXT(“系统设置”), &dlg2, IDD_DLALOG2); //显示 m_tab.Show();
4. 实例项目
创建项目 配置项目 图标的配置 由于微软在VS2013 中不建议再使用 C/C++ 的传统函数 scanf、strcpy等,所以直接使用这些库函数会提示 C4996 错误。 加宏就可以解决这样的问题 _CRT_SECURE_NO_WARNINGS 预定义添加
设置图标(相册上 MainFrm.cpp) SetClassLong(m_hWnd, GCL_HICON, (LONG)AfxGetApp()->LoadIconW(IDI_ICON_WIN));
设置标题 setTitle(TEXT(“销售管理系统”));// mainFrm 右标题
setTitle(TEXT(“销售管理系统”));//CSaleSystemDoc -> OnNewDocument() 左标题
//设置窗口大小及位置
MoveWindow(0, 0, 800, 500);
//设置居中显示
CenterWindow();
创建一个登陆对话框:编辑框 用户 user ,密码 password,登陆按钮,取消按钮 同步到控件中 UpdataData(FALSE); 控件同步到变量 UpdataData(TRUE);
初始化 对话框里面的内容: CLOGOIN-> 属性 重写 ->OnInitDialog()
解决编辑框点击回车直接进入的问题: CLOGOIN->属性 重写 -》 OnOK()
解决点击× 按钮,直接显示界面问题: CLOGOIN->属性 消息-》 WM_CLOSE -> 直接退出 exit(0);
静态拆分窗口: 自定义两个类; CSelectView 和 CDisplayView