补发:2021-11-13


MFC基础篇

以C++类的形式对WINDOWS API进行封装。

MFC框架理论

关键类

CWinApp:MFC应用程序抽象,管理DocumentTemplate。

CFrameWnd: 框架窗口,负责创建应用主窗口,含标题栏,菜单栏,工具栏,状态栏等 。

CView: 负责展示应用数据,View其实是一个没有边框的窗口, 客户区 。

CDocument: 负责存储应用数据 。

CDocTemplate:DocumentTemplate: 隐藏Boss, 负责管理MainFrame,View和Document。

窗口与窗口对象

关系:

  1. 每个窗口对象都包含一个窗口
  2. 窗口对象使用Create方法创建窗口,在Create方法个中将窗口对象与窗口绑定
  3. 窗口对象的与窗口的生命周期不同,并不同生共死。(menu.Detach()将对象与它绑定在窗口的这一块区域分离(分离窗口对象和窗口))

afx

微软mfx小组。

消息映射

把消息ID和相应函数关联起来。 当这种消息发送出来后,对应的函数就会触发。

BEGIN_MESSAGE_MAP(CMFCApplicationView, CView)
	ON_COMMAND(ID_MSG_DRAW_PEN,&CMFCApplicationView::OnPen)
	ON_COMMAND(ID_MSG_DRAW_RECT,&CMFCApplicationView::OnRect)
    ......
END_MESSAGE_MAP()

重绘

元文件

元文件(Metafile)是记录所有"绘图指令"的集合,拥有录制,重放的功能。

view文件中的代码示例:

	//声明一个Metefile的对象
	HMETAFILE	metafile;
	//结束录制,保存文件
	metafile = m_dcMetaFile.Close();
	//重放文件
	pDC->PlayMetaFile(metafile);
	//准备一个新的录制
	m_dcMetaFile.Create();
	//在新的录制中重放旧元文件  
	m_dcMetaFile.PlayMetaFile(metafile);
	//删除元文件
	DeleteMetaFile(metafile);
	//无效界面-请求重绘
	Invalidate();

兼容设备描述表

兼容设备是一种内存设备,在显示图像的过程中,可以先在内存中准备这些图像,之后可以直接拷贝内存数据到真实的设备中,完成图像的显示。

起到一个二次缓冲的效果

自定义重绘

定义一个类,略…。

文件

文件读写

写入文件

void CMFCApplicationView::OnFileWirte()
{
	// TODO: 在此添加命令处理程序代码
	CString hello = _T("hello world\n");
	//打开文件对话框
	CFileDialog fileDlg(FALSE);

	if (IDOK==fileDlg.DoModal())
	{
		//获取对话框返回的文件名
		//打开文件
		//写入文件
		//关闭文件
		CString path = fileDlg.GetPathName();
		CFile file(path, CFile::modeWrite | CFile::modeCreate);
		int len = hello.GetLength()* sizeof(TCHAR);
		file.Write(hello, len); 
		file.Close();
	}
}

读取文件

void CMFCApplicationView::OnFileRead()
{
	// TODO: 在此添加命令处理程序代码
	CFileDialog fileDlg(TRUE);
	if (IDOK == fileDlg.DoModal())
	{
		//获取文件名
		CString path = fileDlg.GetPathName();
		//以读取方式打开文件
		CFile file(path, CFile::modeRead);
		//准备缓冲区
		TCHAR* pBuf;
		int cnt = file.GetLength();
		int chars = cnt / sizeof(TCHAR);
		pBuf = new TCHAR[chars + 1];
		//读取文件内容到缓冲区
		file.Read(pBuf, cnt);
		//设置字符串结束位置
		pBuf[chars] = 0;
		MessageBox(pBuf);
		file.Close();
		delete[] pBuf;
	}
}

类的序列化

类的序列化是将程序中对象以一种二进制格式存放到设备中,如文件/数据库等,以实现"永生"或随意"流动"。

  • 类要从CObject派生,或是CObject的派生类派生
  • 实现Serialize方法
  • 在类声明中使用DECLARE_SERIAL宏
  • DECLARE_SERIAL(类名)
  • 定义不带参数的构造函数
  • 在类实现中添加IMPLEMNET_SERIAL宏
  • IMPLEMNET_SERIAL(类名,父类名,版本号)

常用控件

与使用者进行交互。

  • 获得控件
GetDlgItem(控件ID)获取相应的控件
  • 通过绑定控件和变量
使用
UpdateData(TRUE|FALSE)同步, 
默认为True,将控件内容同步到变量,FALSE,将变量同步回控件

按钮

Radio Button——单选

Check Box——多选

响应事件,如点击按钮时间.

示例:多选按钮。

void CContrlObjectDlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	UpdateData();//同步控件与变量
	CString str;
	str.Format(_T("上衣=%d\n裤子=%d\n鞋子=%d\n"),m_clothes,m_pants,m_shoes);
	MessageBox(str);
}

多选按钮
image-20211112181938778

文本框和列表

  • List Box——列表
  • Edit Control——文本框

示例:将文本框的内容放到列表中

void CContrlObjectDlg::OnBnClickedButton2()
{
	// TODO: 在此添加控件通知处理程序代码
	//获取文本框中的内容
	CString text;
	//得到文本框对象
	CEdit* edit = (CEdit*)GetDlgItem(IDC_EDIT1);
	//将文本框中的文字存放到text中
	edit->GetWindowText(text);	
	//得到列表对象
	CListBox* list = (CListBox*)GetDlgItem(IDC_LIST1);
	//将文本框中的文字添加到列表框中
	list->AddString(text);
	//清空文本框的输入框
	edit->SetWindowText(_T(""));
}

image-20211112185648190

示例2
查看在列表中选择了什么

void CContrlObjectDlg::OnBnClickedButton2()
{
	// TODO: 在此添加控件通知处理程序代码
	//储存获取的内容
	CString text;
	CListBox* list = (CListBox*)GetDlgItem(IDC_LIST1);
	//获取当前在列表中的选择,返回一个整型,该选项在列表中的位置 
	int n = list->GetCurSel();
	//返回选项放到text中
	list->GetText(n,text);
	MessageBox(text);
}

下拉列表

  • ComboBox——下拉列表

类似于ListBox,基本上操作一直,只是ListBox直接展开所有选项,而ComboBox需要点开查看。

示例

void CContrlObjectDlg::OnBnClickedButton2()
{
	// TODO: 在此添加控件通知处理程序代码
	//储存获取的内容
	CString text;
	CComboBox* list = (CComboBox*)GetDlgItem(IDC_COMBO1);
	int n = list->GetCurSel();
	list->GetLBText(n,text);
	MessageBox(text);
}

进度条

  • Progress Control——进度条

示例

BOOL CContrlObjectDlg::OnInitDialog()中
    
//得到进度条控件
CProgressCtrl* prog = (CProgressCtrl*)GetDlgItem(IDC_PROGRESS1);
//设置范围
prog->SetRange(0,100);


//根据条件进行进度条的变动
prog = (CProgressCtrl*)GetDlgItem(IDC_PROGRESS1);
num = prog->GetPos();
prog->SetPos(++num);
prog->GetRange(low, high);
if (num>= high)
{
    prog->SetPos(low);
}

图片

  • Picture Control——图片
BOOL CMFCPicODlg::OnInitDialog()中

//例如:加载bitmap,以局部变量的方式
BitMap bitmap;    
m_bitmap.LoadBitmap(IDB_BITMAP1);
m_pic.SetBitmap(m_bitmap);
bitmap.Detach();

表格

  • List Control

例如:Windows文件查看

image-20211113082415733

示例

//绘制表头
	m_list.InsertColumn(0, _T("ADDRESS"), LVCFMT_LEFT, 400);
	m_list.InsertColumn(0, _T("AGE"), LVCFMT_LEFT, 50);
	m_list.InsertColumn(0, _T("NAME"), LVCFMT_LEFT, 100);
	m_list.InsertColumn(0, _T("ID"), LVCFMT_LEFT, 50);

	//插入第一行数据
	int index;
	index = m_list.InsertItem(0, _T("0001"));
	m_list.SetItemText(index, 1, _T("kenny"));
	m_list.SetItemText(index, 2, _T("26"));
	m_list.SetItemText(index, 3, _T("Franch"));

	//插入第二行数据	
	index = m_list.InsertItem(1, _T("0002"));
	m_list.SetItemText(index, 1, _T("olofm"));
	m_list.SetItemText(index, 2, _T("29"));
	m_list.SetItemText(index, 3, _T("Sweden"));

image-20211113093242047

  • Tree Control

示例:

HTREEITEM root;
HTREEITEM first_sub;
HTREEITEM second_sub;
m_tree.ModifyStyle(0, TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT);
root = m_tree.InsertItem(_T("Root"));
//root的子节点
first_sub = m_tree.InsertItem(_T("First_Sub"), root);
//与first同级的四个
m_tree.InsertItem(_T("1"),root);
m_tree.InsertItem(_T("2"),root);
m_tree.InsertItem(_T("3"),root);
m_tree.InsertItem(_T("4"),root);
//first的子结点
second_sub = m_tree.InsertItem(_T("Second"),first_sub);
//second的四个子节点
m_tree.InsertItem(_T("5"), second_sub);
m_tree.InsertItem(_T("6"), second_sub);
m_tree.InsertItem(_T("7"), second_sub);
m_tree.InsertItem(_T("8"), second_sub);

image-20211113104231000

引入、加载图片

//当前2张,还能加4张
m_imgList.Create(32, 32, ILC_MASK | ILC_COLOR32, 2, 4);
for (int i = 0; i < 2; i++)
{
    HICON icon = theApp.LoadIcon(IDI_ICON1+i);
    m_imgList.Add(icon);
}
m_tree.SetImageList(&m_imgList,TVSIL_NORMAL);
//这两个1分别代表的属性
//分别是:未选中时显示哪张图片,被选中时显示哪在张。
m_tree.InsertItem(_T("1"),1,1,root);
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐