MFC(微软基础类库)相关控件详解

文章目录

    • 1.MFC 入门
    • 1.1 为什么学习MFC
    • 1.2 Windows 消息机制
    • 1.2.1 基本概念解释
    • 1.2.2 Windows 编程模型
    • 1.2.3 钩子函数
    • 1.3 MFC 入门
    • 1.3.1 利用 MFC 创建窗口
    • 1.3.2 消息映射
    • 1.4 用向导生成一个MFC
    • 1.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

你可能感兴趣的:(QT,MFC,mfc,c++)