MFC框架
一、
需要掌握的技能:
调试的方法有很多,比如像win32呢,增加一个dos窗口
断点调试 :F9 设置断点 F10执行下一步 F11进入函数内部
使用call statck(中文叫调用工具栈)查看函数之间的调用关系
熟悉使用向导(比如建项目的时候,每一个界面都要选择)工具(比如)
借助于MSDN
二、MFC概念和作用
MFC概念:MircorsoftFoundation Class Libary,我们称为微软基础类库
它封装了windows用用程序的各种API和相关机制的C++类库
总结:
1.MFC是一个大的类库(既有动态库,也有静态库)
2.MFC是一个应用程序框架,MFC把程序的流程都给封装了
为什么需要MFC?
基于应用程序框架之上,使用提供的类库快速开发,提高项目的开发效率,减小开发周期和成本
常用的头文件:
afx.h -将各种MFC头文件包含在内(使用类的声明都在这个头文件里) 因为afx它内部用include这个预处理指令将其他mfc头文件包含里面,类似于windows32 中的windws.h大集合了
afxwin.h 包含了各种MFC窗口类。包含afx.h和windows.h比afx包含更多,有了它mfc的封装的类随便用
afxext.h-提供了扩展口类的支持,例如工具栏、状态栏。因为最初mfc并没有这些封装的这些类的
. . .
afxwin.h和afxext.h基本包含了全部了,只有小数的库的要自己包含头文件了
三、MFC程序的分类
能调用MFC程序
1、MFC控制台程序:选中解决方案>右键> 添加>新建项目->桌面项目导->(命名)->控制台程序(勾选MFC标头)
MFC控制台和win32的控制台程序的差别main( )函数不同参数不同
main函数不同于普通的控制台程序
CWinApp theApp; 多了一个全局对象
经验之谈:以Afx开头可以确定是MFC库中的 全局函数(不属于那个类,直接可以使用不用对象点) 因为MFC类里面封装的很多函数和win32封装的很多函数同名所以所以为了区分你是调用win32api还是MFC
以 : : 开头可以确定为win32的API函数
2、MFC的库程序
使用MFC制作自己的静态库程序:做一个静态库(可以调用MFC里面的东西) :选中解决方案>右键> 添加>新建项目->桌面项目导->(命名)->静态库(勾选MFC标头)
MFC的动态库(规则库,功能库 )
使用静态库MFC制作自己的动态库 选中解决方案>右键> 添加>新建项目-> MFC动态链接库>共享MFC DLL 常规
使用动态库的MFC制作自己的动态库
MFC拓展库(类型库)
规则库可以被各种程序所调用,拓展库只能被MFC程序调用 :选中解决方案>右键> 添加>新建项目-> MFC动态链接库>MFC 拓展 DLL
3、MFC的窗口程序 :win32不能调用MFC里面的东西,但是MFC能调用win32里面的东西
MFC把窗口程序分的更细一下:
3.1 单文档视图框架程序 创建 :选择解决方案>右键>添加>新建项目>MFC应用程序
CWinApp - 应用程序类,负责管理应用程序的流程
CFrameWnd - 框架窗口类,负责管理框架窗口
CView-视图窗口类(没有标题,没有菜单),负责显示数据 > 实际上是覆盖了在框架窗口类(客户区)上的白色区域
CDocment-文档类、负责管理数据
3.2 多文档视图框架程序
CWinApp-应用程序类
CMDIFrameWnd-多文档主框架窗口类
CMDIChildWnd- 多文档子框架窗口类
CView -视图类显示数据 多文档视图框架的视图类是在子文档视图框架里面的,覆盖在子窗口的客户区那里了
CDocment 文档类、负责数据管理
3.3 对话框应用程序
CWinApp - 应用程序类
CDialog - 对话框窗口类 CDialogEx 继承CDialog
四、MFC库中类的简介
MFC中封装了几千个类。
CObject类
MFC类库中绝大部分类的父类,提供了MFC类库中一些基本的机制
对运行时类信息的支持
对动态创建的支持
对序列化的支持
这里有三大机制,MFC有6大机制(重中之重)
CWinApp类 应用程序类,封装了应用程序、线程等信息(流程管理)
CDocument类,文档类,管理数据
Frame Windows ,框架窗口类,封装了窗口组成的各种框架窗口(CWnd所有窗口类的最基类)
CSplitterWnd- 用来完成拆分窗口的类>不规则框架类
Control Bars 控件条类
Dialog Boxes -对话框类,封装了各种对话框,通用对话框
Views -视图类,封装了各种显示窗口
Controls -控件类,封装了各种常用的控件
Exceptions - 异常处理类,封装了MFC中常用的各种异常
File -文件类,各种文件的I / O 操作等
绘图类,包含CDC类和CGdiObject类
数据集合类,CArry / Clist / CMap,封装了相应的数据结构的管理
非CObject类的子类
提供了数据结构相关的管理,CPoint,CTime,CString行
MSDN帮助手册
查找 Object (最基类) 拉到低下 找到结构图(Hierarchy Chart)可以看到类的结构
图中可以看出绝大部分都是继承Object ,但是有一些也不是继承Object 像 Internet Server Api 和 Support Classes这些
win32程序和MFC程序区别就是不能使用MFC
五、第一个MFC程序
1、创建一个Win32桌面空项目
2、设置一下开发环境
setting当中设置使用MFC库 : 可以由win32过度到MFC:先创建一个Win32桌面空项目
然后选择该项目属性更改 Use of MFC 选择 Use MFC in a Share DLL 或者 Use MFC in a Share Static就可以由Win32过渡到MFC
写代码:
3、添加 MFC库的头文件 #include <afxwin.h>
4、定义自己的框架类CMyFrameWnd,继承于CFrameWnd类。
新建一个源文件xxx.cpp
class CMyFrameWnd: public CFrameWnd {
};
定义自己的应用程序类CMyWinApp,派生于CWinApp类,并定义构造及重写InitInstance虚函数,在虚函数中创建并显示窗口。
class CMyWinApp:public CWinApp{
//
public: CMyWinApp(){
}
//重写InitInstance虚函数
virtual BOOL InitInstance(){
//在虚函数中创建并显示窗口
CMyFrameWnd* pFrame = new CMyFrameWnd;
pFrame - > Create(NULL,"MFCBase");
m_pMainWnd = pFrame;
pFrame -> ShowWindow(SW_SHOW);
pFrame->UpdateWindow();
return TRUE ;
}
}
定义CMyWinApp类的对象(程序的爆破点)
CMyWinApp theApp;要弄成全局的,不在任何一个类里面
写完以上的就可以运行一个简单的MFC程序了
六、MFC程序启动?
入口函数:
与Win32窗口程序相同,都是从WinMain入口。但是MFC已经实现了WinMain函数,所以在程序中不需要实现
总结:在Win32中WinMain由程序员自己实现,那么流程是程序员安排,但是到了MFC中,由于MFC实现了WinMain,也即是MFC负责安排程序的流程
程序的启动,构造theApp对象,调用父类CWinApp的函数 CMyWinApp theApp; //进入函数的内部
执行流程:
将theApp对象的地址保存到线程状态信息中
将theApp对象的地址保存到模块状态信息中
进入WinMain函数,调用AfxWinMain函数
CWinApp应用程序类(类的作用:管理MFC的流程)的成员 :
InitInstance()-程序的初始化函数、完成了窗口创建等初始化处理(创建和显示窗口)
InitApplication()是应用程序类的成员虚函数(既然虚函数就意味,如果我们自己创建的那个继承应用程序类的子类重写了InitApplicate()提供了覆盖版本了,那么!app->InitApplication()就会调用子类的InitApplition(),如果没有重写那么就会调用父类的 )
InitApplication()一般用来初始化
ExitInstance-程序退出时调用,清理资源等善后工作
Run-消息循环
OnIdle -空闲处理函数
成员变量:
m_pMainWnd -当前应用程序主窗口
创建和显示完成之后就是消息循环了
MFC消息循环在CWinApp类中的消息循环:
pThread ->Run(); //pThread保存的是&theApp Run是 应用程序类的成员虚函数 消息循环
OnIdle(); // 空闲处理
for(; ;) {
while(没有消息的时 ){
OnIdle(. .);//利用theApp对象调用程序类虚函数 做空闲处理
do{
if(GetMessage捉到WM_QUIT)
return this ->Exitstance( ); //应用程序类的成员虚函数 // 程序结束前,利用theApp对象调用程序类虚函数 善后处理
}
while(. . . .)
}
}
七、MFC窗口和消息
钩子简介:是win32的技术,不是MFC的技术:特点有优先勾取消息的权力
创建钩子:
HHOOK SetWindowsHookEx(
int idHook, //钩子类型(WH_CBT<HCBT_CREATEWND>)
HOOKPROC lpfn, //钩子处理函数
HINSTANCE hMod, //应用程序实例句柄
DWORRD dwThreadId // 线程ID
)
钩子处理函数
LRESULT CALLBACK CBTProc(
int nCode, //钩子码(HCBT_CREATEWND); //有很多钩子,比如键盘钩子,鼠标钩子
WPARAM lParam // ....
);
win32api函数
更改窗口处理函数
LONG_PTR SetWindowLongPtr( //更改窗口处理函数
HWND hWnd, // 窗口句柄
int nIndex, // GWLP_WNDPROC 这个参数可以更改处理函数或者更改窗口样式
LONG_PTR dwNewLong // 新的窗口处理函数名(函数地址)
)
MFC窗口创建过程
加载菜单
调用CWnd::CreateEx函数创建窗口
调用PreCreateWindow函数设计和注册窗口类调用AfxDeferRegister函数,在这个函数中设计窗口类:
WNDCLASS wndcls; //设计窗口类
. . .
// 定义一窗口的处理函数为DefWindowProc
wndcls.lpfnWndProc = DefWindowProc;
调用_AfxRegisterWithIcon 函数
在函数内部,加载图标,并调用AfxRegisterClass 函数,在函数内部,调用:RegisterClass win32 Api 函数注册窗口类
::AfxCtx开头的是派遣函数 比如 AfxRegisterClass()会派遣这个注册窗口类
C++有缺省值,
AfxGetInstanceHnadle();可以拿到winMain的第一个值
LRESULT CMyFrame::WindowProc(UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch (msgID)
{
case WM_CREATE:
AfxMessageBox("WM_CREATE消息被处理");
break;
}
return CFrameWnd::WindowProc(msgID,wParam,lParam); //给消息处理默认处理
}
在MFC中如果 重写了一个虚函数最后再调用一下被覆盖的那个版本可以把那些自己不处理的消息交给系统处理
成员虚函数必须给对象调用
MFC 六大机制
程序启动机制
窗口创建机制
消息映射机制
消息映射机制的作用:在继承框架类中添加映射机制
在不重写WindowProc虚函数的大前提下,依然可以处理消息
消息映射机制使用
第一步:类必须具备的要件
类内必须添加声明宏 DECLARE_MESSAGE_MAP();
类外必须添加实现宏
BEGIN_MESSAGE_MAP(Class,baseClass);
END_MESSAGE_MAP();
总结
当一个类具备上述两个要件,这个类就可以按照消息映射机制来处理消息
第二步:消息映射机制的实施:(怎么处理消息?)
以WM_CREATE消息为例:
BEGIN_MESSAGE_MAP(ClassName,BaseClassName);
ON_MESSAGE(WM_CREATE(ID),OnCreate(处理函数名)) //宏
END_MESSAGE_MAP();
第三步:
在CMyFrameWnd类内添加OnCreate函数声明和定义
消息映射机制实现原理
静态成员只属于类,不属于对象(比如自定义的类有静态成员,不代表父类有一样的静态成员)
八、消息的分类
为什么分类:
ON_MESSAGE(ID,自定义的函数名) ON_MESSAGE是非常通用的消息宏,也就是说你可以往里面扔任何的消息ID,无论WM_PAINT,还是WM_CREATE都可以
但是我们平时开发都很小用这个通用宏
标准的windows消息:意思是除了自定义消息和WM_COMMAND外都是标准的windows消息
ON_WM_xxx:比如ON_WM_CREATE()就是专属宏,而且是无参宏
LRESULT OnPaint(WPARAM wParam, LPARAM lParam); //声明
afx_msg int OnCreate(LPCREATESTRUCT pcs); // 这是通过ON_WM_CREATE()在手册里找到的处理函数声明
// afx_msg 可以写上,也可以不写
afx_msg void OnPaint();
afx_msg void OnMouseMove(UINT nKey, CPoint pt); //所有的处理消息这些参数都是从WPARAM 和LPARAM过滤出来的信息,把类型都转换好了
//UINT nKey(WPARAM)会传过来)CTRL、shit这些有没有,CPoint pt(LPARAM)传过来鼠标光标的位置
fx_msg void CMyFrame:: OnMouseMove(UINT nFlags,CPoint cPoint) {
if (nFlags == MK_CONTROL) {
AfxMessageBox("Ctrl_按键被按下");
}
if (nFlags == MK_LBUTTON) {
AfxMessageBox("左键_按键被按下");
}
if (nFlags == MK_SHIFT) {
AfxMessageBox("SHIFT按键被按下");
}
m_x = cPoint.x;
m_y = cPoint.y;
//位置更改之后,让它产生绘图消息InvalidateRect() 产生更新画面InvalidateRect // InvalidateRect 刷新 按指定区域更新区域
/*RECT cRect;
cRect.left = 500;
cRect.right = 500;*/
//cRect.bottom = 500;
//cRect.top = 500;
// 三个参数: 窗口句柄,指定绘图区域,是否擦除
::InvalidateRect(this->m_hWnd,NULL,TRUE);
}
定义消息
ON_MESSAGE
步骤:
1、在顶部 定义宏
#define WM_MYMESSAGE WM_USER +100;
//注意WM_USER好像是1到 1024 系统的定义1到1024不能用 ,但是自定义消息操作系统不知道什么时候发送消息
// ON_WM_CREATE()知道什么时候发消息,但是自定义的不知道如何发消息:
如何发消息 ?
2、发消息: 可以用::PostMessage(this-m_hWnd,WM_MYMESSAGE(自定义消息宏名),1(WPARAM),2(WPARAM))发消息;
3、如何处理消息
命令消息
ON_COMMAND
用于菜单,加速键这些
八、MFC菜单
菜单相关问题
Win32 - HMENU Win32菜单句柄代表菜单
MFC - CMenu类对象 MFC中CMenu类代表菜单(其实CMENU代表不了菜单只是当CMenu 于 菜单句柄HMENU)
CMenu类简介:
封装了关于菜单的各种操作成员函数,另外还封装了非常重要的成员变量m_hMenu(菜单句柄)
MFC中的菜单的使用
第一步:添加菜单资源
添加头文件
#include "resouce.h"
第二步:将菜单设置到窗口,两种方式
(1)利用pFrame调用Create函数时,传参数。Create(NULL,"MFC",WS_OVERLAPPEDWINDOE,CFrameWnd::rectDefault,NULL,(CHAR*)IDR_MEUN1);
(2)在处理框架窗口的WM_CREATE消息是
CMenu menu; //这里不能在 Create函数这里声明如果在函数内声明那么函数介绍菜单会死掉,要在类内成员函数里面声明,那么菜单的生命周期就是和类一样
menu.LoadMenu( IDR_MENU1);
this->SetMenu(&menu);
调用 api通常用句柄,调用成员通常要对象 但是句柄和对象绑定了想用谁就用谁
挂载菜单后:点击菜单项的消息的处理。
加载菜单流程
1、先在项目的的资源文件夹 添加资菜单项目资源,菜单选项在属性添加ID
2、
类内 先声明菜单类 CMenu menu
在OnCreate()里面加载菜单
menu.LoadMenu(IDR_MENU1);
this->SetMenu(&menu);
3、菜单项被点击的消息处理
1、在消息映射里面添加 ON_COMMAND(ID_New(菜单项ID),函数名(要先在头文件或者内类声明));
2、在头文件或者类内声明 函数(返回值 void function( 无))只是负责事件点击
3、类外实现 void function(){ }
命令消息的处理顺序
ON_COMMAND 顺序是 框架类先于应用程序类 , 其他消息都框架类的路线
设置菜单项状态
Win32
WM_INITMENUPOPUP
::CheckMenuItem /::EnableMenuItem (设置能否被勾选)
MFC
ON_WM_INITMENUPOPUP
CMenu::CheckMenuItem / CMenu::EnableMenuItem
//pPopupMenu是下拉的那个对象,
afx_msg void CMyFrame::OnInitMenuPopup(CMenu* pPopupMenu,UINT nIndex,BOOL bSysMenu)
{
//MFC写法
//pPopupMenu->CheckMenuItem(ID_New,MF_CHECKED); //给下拉菜单打勾
//Win32Api写法 // pPopMenu 对象可以拿到m_hMenu成员句柄
::CheckMenuItem(pPopupMenu->m_hMenu,ID_New,MF_CHECKED);
}
右键菜单
Win32:
WM_CONTEXTMENU //消息宏
::TrackPopupMenu //z
MFC:
ON_WM_CONTEXTPopupMenu //消息宏
CMenu::TrackPopupMenu()
// 内类声明处理消息函数,借助手册
afx_msg void OnContextMenu(CWnd* pWnd,CPoint pos); //右键菜单项
// 内外实现消息处理函数
//右键菜单项
afx_msg void CMyFrame::OnContextMenu(CWnd* pWnd, CPoint pos) {
//HMENU hPopUpMenu = ::GetSubMenu(menu.m_hMenu, 0); // 可以获取顶层菜单的某一个菜单项 0是顶层菜单项下的下拉菜单返回值是菜单句柄,拿到大菜单的顶层菜单
Win32显示菜单 Track 小径、路径、跟踪
//::TrackPopupMenu(hPopUpMenu,TPM_LEFTALIGN|TPM_TOPALIGN , pos.x, pos.y,0,this->m_hWnd,NULL); //只能是弹出菜单函数,不是整个菜单函数,注意第一个参数不能用menu.hMenu去拿到菜单句柄(这是整个菜单的,不是单独一个菜单项的句柄)
以上是api的调用
// 以下是MFC的调用
CMenu* pPonpup = menu.GetSubMenu(0); //0是顶层菜单项下的下拉菜单返回值是菜单句柄,拿到大菜单的顶层菜单
pPonpup->TrackPopupMenu(TPM_LEFTALIGN|TPM_TOPALIGN,pos.x,pos.y,this);
}
MFC工具栏及两大机制
工具栏:
工具栏和菜单栏都是 ON_WM_COMMAND()消息的
相关类
CToolBarCtrl父类CWnd,封装了关于工具栏 控件 的各种操作(工具栏是一个容器,里面安装的是一个个工具 按钮)代表的不是工具栏,代表的是一个个的 工具栏的控件
CToolBar-父类CCtrolBar,封装了关于 工具栏 的操作,以及和控件窗口的关系 代表了 工具栏
工具栏是一个窗口(子),框架窗口也是窗口(父) 他们之间还有停靠关系 ,
CWinApp应用程序类只能处理 ON_COMMAND()消息
CFrame框架类消息都可以处理。
工具栏的使用
1、添加工具栏资源 删除工具按钮只有选择如何往外拉就可以幅度大一些。
2、创建工具栏 CToolBar::CreateEx() 创建时机 是在 父窗口的(框架窗口)ON_WM_CREATE() 处理消息创建时创建
3、加载工具栏 CToolBar::LoadToolBar
设置工具栏的停靠
CToolBar::EnableDocking 工具栏(船)想停在哪里
CFrameWnd::EnableDocking 港口(框架窗口)运行工具栏能停在哪里 CToolBar 和CFrameWnd要有交集
CFrameWnd::DockControlBar 设置工具栏临时停在哪里
//工具栏创建时机在 框架创建时创建
int CMyFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {
// 1、父类窗口的对象 // 2、风格但是不是工具栏的风格,是工具按钮的风格。// 3、是工具栏的风格 CBRS_GRIPPER加个点点便于拖拉
toolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP| CBRS_GRIPPER);//创建一个工具栏
toolBar.LoadToolBar(IDR_TOOLBAR1); //加载工具栏资源
// 工具栏想停止哪里 CToolBar是CControlBar的子类,子类调用父类的函数EnableDocking()
toolBar.EnableDocking(CBRS_ALIGN_TOP| CBRS_ALIGN_LEFT);
this->EnableDocking(CBRS_ALIGN_ANY);//父类框架类this调用父类(自身)EnableDocking(CBRS_ALIGN_ANY)允许停任何地方
this->DockControlBar(&toolBar, AFX_IDW_DOCKBAR_LEFT); //父类港口临时停在哪里?
return CFrameWnd::OnCreate(lpCreateStruct);
}
子窗口的创建都是在父窗口的WM_CREATE()时候去创建
框架窗口父类:H要的是句柄 *号要的是对象
再框架下类下的pFrame 对象就是this 是在这个类下的
九、运行时类信息机制
运行时类信息机制的作用
在程序运行过程中可以获知对象的类的相关信息:(例如:对象是否属于某个类)我们应该知道,但是机器不知道某个类的对象
自定义类必须要有这三个要件
1、类必须派生自CObject
2、内类必须添加什么宏 DECLARE_DYNAMIC dyanmic (the Class)//dyanmic 动态的;动力的;动力学的;有活力的 ...
3、类外必须添加实现宏 IMPLEMENT_DYANMIC(the Class, baseClass);
当一个类具备上述三个要件后,CObject::isKindOf函数判断对象是否属于某个类
## 是拼接的意思
# xxx 代表字符串的意思 换成字符串就是“xxx”
IskindOf 执行过程
十、动态创建机制
动态机制的作用
在不知道类名的情况下,将类的对象创建出来
动态机制的使用(就是创建类对象 ,优点就是不知道类名)
必须具备三个条件
派生类必须 继承CObject(直接派生,或者间接派生都可以)
类内必须添加声明宏DECLARE_DYCREATE(the Class)
类外必须添加实现宏 IMPLENT_DYCREATE(theClass.baseClass)
当一个类具备上述三个要件后,CRuntimeClass::CreateObject() //对象加工厂
函数就可以将类的对象创建出来
作用:是给MFC创建对象
十一、MFC视图和文档
视图窗口:会把主窗口(框架窗口)的客户区给遮挡了
视图窗口的作用 :提供了一个用于显示数据的窗口 (为什么不直接画在数据在框架类里面的客户区呢,微软架构师认为每个类单独处理一件事情,模块化,框架窗口有其他的作用(就是一个容器,就是装声明视图窗口啊,工具栏啊,菜单栏啊))
视图窗口的相关类
CView 及其子类,父类为CWnd类,封装了关于视图窗口的各种操作,已经和文档类的数据交互(MVC)
视图窗口的使用
1、定义一个自己的视图类(CMyView),派生自CView,并重写父类纯虚函数OnDraw(可以用于绘图) //必须要重写OnDraw 是纯虚函数
virtual void OnDraw(CDC* /*pDC*/);
2、其余框架类和应用程序类代码不变
3、在处理框架窗口的WM_CREATE消息时,定义CMyView类对象,并调用Create函数创建视图窗口
视图窗口的ID为 AFX_IDW_PANE_FIRST
pMyView->Create(NULL, "MFCView", WS_CHILD | WS_VISIBLE|WS_BORDER, CRect(0,0,100,100),this,1001); //如果ID AFX_IDW_PANE_FIRST 写这个那么这个子窗口就会平铺在框架窗口上
用OnDraw(CDC* pDC){ }画图会更好
CWinApp
CView
CFrameWnd
应用程序类只是处理ON_COMMAND() 消息,因为应用程序类没有管理窗口
命令消息处理顺序 ON_CONAMD( ) 和其他消息顺序
视图类>框架类>应用程序类
对象关系图:
theApp
m_pMainWnd = pFrame;
m_pViewActive = pView;
theApp
|->m_pMainWnd(pFrame框架对象地址) //m_pMainWnd是应用程序类的成员
|->m_pViewActive(pView) //m_pViewActive是框架类的成员
十二、文档类
1、作用
文档类 CDocument:提供了一个用于管理数据的类、封装了关于数据的管理(数据提取、数据转换、数据存储等,)并和视图类进行数据交互
2、文档类的使用:
定义一个自己的文档类(CMyDoc),派生于CDocument
3、程序框架过程
WM_CREATE消息的两个附带信息
wParam-不使用
lParam-传入的信息为指针(CREATESTRUCT类型)这个指针指向位置保存了创建窗口函数(::CreateWindowEx)的区别参数
结合消息映射机制
ON_WM_CREATE()
处理WM_CREATE 消息函数为:
afc_msg int OnCreate(LPCREATESTRUCT pcs);
利用框架类对象地址(pFrame)调用LoadFrame函数,创建框架窗口
在处理框架窗口的WM_CREATE消息时,动态创建视图类对象,并创建视图窗口
在处理视图的WM_CREATE消息时,将文档类对象和视图类对象建立关联关系
最后一个机制:序列化机制(程序启动机制、窗口创建机制、动态创建机制、消息映射机制)
作用:读写硬盘文件
文件操作相关类
CFile -文件操作类,封装了关于文件读写等操作
CFile :: Open
CFile :: Write / Read
CFile :: Close
CFile :: SeekToBegin (将文件读写放到开始) / SeekToEnd (将文件读写放到最后)/ Seek(随意设置 读写位置)
void File() {
CFile file;
//CFile::modeCreate|CFile::modeReadWrite //没有就创建,有就打开
file.Open("D:/MFC/7Day/file.txe",CFile::modeCreate|CFile::modeReadWrite);
char str[] = "hello file";
file.Write(str,strlen(str));
file.SeekToBegin();
char buf[256] = { 0 };
long nLen = file.Read(buf,256);
cout << buf << ' ' << nLen << endl;
file.Close();
}
序列化基本类型
作用:以二进制读写硬盘文件(string)(不同之处之前都是或者数据都是字符串的或者ascii码保存在文件总,但是有时候不会存储string的,有时候会存double int long 这些每一种数据类型都有自己的存储格式 但是但是效率很高
序列化机制相关类
CFile -文件操作类,完成硬盘文件的读写操作
CArchive - 归档类(有缓冲区),完成内存数据的读写操作
其实就是 CFile 类组织好数据 先把数据扔到CArchive归档类中的缓冲区里再完成内存数据的读写操作
序列化机制(序列化(写数据)和反序列化(读数据))的使用
创建或者打开文件 CFile ::Open
定义归档类对象 CArchive ar;
数据序列化(存储/写) ar << 数据 (往箭头方向写数据)
关闭归档类对象 ar.Close( )
关闭文件CFlie :: Close( );
分析以上:代码执行过程. . . .
MFC序列化机制和对话框架构程序
序列化类对象: 把一个类对象存到内存里面
序列化对象的使用
类必须派(直接或者间接)生自CObject
1、类内必须添加声明宏DECLARE_SERIAL(theClass)
2、类外必须添加实现宏 IMPLEMENT_SERIAL(theClass ,baseClass , 1)
3、类必须重写虚函数Serialize()
当类具备上述三个要件后,类对象就可以序列化到文件中保存了
间接方式创建无模式对话框
1、添加对话框资源
2、查找资源
FindResource
3、锁定资源
LoadResource
4、创建无模式对话框
CreateDialogIndirect
MAKEINTRESOURCE 微软建议的用的宏 数字转换成宏字符串(CHAR*)
烧毁无模式对话框,使用DestroyWindow函数,不能使用EndDialog函数,
因为EndDialog函数只能将无模式对话框隐藏,不能销毁
对话框架构特点:
对话框分类
模式对话框(假)/ 无模式对话框 MFC中都是无模式对话框
参与架构的类
CDialog / CWinApp
1、加资源
2、定义对话框类 (CMyDlg)管理对话框、派生自CDialog 或者
CDialogEx均可
3 见代码
4执行过程
MFC模式对话框:架构(假的模式对话框因为,MFC都是无模式对话框,因为只是用了Endablewindow(false/ true))
1、参与架构的类
CDialog / CWinApp
代码
1、加资源
2、定义自己的对话框,管理对话框资源,派生CDialog或者CDialogEx均可
对象与控件绑定:
绑定的作用:
将控件窗口和类对象绑定具有两大作用
如果和数据类对象绑定,对象和控件可以数据交换
如果和控件类对象绑定,对象就可以代表整个控件
控件也数据类型对象绑定
数据类型对象和控件可以实现数据交换
重写父类成员虚函数DoDateExChange
在函数内部通过以系列的DDX_xxx函数,实现控件和数据对象的数据交互。
如果需要实现数据交互,调用UpDate函数
UpdateDate(TRUE):控件->变量
UpdateDate(FALSE)变量->控件
1、与控件类型对象绑定
2、重写父类成员函数DoDateExchange
在函数内部通过一系列的DDX_xxx函数,实现控件句柄和控件类型对象的绑定
3、控件类型对象,就代表这个控件
控件消息的处理
WM_COMMAND消息
LOWORD(wParam)- 菜单项ID,控件ID
HIWORD (wParam) - 菜单项 为 0
控件,通知码 (控件发生的事情)
lParam- 均无用
按钮如果想双击,属性需要把Notify 改成 True ,因为按钮通常默认只有单击,不然会误以为点击了两次
基本控件:
控件如何与数据类型对象绑定(做数据交换)
CEdit edit = String m_string
控件如何与控件类对象绑定(对象代表控件)
控件的消息如何处理
下压式按钮
相关类
CButtton: 父类为CWnd ,封装了关于下压式控件的各种操作。
消息
当下压式按钮被点击
WM_COMMAND消息(通知码BN_CLICKED)
下压式按钮
相关类 CButton类:父类为CWnd,封装了关于下压式按钮的各种操作
消息:
当下压式按钮被单击
WM_COMMAND消息(BN_CLICKED)
类向导: 在资源界面 工具箱里 可以找到你要的控件 拖过来 要让这个控件与 CButton对象绑定 >在Project > Class Wizard > 选择好你的 项目>选择好你要操作的类 >选择 成员变量> 让成员变量m_xxx与控件 绑定(控件的ID)绑定,那么m_xxx就代表了控件,
m_xxx就可以调用CButton里面的函数了
编辑框
相关类
CEdit 类:父类为CWnd,封装了关于编辑框控件的各种操作
常见操作
获取编辑框文本内容
设置编辑框文本内容
数据与控件绑定,如果已经跟控件变量绑定那么可以 在 >类向导 > 成员变量 > 添加变量 >类别(选择值<value>) > 类型默认Cstring 可以选择
m_str = "aaaa";
UpdateDate(FALSE); // 变量 到 控件
消息
当编辑框文本内容发生变化(为什么要更改我编辑框的内容)
WM_COMMAND消息(通知码EN_CHANGE)
类向导 > Commands > IDC_EDIT > EN_CHANGE
1、复选框按钮:也是按钮 check box
相关类
CButton类:父类CWnd,封装了关于复选框按钮控件的各种操作
常见操作获取复选框状态
CButton::GetCheck
设置复选框状态
CButton::SetCheck
消息
当下压式按钮被点击
WM_COMMAND消息(通知码BN_CILCKED)
选择 command > 找到ICDC_Check > BN_CILCKED >确定
把一个数字格式成字符串
int nState = m_check.GetCheck();
Cstring sState;
sState.Format("%d",nState);
m_btn.SetWindowText(sState);
在属性里面 Push Like > 选择ture那么会变成下压式按钮 (多态按钮)
单选框按钮
通常一对出现 如 男 女
Radio Button
相关类
CButton:父类为CWnd,封装了关于单选框控件的各种操作
常见操作
获取复选框类状态
CButton::GetCheck();
CButton::SetCheck();
当单选框被点击
WM_COMMAND消息(通知码BN_CILCKED)
选择 command > 找到ICDC_Check > BN_CILCKED >确定
默认的时候 单选择框 ID没有出现在类向导里面 需要把Group 设置成ture才能出现ID
分组框按钮:
常见操作:
用于控件分组显示,提高界面友好性
这种id不常改的IDC_STATIC通常不常改,在类向导不会出现,手动去改ID 在类向导才会出现 分组框在类向导类也是CButton
文本静态框:也是提高界面友好性:常用于 显示 字符串 ,提高界面友好性
CWnd::SetWindowText
图像静态框:常见操作 显示 图像 在资源视图 工具箱里找到 Picture Control 拖拉过去画板
在属性 Type(类型) 通常选择 Icon和Bitmap 如果选择了 Bitmap 可以添加资源那样 在属性 Image 就会出现那个Bitmap图像,同样默认ID是STATIC地不会出现在类向导里面,所以要自己改ID
CStatic::SetIcon / CStatic::SetBitmap
组合框:简单式组合框 (同样选择Combo box 如何在属性哪里 type >选择简单(simple),可以输入)/下拉式组合框(同样选择Combo box 默认式dropdown下拉式,支持输入) / 下拉列表组合框同样选择Combo box 如何在属性哪里 type >选择Drop List (下拉列表不支持输入)
有个下来小三角的图案,添加的时候往下拉一下,不然下拉的展示的东西很少
相关类 CComboBox类 :父类为CWnd,封装了关于组合框控件的各种操作
常见操作
添加选项
CComboBox::AddString //注意排序: 如果不在属性中 sort 排序中选择 false 会不按你的排序来
删除选项
CCombobox ::DeleteString(index) 要删除指定的 ResetContent是 全部删除
CComboBox ::GetCurSels 选择项 你能够通过它,选择选择项目的索引(不是文本内容)
添加完后AddString后
设置选择项 默认项目
CComboBox::SetCurSel() ,
获取选项文本内容
CComboBox::GetLBText
设置选项附件数据
CComboBox::SetItemDate 当Item的名字相同时候,为了避免,为了区分,可以给不同选项设置不同的附加数据
当AddString之后 设置附加数据 m_simple.SetItemDate(int index,附加数据)
获取选项附件数据
CComboBox::GetItemDate 得到任意一个选项的附加数据
MFC中格式字符串
先声明一个CString str 变量字符串;
如何给str赋值 值通常 其他地方获取然后变量接收 如 DWORD nWord = ..... nWord就是值
str.Format("",nWord) ; //" "双引号中 输入你要的 文字 然后% d/s 具体用s或者d 要看需要格式的内容的类型
组合框消息:
当选项发生变化时
WM_COMMAND消息(CBN_SELCHANGE)
但文本内容发生变化时
WM_COMMAND消息(CBN_EDITCHANGE)
列表框: List Box
相关类:CListBox :父类为CWnd,封装了关于列表控件的各种操作
常见操作
添加选项
CListBox::AddString
删除选项
CListBox::DeleteString
获取选项
CListBox::GetCurSel
设置选项
CListBox::SetCurSel
获取选项文本内容
CListBox::GetItemText 和组合框唯一的区别,获取文本框内容不一样
设置选项附加数据
CListBox::SetItemDate
获取选项附加数据
CListBox::GetItemDate()
MFC控件的使用
滑块控件
Silder Control 在属性里面可以更改,方向:横Horizontal 向和竖Vertical 不过要拉一些才行 在画布中
相关类
CSliderCtrl类: 父类为CWnd,封装了关于滑块控件的各种操作。
常见操作
设置范围
CSliderCtr::SetRange(Min,Max);
设置位置CSliderCtr::SetPos( );
获取位置
CSliderCtrl::GetPos
滑块的消息
当滑块的位置改变后
滑块控件发出WM_COMAND消息(NM_CUSTOMRAW)
进度条控件
相关类CProgressCtrl 类:
常见操作
设置范围
CProgressCtrl::SetRange
设置位置
CProgressCtrl::SetPos
获取位置
CProgressCtrl::GetPos
文件搜索类:该类能实现文件的搜索,遍历
列表,需要用到一些文件搜索类的一些功能
文件搜索类:相关类:CFileFind类:封装了关于文件遍历的各种操作
常见操作
开启查找(仅仅开启查找,并不会找任何文件),成功返回TRUE(开启查找成功),返回失败FALSE(开启查找失败)
CFileFind::FindFile
找到当前文件,返回下一个文件是否存在
调用一系列GetXXX函数获取文件信息
CFileFind::GetFileName / CFileFind::GetFilePath
调用一系列IsXXX函数判断文件属性
例如:CFileFind::IsDirectory / CFileFind::IsDos
关闭查找
例如CFileFind::Close
. 点目录代表当前目录
.. 目录代表上一级目录
列表框:
List Contorl
相关类 CListCtrl类:父类为CWnd,封装了关于列表控件的各种操作
风格:
图标(LVS_ICON)
小图标(LVS_SMALLICON)
列表(LVS_LIST) 平时看的列表
报表(LVS_REPOST) //详细信息,就是报表的
修改风格
CWnd::ModifStyle(,)任何控件都可以用这个风格第一个参数时去掉的风格,第二个时需要的风格
列表控件常见操作
添加选项
CListCtrl::InserItem
删除选项
CListCtrl::DeleteItem/DeleteAllItem
添加列
CListCtrl::InsertColumn
设置文本内容
CListCtrl::SetItemText
设置图像
CListCtrl::SetImageList //位图是默认 48高 48宽
相关类:CImageList图像列表类
设置附加数据
CListCtrl::SetItemDate
获取附加数据
CList::GetItemDate
消息
当列表控件被点击
发出WM_COMMAND消息(通知码LNM_DBLCLK)
列表控件(CListCtrl)和列表框控件(CListBox)有一定的区别,
不要混淆。列表控件(List Control)用来成列地显示数据,其表项通常包括图标(Icon)和标签(Lable)两部分,
它们分别提供了对数据的形象和抽象描述。
相关类
CTreeCtrl类:父类为:CWnd,封装了关于树控件的各种操作
常见操作
添加选项
CTreeCtrl::InsertItem
删除选项
CTreeCtr::DeleteItem / DeleteAllItems
换取选项
CTreeCtrl::GetSelectedItem
获取选项文本内容
CTreeCtrl::GetItemText
设置选项高度
CtreeCtrl::SetItemHeight
设置图像
CTreeCtrl ::SetImageList
MFC打印
Ondraw( ) 屏幕显示, 复制打印OnPrint( )专门用来
OnPreparePrinting( ) 预设定打印页数
OnBeginPrinting() //这里创建字体
OnPrepareDC( ) //检查是否结束
OnPrint( ) // 完成打印
OnEndPrinting( ) //这里销毁字体