MFC笔记

Day02
1.MFC程序的执行过程
1.1程序启动,CWinApp构造
1.2 WinMain调用AfxWinMain函数
1.3 AfxWinMain函数的执行
1.3.1获取theApp对象的地址调用AfxGetThread/AfxGetApp分别从线程状态信息和模块状态信息中获取theApp的地址
1.3.2调用AfxWinInit函数,初始化MFC库
1.3.3调用InitApplication函数,初始化应用程序数据
1.3.4调用InitInstance函数,创建并显示窗口
1.3.5使用App的Run()函数进入消息循环
1.3.6结束MFC库,退出程序
1.4 CWinApp类
应用程序封装类,父类是CWinThread,封装了程序的初始化信息,消息循环等
InitInstance – 程序的初始化函数,完成窗口的创建等初始化处理
ExitInstance – 程序退出时,调用的函数,做一些资源释放等清理工作
OnIdle – 空闲处理函数,Run函数中调用的
m_pMainWnd, - 保存当前程序的主窗口
2.窗口的创建
2.1窗口的创建过程
2.1.1 LoadMenu – 加载菜单
2.1.2 CWnd::CreateEx – 创建窗口
2.1.2.1 PreCreateWindow – 设计和注册窗口类
将DefWindowProc函数设置成窗口处理函数
2.1.2.2调用AfxHookWindowCreate函数,创建钩子
创建CBT类型的钩子,设置钩子的处理函数,_AfxCbtFilterHook
2.1.2.3调用CreateWindowEx函数,创建窗口
马上执行2.1.3
2.1.2.4调用AfxUnhookWindowCreate卸载钩子,并返回
2.1.3钩子处理函数_AfxCbtFilterHook
2.1.3.1获取MFC提供的窗口处理函数的地址(AfxWndProcBase的地址)
2.1.3.2调用SetWindowLong函数将窗口的处理函数设置成MFC提供的窗口处理函数
AfxWndProcBase
3. 消息映射机制
3.1消息映射的使用
3.1.1在FrameWnd的子类中添加消息映射声明宏
DECLARE_MESSAGE_MAP
3.1.2在类的实现中,添加消息映射实现宏
BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)
END_MESSAGE_MAP()
3.1.3在类的中要添加消息处理函数的声明和实现
3.1.4在消息映射实现宏中添加消息ID与处理函数的对应关系
BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)
ON_MESSAGE(WM_CREATE,OnCreate)
ON_MESSAGE(WM_PAINT,OnPaint)
END_MESSAGE_MAP()
3.2消息映射的实现
3.2.1声明宏展开后的代码
private:
static const AFX_MSGMAP_ENTRY _messageEntries[];
protected:
static AFX_DATA const AFX_MSGMAP messageMap;
static const AFX_MSGMAP* PASCAL _GetBaseMessageMap();
virtual const AFX_MSGMAP* GetMessageMap() const;
void OnCreate();
void OnPaint();
3.2.2实现宏展开后的代码
const AFX_MSGMAP* PASCAL CMainFrame::_GetBaseMessageMap()
{
return &CFrameWnd::MessageMap;

}
const AFX_MSGMAP* CMainFrame::GetMessageMap() const
{
return &CMainFrame::messageMap;
}

AFX_COMDAT AFX_DATADEF const AFX_MSGMAP CMainFrame::messageMap =
{ &CMainFrame::_GetBaseMessageMap, &CMainFrame::_messageEntries[0] };
AFX_COMDAT const AFX_MSGMAP_ENTRY CMainFrame:_mes

sageEntries[] =
{
{ WM_CREATE, 0, 0, 0, AfxSig_lwl,
(AFX_PMSG)(AFX_PMSGW)(LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM))&OnCreate },
{ WM_PAINT, 0, 0, 0, AfxSig_lwl,
(AFX_PMSG)(AFX_PMSGW)(LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM))&OnPaint },
{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 }
};
3.2.3结构
struct AFX_MSGMAP_ENTRY
{
UINT nMessage; // windows message消息的标识
UINT nCode; // control code or WM_NOTIFY code消息的通知码
UINT nID; // control ID (or 0 for windows messages)命令ID/控件ID
UINT nLastID; // used for entries specifying a range of control id’s控件的最后一个ID
UINT nSig; // signature type (action) or pointer to message #消息处理函数的类型
AFX_PMSG pfn; // routine to call (or special value)消息处理函数指针
};
3.2.4结构
struct AFX_MSGMAP
{
#ifdef _AFXDLL
//函数的指针
const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
#else
const AFX_MSGMAP* pBaseMap;
#endif
// AFX_MSGMAP_ENTRY的地址3
const AFX_MSGMAP_ENTRY* lpEntries;
};
3.3作用
3.3.1 AFX_MSGMAP_ENTRY[]数组
静态数组,元素类型AFX_MSGMAP_ENTRY,数组中的每一个元素都保存了消息的标识和消息处理函数
3.3.2 messageMap
静态变量,类型是MSGMAP,保存了当前类_GetMessageMap函数的地址,和AFX_MSGMAP_ENTRY[]的首地址
3.3.3 _GetBaseMessageMap()函数
静态函数,获取父类的messageMap变量的地址
3.3.4 GetMessageMap()虚函数
虚函数,获取本类的messageMap变量的地址
3.4 关系
GetMessageMap()
|->messageMap
|->_messageEntries[]
|->ID,函数
|->_GetBaseMessageMap()
|->CFrameWnd::messageMap
|->_messageEntries[]
|->ID,函数
|->CFrameWnd::GetBaseMessageMap
|->CWnd::messageMap
|->_messageEntries[]
|->ID,函数
|->CWnd::_GetBaseMessageMap
3.5 执行过程

Day03
1.窗口消息的处理过程
2.MFC消息的分类
2.1 窗口消息
大部分的窗口、鼠标、键盘等消息,系统提供了标准的消息处理函数。
消息映射:
ON_WM_XXX
2.2 命令消息
菜单、工具栏、按钮等等消息
消息映射:
ON_COMMAND
2.1 在CWnd::OnWndMsg函数,如果判断是命令消息,调用OnCommand函数
2.2 在OnCommand函数中,调用CCmdTarget::OnCmdMsg函数
2.3 在OnCmdMsg函数中,查找消息映射,找到后调用消息ID所对应的处理函数
2.3 通知消息(Control NofinNotification)
WM_NOTIFY部分控件的命令消息WM_COMMAND的属于通知消息
这种消息由控制组件产生,为的是向其父窗口(通常是对话盒)通知某种情况。
2.4 系统注册消息(用户自定义消息)
3 MFC菜单的使用
3.1 MFC菜单相关
Win32 - HMENU
CMenu - 封装菜单句柄和菜单相关的API函数
3.2 菜单的使用
3.2

.1 添加资源文件
3.2.2 在创建窗口是设置或者CMenu类加载到窗口
CMenu::Attach - 将菜单句柄附加到菜单对象中
CMenu::Detch - 将菜单句柄从菜单对象中分离
3.2.3 添加菜单的命令消息
3.2.4 菜单项的状态
ON_UPDATE_COMMAND_UI
3.2.5 消息的响应顺序
Frame -> App
在CFrameWnd::OnCmdMsg函数中确定了响应顺序
3.3 CCmdTarget类
消息映射机制的父类,所有继承自它的子类都支持消息映射
来自于菜单、工具栏、按钮和加速键等等
3.4 快捷菜单(向导生成右键菜单)
4 工具栏的使用
4.1 MFC 工具栏相关
CToolBarCtrl - 父类是CWnd,封装了ToolBar Control控件相关的信息、API等等
CToolBar - 父类ControlBar,封装了ToolBar与FrameWnd之间的关系

精通>熟练>熟悉>掌握>了解
day04
1 工具栏的使用4 工具栏的使用
1.1 MFC 工具栏相关
CToolBarCtrl - 父类是CWnd,封装了ToolBar Control控件相关的信息、API等等
CToolBar - 父类ControlBar,封装了ToolBar与FrameWnd之间的关系4 工具栏的使用
1.2 工具栏的使用
1.2.1 创建工具栏
CToolBar::Create/CreateBar
1.2.2 加载工具栏的资源
1.2.2.1 添加资源
1.2.2.2 加载资源
1.2.3 工具栏的停靠
1.2.3.1 设置工具栏允许停靠
1.2.3.2 设置窗口允许被停靠
1.2.3.3 停靠工具栏
1.2.4 命令处理
1.2.5 工具栏的显示和隐藏
CFrameWnd::ShowControlBar
1.2.6 工具栏按钮添加提示信息
1.2.6.1 在资源当中添加提示字符串
1.2.6.2 增加风格 CBRS_TOOLTIPS
2 MFC状态栏
2.1 MFC状态栏相关类
CStatusBarCtrl - 父类是CWnd,对于status Bars控件封装
CStatusBar - 父类是CControlBar,封装了状态栏和窗口之间的关系
2.2 MFC状态的使用
2.2.1 创建状态栏
2.2.2 设置状态指示器
SetIndicators
2.2.3 设置或获取状态栏的信息
SetPaneText
GetPaneText
3 MFC视图
3.1 MFC视图相关
MFC视图-提供了一个显示数据的窗口,用于和用户进行交互
MFC视图相关类 - CView及相关子类,父类CWnd,可以接受窗口消息
3.2 视图的使用
3.2.1 视图的创建和显示
3.2.1.1 定义CView类的子类,实现OnDraw函数
3.2.1.2 使用Create函数创建
AFX_IDW_PANE_FIRST
3.2.2 视图的销毁
CView::PostNcDestory会销毁视图
3.3 视图命令消息的响应
3.3.1 Frame窗口收到菜单的命令消息
3.3.2 在Frame的OnCmdMsg函数中会获取Frame的活动视图ActiveView,调用ActiveView的OnCmdMsg
3.3.3 调用Frame本身的OnCmdMsg
3.3.4 获取当前的App,调用App的OnCmdMsg
响应顺序:view->Frame->App
4 切分窗口
4.1 MFC切分窗口的类型
动态切分 - 在窗口执行过程中根据用户需要实施切分窗口
静态切分 - 在窗口创建时就完成了窗口切分
4.2 切分窗口相关


CSplitterWnd - 父类是CWnd,实现窗口切分操作
4.3 动态切分
4.3.1 定义 CSplitterWnd对象
4.3.2 创建切分窗口
4.3.2.1 在CFrameWnd::OnCreateClient()函数中
4.3.2.2 调用CSplitterWnd::Create函数创建切分
注意切分数量不能大于2*2,每个切分单元都是独立的View窗口
4.4 静态切分
4.4.1 定义CSplitterWnd对象
4.4.2 创建切分窗口
调用CSplitterWnd::CreateStatic
4.4.3 要创建视图
动态切分每个切分单元使用的是统一类型的视图,但是静态切分可以为每一个切分单元指定
不同类型的视图
4.4.4 切分窗口的再切分
在已经切分的窗口中再放一个切分窗口
4.4.4.1 在切分窗口的父窗口是要切分的单元格窗口
4.4.4.3 将每个切分后的单元创建视图
Day05
2 运行时类信息(机制4)
2.1 运行时类信息
程序运行时,对象相关类的信息,能够提供判断对象的类以及类的继承关系
2.2 使用
2.2.1 继承自CObject
2.2.2 添加宏声明DECLARE_DYNAMIC(theC)
2.2.3 添加宏的实现 IMPLEMENT_DYNAMIC(theClass,baseClass)
2.2.4 CObject类中与运行时类信息相关的俩个函数
2.2.4.1 virtual CRuntimeClass* GetRuntimeClass()
//获取运行时类信息的
2.2.4.2 BOOL IsKindOf(const CRuntimeClass* pClass)
//判断对象是否属于某个类
2.3
2.3.5 IsKindOf的实现
2.3.5.1 获取对象的CRunTimeClass的变量的地址
2.3.5.2 与判断的类型的CRuntimeClass的变量的地址比较,如果相等则返回TRUE
表示对象属于该类,否则获取父类的CRuntimClass变量的地址,循环比较
找不到,返回FALSE.
3 动态创建
3.1 在不需要知道对象类型的情况下,将对象创建
3.2 实现
3.2.1 代码
3.2.2 作用
CreateObject - 创建CDog类的对象并返回地址
classCDog - 将CreateObject函数的地址保存
3.2.3 动态创建的执行
3.2.3.1 获取CDog类的运行时类信息
3.2.3.2 调用CRuntimeClass::CreateObject函数
3.2.3.3 在CreateObject函数,会通过函数地址调用CDog类的CreateObject函数
有了运行时类信息和动态创建,底层可以创建上层的对象
MFC库就支持我们定义的类对象创建。
4 文档类CDocument
4.1 文档类相关
对数据的管理,封装了数据和视图,框架窗口之间的基本操作
CDocument类- 父类是是CCmdTarget ,提供了文档数据的管理
Day06
1.单文档视图架构应用程序
1.1 单文档视图程序
只能管理一个文档
1.2 相关类
1.2.1 CWinApp\CFrameWNd\CView\CDocument
1.2.2 CDocTemplate - 文档模板类
CSingleDocTemplate - 单文档模板类
CMultiDocTemplate - 多文档模板类
1.3 创建过程
1.3.1 关系
CWinApp
|->CDocManager *m_pDocManager
|->m_templateList(CDocTemplate List)
|->CSingleDocTemplate
|->CDoc

ument* m_pOnlyDoc
|->CRuntiemClass *m_pDocClass
|->CRuntiemClass *m_pFrameClass
|->CRuntiemClass *m_pViewClass
1.3.2 创建过程(CWinApp::OnFileNew)
1.3.2.1 使用m_pDocManager获取文档模板
1.3.2.2 使用文档模板中m_pDocClass动态创建文档对象
1.3.2.3 使用文档模板中的m_pFrameClass动态创建Frame对象
1.3.2.4 将文档对象以及m_pViewClass传给Frame对象,创建Frame对象(LoadFrame函数中)
1.3.2.5 在Frame 的OnCreate消息响应函数中,创建View的对象和窗口
1.3.2.6 在View的OnCreate中,将View的地址保存到Document中;将Document的地址保存到View中
1.3.3 在一个单文档程序中,可以有多个模板吗?
doc1\ndoc2\ndoc3
doc1 - 视图窗口的标题
doc2 - 框架窗口的标题
doc3 - 模板显示的内容
2.多文档视图架构程序
2.1 多文档视图
可以同时打开多个文档进行处理
2.2 多文档视图相关类
2.2.1 CWinApp/CMDIFrameWnd/CMDIChildWnd/CView/CDocument
2.2.2 文档模板
CMultiDocTemplate
2.3 创建过程
2.3.1 关系
CWinApp
|->CDocManager *m_pDocManager
|->m_templateList(CDoctEemplate List)
|->CMultiDocTemplate
|->m_docList(CDocument List)
|->CRuntiemClass *m_pDocClass
|->CRuntiemClass *m_pFrameClass
|->CRuntiemClass *m_pViewClass
2.3.2 创建(CWinApp::OnFileNew)
与单文档类似
3 文档视图架构(总结文档视图架构的相关知识)
3.1 相关的类
CWinApp/CMDIFrameWnd/CMDIChildWnd/CView/CDocument
3.2 数据关系
CWinApp
|->m_pDocMananger(CDocManager*)
|->m_templateList(CDodTemplate List)
|->CMultiDocTemplate/CSingleDocTemplate
|->m_docList/m_pOnlyDoc
|->CDocument *
|->m_viewList(CView List)
|->m_pMainWnd(CWnd *)
|->m_pActiveView(CView *)
|->m_pDocument
3.3 创建过程
3.3.1 CWinApp中查找对应的模板,创建文档
3.3.2 使用创建的文档,创建框架窗口Frame
3.3.3 在Frame的OnCreate中中创建View
3.3.4 在View的OnCreate中,和文档关联
3.5 命令消息
CView->CDocument->CFrameWnd->CWinApp
Day07
1.MFC绘图
1.1 MFC绘图相关类
CDC相关-绘图设备类,封装HDC绘图句柄和相关的绘图API
CGdiObject-绘图对象类,封装了绘图对象
1.2 CDC类
1.2.1 CDC - 父类是CObject
1.2.2 CClientDC - 父类是CDC,封装了客户区的DC
1.2.3 CPaintDC - 父类是CDC, 客户区DC,和CClientDC的区别是只能在
WM_PAINT的消息处理函数中使用
1.2.4 CWindowDC - 父类是CDC,封装了整个窗口的DC
1.2.5 CMetaFileDC - 父类也是CDC,封装了Windows图元文件的处理
1.2.5.1 创建文件
1.2.5.2 绘制
1.2.5.3 关闭
1.2.5.4 显示
1.2.5.5 销毁
1.3 CGdiObject类
1.3.1 CPen - 画笔
1.3.2 CBrush - 画刷
1.3.3 CBitmap - 位图
1.3.4 CFont - 字体
1.3.5 CPalette - 调色板
1.3.6 CRgn - 复杂

的几何区域
1.3.6.1 作用
基于基本的几何图形,构建复杂几何图形
1.3.6.2 使用
1.构造Rgn对象
2.调用一系列的CreateXXXX函数创建基本的几何图形
3.调用CombineRgn将图形进行几何运算
4.绘制/填充几何图形
Day08
1.文件操作
1.1 MFC文件的相关类
CFile - 父类是CObject,封装了文件操作的API,提供了文件的创建、数据读写等操作
CFileFind - 文件搜索,父类是CObject,提供文件查找功能
1.2 CFile的使用
1.2.1 打开或者创建文件
CFile::Open
1.2.2 数据的读写
CFile::Read/CFile::Write
注意读写操作时的异常捕获
1.2.3 文件的关闭
CFile::Close
1.2.4 文件指针
SeekToBegin/SeekToEnd/Seek( LONG lOff, UINT nFrom )
1.2.5 Flush - 强制缓冲区的数据写入文件,并清空缓冲区
1.2.6 CFile::LockRange/CFile::UnLockRange
用于多个程序、多进程同时操作一个文件时
1.2.7 文件状态信息
GetStatus/SetStatus
1.3 CFileFind 文件查找
1.3.1 FindFile - 开始查找
1.3.2 FindNextFile - 得到第一个文件信息,返回第二个文件是否存在
1.3.3 Close - 结束查找

2.序列化(机制6)
2.1 序列化
采用数据流的方式,将数据一次写入文件/读取文件,是二进制的存储方式
2.2 序列化相关类
1 CFile - 文件类
2 CArchive - 封装了序列化的操作,归档类,完成数据的具体操作,读写操作的过程封装到该类
3 CObject - 提供了基本序列化的基本操作
CObject::IsSerializable - Nonzero if this object can be serialized
virtual void Serialize( CArchive& ar ); - 完成数据读写的函数
2.3 序列化的使用
2.3.1 创建或者打开文件
CFile::Open
2.3.2 定义CArchive对象
2.3.3 数据读写
写入,存储:<<
读取,加载: >>
2.4 CArchive类
2.4.1 CArchive定义缓存,缓存的长度由m_nBufSize决定,减少硬盘的读写次数
BOOL m_nMode; - A flag that specifies whether objects will be loaded from or stored to the archive
BOOL m_bUserBuf;
int m_nBufSize; - 缓存的长度
CFile* m_pFile; -
BYTE* m_lpBufCur; - 当前指针的位置
BYTE* m_lpBufMax; - 终止指针位置
BYTE* m_lpBufStart; - 起始指针位置
2.4.2 执行过程(存储/数据写入)
2.4.2.1 判断在缓存区中Buff中,是否有足够的空间存储数据
m_lpBufCur+sizeof(数据)>m_lpBufMax
2.4.2.2 如果空间不够,将Buff中已有的数据写入文件,重置当前值的位置为Buff的起始位置
2.4.2.3 将内存数据写入到m_lpBufCur指定的地址
2.4.2.4 将当前指针m_lpBufCur向后偏移写入的字节数,写入到最后,调用了ar.Close(),
自动调用Flush,将缓冲区的数据写入到文件
2.4.3 执行过程(加载/数据的读取)
2.4.3.1 首先判断剩余的Buff是否满足读取数据的大小
2.4.3.

2 如果空间不够,调用FileBuffer函数,并将需要的字节传入
1.将Buff中没有使用的字节数,拷贝到Buff的起始位置
2.从文件当中读取Buff剩余空间的长度的数据
3. 根据实际读取的数据长度,设置Max的地址
2.4.3.3 将数据从当前位置m_lpbufCur中取出,放入变量中
2.4.3.4 将m_lpBufCur向后偏移读出的字节数
2.5 对象的序列化和反序列化
序列化对象 - 将对象的类的信息和对象的数据保存到文件
反序列化对象 - 根据读取的类的信息,创建对象,并将对象的数据读入
2.5.1 使用
2.5.1.1 支持序列化的类的定义
1. CObject类的子类
2. 重写Serilize函数
3. 添加声明宏和实现宏
2.5.1.2 打开或创建文件
2.5.1.3 定义CArchive对象
2.5.2.4 将类的对象保存到CArchive对象或者从CArchive对象读取
2.5.2.5 关闭CArchive对象
2.5.2.6 关闭文件
2.5.2 代码
class CStudent
{
_DECLARE_DYNCREATE(class_name)
AFX_API friend CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb);
};
CObject* PASCAL class_name::CreateObject()
{
return new class_name;
}
_IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, class_name::CreateObject)
AFX_CLASSINIT _init_##class_name(RUNTIME_CLASS(class_name));
CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb)
{ pOb = (class_name*) ar.ReadObject(RUNTIME_CLASS(class_name));
return ar; }
2.5.3 作用
operator>> 创建类的对象并读取数据
_init_CStudent 将CStudent类的运行时类信息保存到应用程序当中m_classList的链表中.
2.5.4 序列化的过程
1. 获取对象的运行时类信息
2. 将类的名称和版本号写入到ar中
3. 调用对象的Serilize函数
4. 在Serilize函数中,保存该对象自己的数据
2.5.5 反序列化的过程
1. 从文件当中读取类的名称和版本号
2. 根据类的名称,从m_classList的链表中查询该类所对应的运行时类信息
3. 使用查询到的运行时类信息创建对象
4. 调用对象的Serilize函数
5. 在Serilize函数内部读取该对象的数据
Day09
1 对话框
1.1 对话框分类
模式/非模式
1.2 对话框的相关类
CDialog - 父类是CWnd
CCommonDialog - 通用对话框类,父类是CDialog
CPropertyPage - 属性页类,父类也是CDialog
1.3 模式对话框
1.3.1 在Win32应用程序中使用MFC创建基于对话框的应用程序
1.3.1.1 资源模板的定义和类的定义
通过构造函数将资源模板的ID赋值给CDialog
1.3.1.2 调用CDialog::DoModal函数,显示对话框
1.3.1.3 使用CDialog::OnOK或者CDialog::OnCancl关闭对话框(内部都调用了EndDialog)
1.3.1.4 对话框的初始化
在OnInitDialog函数中完成初始化工作
1.3.2 MFC下的模式

对话框
1.3.2.1 插入对话框资源,定义对话框类
1.3.2.2 对话框的创建和显示
DoModal函数的执行
1.查找并加载对话框资源
2.将对话框的父窗口设置为非激活窗口
3.创建对话框窗体
4.执行对话框的消息循环
5.退出后,隐藏对话框窗口
6.将主窗口设置为激活窗口
7.销毁对话框窗口
1.3.2.3 对话框的关闭
1.3.2 非模式对话框
注意:非模式对话框不能通过EndDialog函数真正的关闭对话框
1 定义对话框类
2 创建和显示对话框
调用Create/ShowWindow函数
3 关闭(重写OnOK和OnCancel)
1.4 对话框的数据交换
1.4.1 对话框数据交换
通过将对话框上得控件和成员变量进行绑定,可以通过成员变量访问控件或者数据交换
1.4.2 相关的函数
1.4.2.1 CWnd::DoDataExchange - 当变量和控件之间进行数据交换时,被1.4.2.2调用
1.4.2.2 CWnd::UpdateData - 当需要进行数据交换时调用
UpdateData(TRUE) - 将控件的数据保存到变量
UpdateData(FALSE) - 将变量的数据保存到控件
1.4.2.3 DDX_XXX - 绑定函数,完成具体的交换操作,被1.4.2.1调用
1.4.3 DDX的使用
1 定义对话框和控件
2 定义对话框的成员变量
3 实现绑定
3.1 CWnd::DoDataExchange
3.2 DDX_XXX(有几个绑定对应几个DDX_XXX)
4 数据的交换
UpdateData
1.4.4 DDX的实现
1 变量的交换
1.1 获取指定ID的控件的窗口句柄
1.2 从控件窗口获取值或者设置值、
2 控件
2.1 获取指定ID控件的窗口句柄
2.2 将控件对象与窗口句柄绑定
1.4.5 通用对话框
CFileDialog - 文件打开/保存对话框
CFindReplaceDialog - 查找替换对话框
CFontDialog - 字体对话框
CColorDialog - 颜色对话框
CPrintDialog - 打印对话框
CPageSetupDialog - 打印页面设置对话框
2 MFC基本控件

Day11
1 属性页
1.1 向导是属性页
1.1.1 使用
1. 插入资源模板,定义页面对话框
2. 定义容器窗口(CPropertySheet)
3. 将页面添加到容器窗口中AddPage
CPropertySheet::AddPage
4. 设置成为向导模式
CPropertySheet::SetWizardMode
5. 创建和显示
CPropertySheet::DoModal
6. 消息
CPropertyPage::OnSetActive
CPropertyPage::OnWizardNext
CPropertyPage::OnWizardBack
CPropertyPage::OnWizardFinish
1.1.2 注意
1 向导是页面的顺序不能随意的修改,需要在每一个页面设置向导按钮
CPropertyPage::OnSetActive函数中去设置
2 当点击向导按钮时,产生的消息只属于当前页面
2 列表控件
2.1 列表相关类
CListView - 父类是CView,本质是一个视图类
GetListCtrl - 获取列表控件
CListCtrl - 父类是CWnd,本质是一个控件
2.2 分类(根据显示方式分类)

图标的方式 - LVS_ICON
小图标 - LVS_SMALLICON
列表 - LVS_LIST
报表 - LVS_REPORT
2.3 使用
1 风格
LVS_ICON/LVS_SMALLICON/LVS_LIST/LVS_REPORT
2 图标
CListCtrl::SetImageList
CListCtrl::GetImageList
3 设置列
CListCtrl::InsertColumn
4 数据添加
CListCtrl::InsertItem - 插入数据项
CListCtrl::SetItemText - 设置项的文本
5 遍历数据项
CListCtrl::GetSelectedCount - The number of selected items in the list view control
CListCtrl::GetFirstSelectedItem - 获取第一个被选择项
6 删除
CListCtrl::DeleteItem - 删除指定项
CListCtrl::DeleteAllItems - 删除所有项
CListCtrl::DeleteColumn - 删除指定列
7 查找
CListCtrl::FindItem - 找到指定项
8 附加数据
CListCtrl::SetItemData
CListCtrl::GetItemData
3 树控件
3.1 相关类
CTreeView - 父类是CView,本质是视图
CTreeCtrl - 父类是CWnd,本质是一个控件
3.2 使用
3.2.1 增加节点
CTreeCtrl::InsertItem
添加节点,并返回节点句柄
3.2.2 获取节点
CTreeCtrl::GetSelectedItem - 获取选择节点
CTreeCtrl::GetNextItem - 从某个节点查找指定状态的节点
CTreeCtrl::GetRootItem -
CTreeCtrl::GetParentItem -
2.2.3 判断
CTreeCtrl::ItemHasChild - 判断节点是否有子节点
2.2.4 删除
CTreeCtrl::DeleteItem - 删除指定节点
CTreeCtrl::DeleteAllItem - 删除所有节点
2.2.5 附加数据
CTreeCtrl::SetItemData
CTreeCtrl::GetItemData
2.2.6 消息
NM_DBLCLK - 双击消息

3 通用控件
3.1 滑块 - CSliderCtrl
SetPageSize/GetPageSize -
SetLineSize/GetLineSize -

3.2 进度条 - CProgressCtrl::SetStep
SetStep - 设置步长
SetIt - 向前移动一个步长
3.3 微调控件 - CSpinButtonCtrl
3.3.1 SetBuddy/GetBuddy - 设置伙伴关系
也可以通过属性去设置,选择上AutoBuddy和Set Buddy Integer选项。注意编辑框控件的Tab键顺序在微调按钮的前面
3.4 相同的成员函数
3.4.1 设置范围
SetRange/GetRange
SetRange32/GetRange32
3.4.2 设置/获取当前进度
SetPos/GetPox
3 MFC集合
3.1 MFC动态数组 -
template< class TYPE, class ARG_TYPE > class CArray : public CObject
type:元素类型
ARG_TYPE:成员函数参数类型
3.1.1 CArray模板类,用于创建任何数据类型的类型安全数组 头文件 include
3.1.1.1 设置/获取数组大小
CArray::SetSize - 设置数组大小
3.1.1.2 设置/获取元素的值
SetAt/GetAt,除此之外,还可以用下标[]
3.1.1.3 添加元素
SetAtGrow - 需要时,分配内存
Add - 在数组的末尾添加元素
InsertAt - 在指定的索引位置,插入元素
3.1.1.4 删除元素
RemoveAt
RemoveAll
3.1.1.5 释放不用的内存空间
FreeExtra
注意:
1.如果

存储的时是定义的类的对象,定义类时需要有默认的构造函数,因为在调用类似于InsertAt这样的函数时,
系统内部会调用类的默认构造函数
2.SetSize函数的调用
使用动态数组时,最好预计数组的大小,并通过SetSize函数去设置,避免频繁的分配内存



3.1.2 非模板类,用于存特定类型的数据而设计的4 CUIntArray/CStringArray/CPtrArray/CObjArray
3.2 MFC链表 - 添加或者删除 元素时效率高,所以适用于频繁添加或者删除元素的情况
3.2.1 CList模板类
template< class TYPE, class ARG_TYPE > class CList : public CObject
1.添加元素
AddTail/AddHead
InsertBefore/InsertAfter
2.遍历元素
GetHeadPosition
GetNext
3.元素查找
Find
3.2.2 注意的问题
1.要求自定义的类有默认构造
2.如果需要调用Find函数,要求重载操作符
operator==

3.2.2 非模板类
CStringList/CObList/CPtrList

3.3 MFC映射 - 快速的查找元素的特性

3.3.2 CMap模板类
3.3.1 定义
template< class KEY, class ARG_KEY, class VALUE, class ARG_VALUE >class CMap : public CObject
KEY:元素的键
ARG_KEY:参数的键
VALUE:元素的值
ARG_VALUE:参数的值
3.3.3 非模板类
4 MFC线程
线程分类
1 工作者线程 - 一般没有界面,注意处理后台比较耗时的操作
1.1 定义线程函数
线程函数要么是全局函数,要么是类的静态成员函数
1.2 调用AfxBeginThread()函数,指定线程函数
2 用户界面线程 - 拥有单独的消息队列,可以具有自己的窗口界面,能够对用户的输入和事件作出反应
2.1 定义一个CWinThread类的派生类
3.2 调用AfxBeginThread()函数,指定线程类

Day14
1 组件基础
1.1 函数调用约定,主要约定俩件事情:
1 参数传递顺序
2 栈的清理由谁来完成的?
俩种约定方式__stdcall和__cdecl
__stdcall:压栈方式参数从右向左,被调用者本身完成栈的清空,
被调用者和调用者使用不同语言产生栈的方式是不同的,不同语言的编译器产生栈的方式不同,需要被调用者来清空栈
__cdecl:C/C++的调用约定,参数入栈也是从右向左,由调用者来完成清空栈的操作,
某些情况下被调用者,无法完成栈的清空,例如可变长参数函数,被调用者不知道调用者,使用了多少参数
所以只能由调用者来清空栈
1.2 COM接口
1.2.1 COM接口的规范
1.2.1.1 IUnknown的接口等价性
俩个接口是否相等,需要分别获得俩个接口的IUnknown接口,判断IUnknown接口的地址,如果相等,表示者俩个接口相等
1.2.1.2 接口查询自反性
查询接口时,可以查询到接口本身
1.2.1.3 接口查询的互反性
从接口A可以查询到接口B,从接口B必然

能够查询到接口A
1.2.1.4 接口查询的传递性
从接口A可以查询到接口B,从接口B可以查询到接口C,从接口A必然可以查询到接口C.
1.2.1.5 接口查询的时间无关性
某个时间段,可以从接口A查询到接口B;所有时刻都可以从接口A查询到接口B
1.2.2 COM接口的编写
1 定义IDL文件(math.idl)
2 添加实现接口的类(CImpMath)
3 创建类的对象并返回接口(Createinstance)
2 COM组件
2.1 COM组件的概念
COM接口 - 一组函数的集合
COM组件 - 一组接口的集合,从程序看,组件就是可以执行的代码,从C++看,组件就是一个或者多个类
2.2 COM组件和COM接口之间的关系
C++中组件就是通过一个类或者多个类实现的一组功能,然后通过COM接口将这些功能展现给客户。
-------------
| |--o IUnknown
| |--O IMath
| |
|CImpMath |
| |
-------------
2.3 COM组件的实现
2.3.1 组件ID
每一个组件都通过一个GUID来标识
2.3.2 IDL中定义组件
3 COM组件与ATL库
3.1 ATL库(Active Template Library)
VC6.0集成了ATL3.0库
封装了COM组件实现的细节,可以方便的完成组件的开发
3.2 使用ATL库实现组件
3.2.1 常用的ATL类
1 CComObjectRootBase - 定义了一个引用技术和内部函数
2 CComSingleThreadMode - 对引用计数实现++和--操作
3 CComMultiThreadModel - 对引用计数实现原子锁的++和--操作
4 CComObjectRootEx - 父类是CComObjectRootBase,调用2和3,完成对引用计数的++和--操作
5 CComObject - 实现了IUnknown接口的3个函数,完成组件的定义
3.2.2 组件的实现
1 添加头文件(stdafx.h)
#include
CComModul _Module;
#include
2 添加父类CComObjectRootEx
3 添加结果映射
BEGIN_COM_MAP(CImpMath)
END_COM_MAP
4 添加接口函数的实现
3.2.3 组件的创建
CComObjectRootBase
|->CComObjectRootEx
|->CImpMath
|->CComObject
1 CComObjectRootBase类实现了一个内部函数InternalQueryInterface作用是通过查询在CImpMath中
定义的IID和接口地址的映射关系,返回查询到的地址
2 CComObjectRootEx类实现了
InternalAddRef
InternalRelease
3 CImpMath类实现
_InternalQueryInterface函数,调用了
InternalQueryInterface函数
4 CComObject类
AddRef - 调用InternalAddRef
release- 调用InternalRelease
Queryinterface - 调用_InternalQueryInterface
4 类厂 - 组件创建
4.1 类厂
类厂是创建组件的组件
类厂是组件,作用创建其他组件
4.2 相关的接口和类
类厂的接口:IClassFactory
ATL:CComCoClass类
4.3 类厂的实现
4.3.1 组件添加CComCoClass父类
public CComCoClass
在类的定义前extern vonst SLSID SLSID_Math;
4.3.2 在组件CImp

Math中添加宏
4.3.3 将组件与组件ID建立映射关系
BEGIN_OBJECT_MAO(objectmap)
OBJECT_ENTRY(CLSID_Math,CImpMath)
END_OBJECT_MAP()
4.3.4 将映射关系保存到_Module中
当DLL被初次映射到进程的地址空间时
_Module.Init(objectmap,(HINSTANCE)hModule);

4.4 类厂创建
4.4.1 使用_Module::FetClassObject获取指定组件的类厂
4.4.2 使用类厂CreateInstance函数创建组件
4.5 类厂说明
4.5.1 当组件添加CComCoClass父类之后,会引入类厂创建函数和组件创建函数
4.5.2 创建会保存到组件的ID与组件的映射表中
4.5.3 可以根据组件的ID,获取类厂的创建函数的指针
2 组件的使用
2.1 DLL中的4个导出函数
2.1.1 DllRegisterServer 注册组件,将组件信息写入注册表
2.1.2 DllUnregisterServer 卸载组件,将组件的相关信息从注册表中删除
2.1.3 DllCanUnloadNow 判断组件所在的DLL是否可以卸载
2.1.4 DllGetClassObject 根据组件ID,获取组件的类厂接口
2.2 组件的注册
2.2.1 注册信息
使用*.rgs文件,设置注册信息
CLSID
ProgID
InprocServer32:组件所在的DLL文件的路径
2.2.2 ProgID
为了方便记忆组件的ClassID使用一个字符串来表示一个组件
2.2.3 组件的注册
1 编写完成组件后编译时会自动注册组件
2 可以使用系统自带的regsvr32.exe 手动注册
regsvr32 (/u) 路径:完成注册(卸载)路径可以直接拖拽文件
3 组件的使用
3.1 CoInitialize
初始化COM库,必须在使用组件前调用
一般放在程序的开始调用
3.2 CoCreateInstance
创建组件并返回接口
STDAPI CoCreateInstance(
REFCLSID rclsid,//组件的ID
LPUNKNOWN pUnkOuter,//不使用,NULL
DWORD dwClsContext, //组件的运行方式
REFIID riid, //接口ID
LPVOID *ppv //返回接口的地址
);

3.3 CoUninitialize
卸载COM库,常常在应用程序结束时调用
4 组件的创建过程
4.1 CoCreateInstance首先使用CLSID在注册表中查找组件
4.2 如果找到对应的项,或组件所在的DLL的路径
4.3 加载组件所在的DLL(LoadLibrary)
4.4 获取DllGetClassObject函数,创建组件所对应的类厂
4.5 使用类厂创建组件并返回接口
注意:组件一旦注册,路径不能随意更改,如果路径发生变化,需要重新注册组件
5 COM的智能指针
用于自动的维护接口的指针,包括创建和释放
CComPtr - 完成了基本接口指针的维护
CComQIPtr - 类似于CComPtr,可以自动完成查询功能
3 接口调度
3.1 接口调度
在不使用头文件的情况下,调用接口的函数
3.2 接口调度
BSTR类型 - 字符串类型
VARIANT - 可变类型
SAFEARRAY - 安全数组
IDispatch 接口 - 实现接口调度
3.3 数据类型
3.3.1 BST

R - 字符串类型
|---|-------------------|00|
4 2
字符串的长度 字符串数据 字符串的结尾
1 字符串的创建
SysAllocCstring
2 字符串的释放
SysFreeString
3 CComBSTR ATL库对BSTR的封装
4 _bstr_t C++库对BSTR的封装
3.3.2 VARIANT - 可变类型
分为俩部分
1 各种数据类型的联合体
2 VT值 - 表示数据类型
CComVariant ATL库对VARIANT的封装
_variant_t C++库对VARIANT的封装
3.3.3 SAFEARRAY - 安全数组
数组定义,需要通过定义维数,类型以及每一维的数组数量和索引号,完成了数组的定义
1 创建数组
SafeArrayCreate
2 赋值
SafeArrayPutElement
3 取值
SafeArrayGetElement
4 释放数组
SafeArrayDestory
3.3 IDispatch接口
3.3.1 IDispatch
完成接口函数的调度,可以在不使用头文件的情况下,调用接口函数.

相关文档
最新文档