MFC应用程序编程
一 MFC的发展
VC 1.0->VC 5.0->VC 6.0->VC2008 SP1)->VS2010
二 MFC基础
1 MFC 微软基础类库
采用类的方式,将Win32 API等进行封装,
形成的库.
2 MFC相关的头文件
afx.h (application framework, X)
afxwin.h (类似于windows.h)
afxext.h MFC扩展头文件
...
三 MFC应用程序
1 MFC的控制台程序
1.1 包含afx系列的头文件
1.2 CWinApp theApp - MFC的应用程序类
封装了应用程序的启动过程.
1.3 AfxWinInit MFC初始化函数
将应用程序的信息初始化.
2 MFC的动态库和静态库
2.1 静态库 - 增加了MFC的支持
2.2 动态库
2.2.1 MFC规则DLL
2.2.1.1 使用MFC静态库的规则DLL
2.2.1.2 使用MFC动态库的规则DLL
2.2.2 MFC扩展DLL
2.3 不同
2.3.1 MFC相关的afx头文件
2.3.2 包含一个继承CWinApp类, 并且
声明了该类的全局变量.
3 MFC应用程序
3.1 单文档视图应用程序
3.1.1 包含一个继承CWinApp类
3.1.2 CMainFrame类
3.1.3 CView的一个子类
3.1.4 CDocument的一个子类
3.2 多文档视图应用程序
3.2.1 包含一个继承CWinApp类
3.2.2 CMainFrame类
3.2.3 CView的一个子类
3.2.4 CDocument的一个子类
3.2.5 CChildFrame 子框架窗口
3.3 对话框应用程序
3.3.1 包含一个继承CWinApp类
3.3.2 对话框类
四 MFC中的类
1 CObject类
MFC类的基础,大部分MFC类都是它的子类.
CObject封装了MFC的基础的机制
1.1 new和Delete
1.2 Assert
1.3 运行式信息
1.4 动态创建
1.5 序列化
2 应用程序框架
应用程序启动相关信息,以及MFC消息映射
机制。
3 窗口支持类
封装了窗口操作的API,各种控件及窗口的
框架.
4 绘图类
提供了绘图API的封装,以及相关的GDI设备
封装.
5 MFC的集合类
提供了数组、链表、映射的数据结构的操作.
6 数据库支持类
ODBC支持类和DAO的支持类。
DAO的类已作废.
7 同步类
临界区/事件/互斥/信号量的封装
8 Socket类
封装了socket的编程.
9 常用数据结构
CString CRect CPoint等.
五 第一个MFC程序
1 环境设置
1.1 修改头文件
1.2 在Setting中增加MFC库支持
2 增加应用程序类CWinApp
2.1 添加CWinApp的子类CMyApp
2.2 添加InitInstance函数
是在程序启动过程中,会被调用,我们可以
在这个函数中,创建窗口或者各种初始化
操作.
2.3 添加CMyApp的全局变量
3 窗口
3.1 添加CFrameWnd的子类CMyFrameWnd
3.2 在App的InitInstance函数定义窗口
对象
3.3 创建窗口(Create)并显示(ShowWindow)
3.4 将窗口设置成App的主窗口
m_pMainWnd = pWnd;
3.5 在CMyFrameWnd中添加窗口处理函数
WindowProc,在WindowProc中处理消息
//框架窗口类
class CMyFramWnd : public CFrameWnd
{
public:
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
};
LRESULT CMyFramWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
AfxMessageBox("创建窗口");
break;
case WM_PAINT:
{
PAINTSTRUCT ps = {0};
HDC hDC = ::BeginPaint( m_hWnd , &ps ); //窗口自带句柄参数, ::BeginPaint-全局系统API函数
TextOut(hDC, 200, 200, "Hello World!",11);
EndPaint(&ps);
}
}
return CFrameWnd::WindowProc(message, wParam, lParam);
}
//应用程序类
class CMyApp : public CWinApp
{
public:
virtual BOOL InitInstance(); //重载基类中虚函数实现动态联编
};
CMyApp theApp;
BOOL CMyApp::InitInstance()
{
//AfxMessageBox("Hello App");
//定义窗口对象
CMyFramWnd *pWnd = new CMyFramWnd();
//创建窗口
pWnd->Create(NULL,"MFC窗口");
pWnd->ShowWindow(SW_SHOW);
//设置主窗口
m_pMainWnd = pWnd;
return TRUE;
}
MFC应用程序与Win32程序一样,都需要程序
的入口函数.
1 CWinApp
应用程序类,封装了应用程序的相关信息,
可以提供初始化 消息循环等处理.
CWinApp的构造函数:
1.1 将this指针保存到ThreadState中.
m_pCurrentWinThread = this
1.2 将this指针保存到ModuleState中
m_pCurrentWinApp = this
1.3 各种的成员变量的初始化
2 程序的入口函数
2.1 WinMain函数,与Win32程序一致.
2.2 在WinMain函数中,调用了AfxWinMain
函数.
2.3 AfxWinMain函数
2.3.1 调用AfxWinInit初始化应用程序
2.3.2 调用CWinApp的InitApplication
初始MFC内部数据
2.3.3 调用CWinThread的InitInstance
函数做初始化操作
2.3.4 调用CWinThread的Run函数进行
消息循环
2.3.5 调用AfxWinTerm函数做退出处理.
3 程序的启动
3.1 CWinApp在构造过程中, 将自己的this
指针分别保存到全局变量中.
3.2 在AfxWinMain执行中,首先从全局变量
中将保存CWinApp的地址获取到.
3.3 调用CWinApp的InitInstance函数,进行
初始化.我们在InitInstance函数中,创建
窗口等初始化操作.
3.4 调用Run函数,进行消息循环.
七 窗口创建及窗口处理函数
1 窗口创建
1.1 窗口的参数初始化,包括窗口类.风格
窗口处理函数等信息.
注意:
将DefWindowProc注册成窗口处理函数.
1.2 设置 创建HOOK (钩子)
当窗口创建的时候,调用这个HOOK函数.
Wnd -> HOOK -> WndProc
1.3 创建窗口
CreateWindowEx
1.4 卸载创建HOOK
将HOOK程序从当前程序中移除
2 HOOK(钩子)程序
2.1 使用AfxGetAfxWndProc函数获取了
一个WNDPROC函数指针, 也就是
AfxWndProc(AfxWndProcBase)函数
地址.
2.2 将这个WNDPROC函数设置成当前窗口的
处理函数
2.3 将窗口句柄和窗口类的指针保存到
MFC的映射数据中.(afxMapHWND函数)
3 AfxWndProc(Base)窗口处理函数
3.1 根据窗口句柄获取了相对应的窗口
的CWnd *类型的指针,从映射数据中
根据窗口句柄查找CWnd *指针.
(afxMapHWND函数)
3.2 调用AfxCallWndProc函数
3.3 在AfxCallWndProc函数中,调用CWnd
的WindowProc函数
注意: 在MFC程序当中,所有窗口处理都是
使用一个函数.
4 窗口的创建及处理过程
4.1 将DefWindowProc函数注册成当前
窗口的处理函数
4.2 设置钩子函数
4.3 创建窗口,并执行钩子函数
4.4 将窗口类指针和窗口句柄的对应关系
保存.
4.5 在钩子函数将AfxWndProc(Base)函数
设置当前窗口的窗口处理函数
4.6 在AfxWndProc(Base)收到窗口消息,
从窗口对应关系中,查询相应的窗
口类指针.
4.7 调用窗口类WindowProc函数处理消息
八 消息映射
1 消息映射添加
1.1 在FrameWnd添加消息宏定义
DECLARE_MESSAGE_MAP
1.2 添加消息宏实现
1.3 添加消息处理函数
1.4 添加消息和处理函数的对应
2 消息宏的实现
2.1 数据类型
2.1.1 AFX_MSGMAP_ENTRY 是用于保存
消息ID与对应函数指针,及相关的信息
struct AFX_MSGMAP_ENTRY
{
UINT nMessage; //消息ID
UINT nCode;//通知代码
UINT nID; //控件的ID
UINT nLastID;//控件的ID范围的最后
UINT nSig;//操作类型或pfn函数类型
AFX_PMSG pfn;//消息处理函数的函数指针
};
2.1.2 AFX_MSGMAP 用于保存GetBaseMap
的函数地址及AFX_MSGMAP_ENTRY数组的
地址.
struct AFX_MSGMAP
{
const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
//函数指针
const AFX_MSGMAP_ENTRY* lpEntries;
//AFX_MSGMAP_ENTRY类型指针
};
2.2 代码
class CMsgFrame : public CFrameWnd
{
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;
}
const AFX_MSGMAP* PASCAL CMsgFrame::_GetBaseMessageMap()
{
return &CFrameWnd::messageMap;
}
const AFX_MSGMAP* CMsgFrame::GetMessageMap() const
{
return &CMsgFrame::messageMap;
}
AFX_COMDAT AFX_DATADEF const AFX_MSGMAP CMsgFrame::messageMap =
{
&CMsgFrame::_GetBaseMessageMap,
&CMsgFrame::_messageEntries[0]
};
AFX_COMDAT const AFX_MSGMAP_ENTRY CMsgFrame::_messageEntries[] =
{
{ 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 }
};
一 MFC的发展
VC 1.0->VC 5.0->VC 6.0->VC2008 SP1)->VS2010
二 MFC基础
1 MFC 微软基础类库
采用类的方式,将Win32 API等进行封装,
形成的库.
2 MFC相关的头文件
afx.h (application framework, X)
afxwin.h (类似于windows.h)
afxext.h MFC扩展头文件
...
三 MFC应用程序
1 MFC的控制台程序
1.1 包含afx系列的头文件
1.2 CWinApp theApp - MFC的应用程序类
封装了应用程序的启动过程.
1.3 AfxWinInit MFC初始化函数
将应用程序的信息初始化.
2 MFC的动态库和静态库
2.1 静态库 - 增加了MFC的支持
2.2 动态库
2.2.1 MFC规则DLL
2.2.1.1 使用MFC静态库的规则DLL
2.2.1.2 使用MFC动态库的规则DLL
2.2.2 MFC扩展DLL
2.3 不同
2.3.1 MFC相关的afx头文件
2.3.2 包含一个继承CWinApp类, 并且
声明了该类的全局变量.
3 MFC应用程序
3.1 单文档视图应用程序
3.1.1 包含一个继承CWinApp类
3.1.2 CMainFrame类
3.1.3 CView的一个子类
3.1.4 CDocument的一个子类
3.2 多文档视图应用程序
3.2.1 包含一个继承CWinApp类
3.2.2 CMainFrame类
3.2.3 CView的一个子类
3.2.4 CDocument的一个子类
3.2.5 CChildFrame 子框架窗口
3.3 对话框应用程序
3.3.1 包含一个继承CWinApp类
3.3.2 对话框类
四 MFC中的类
1 CObject类
MFC类的基础,大部分MFC类都是它的子类.
CObject封装了MFC的基础的机制
1.1 new和Delete
1.2 Assert
1.3 运行式信息
1.4 动态创建
1.5 序列化
2 应用程序框架
应用程序启动相关信息,以及MFC消息映射
机制。
3 窗口支持类
封装了窗口操作的API,各种控件及窗口的
框架.
4 绘图类
提供了绘图API的封装,以及相关的GDI设备
封装.
5 MFC的集合类
提供了数组、链表、映射的数据结构的操作.
6 数据库支持类
ODBC支持类和DAO的支持类。
DAO的类已作废.
7 同步类
临界区/事件/互斥/信号量的封装
8 Socket类
封装了socket的编程.
9 常用数据结构
CString CRect CPoint等.
五 第一个MFC程序
1 环境设置
1.1 修改头文件
1.2 在Setting中增加MFC库支持
2 增加应用程序类CWinApp
2.1 添加CWinApp的子类CMyApp
2.2 添加InitInstance函数
是在程序启动过程中,会被调用,我们可以
在这个函数中,创建窗口或者各种初始化
操作.
2.3 添加CMyApp的全局变量
3 窗口
3.1 添加CFrameWnd的子类CMyFrameWnd
3.2 在App的InitInstance函数定义窗口
对象
3.3 创建窗口(Create)并显示(ShowWindow)
3.4 将窗口设置成App的主窗口
m_pMainWnd = pWnd;
3.5 在CMyFrameWnd中添加窗口处理函数
WindowProc,在WindowProc中处理消息
#include "stdafx.h"
//框架窗口类
class CMyFramWnd : public CFrameWnd
{
public:
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
};
LRESULT CMyFramWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
AfxMessageBox("创建窗口");
break;
case WM_PAINT:
{
PAINTSTRUCT ps = {0};
HDC hDC = ::BeginPaint( m_hWnd , &ps ); //窗口自带句柄参数, ::BeginPaint-全局系统API函数
TextOut(hDC, 200, 200, "Hello World!",11);
EndPaint(&ps);
}
}
return CFrameWnd::WindowProc(message, wParam, lParam);
}
//应用程序类
class CMyApp : public CWinApp
{
public:
virtual BOOL InitInstance(); //重载基类中虚函数实现动态联编
};
CMyApp theApp;
BOOL CMyApp::InitInstance()
{
//AfxMessageBox("Hello App");
//定义窗口对象
CMyFramWnd *pWnd = new CMyFramWnd();
//创建窗口
pWnd->Create(NULL,"MFC窗口");
pWnd->ShowWindow(SW_SHOW);
//设置主窗口
m_pMainWnd = pWnd;
return TRUE;
}
MFC应用程序与Win32程序一样,都需要程序
的入口函数.
1 CWinApp
应用程序类,封装了应用程序的相关信息,
可以提供初始化 消息循环等处理.
CWinApp的构造函数:
1.1 将this指针保存到ThreadState中.
m_pCurrentWinThread = this
1.2 将this指针保存到ModuleState中
m_pCurrentWinApp = this
1.3 各种的成员变量的初始化
2 程序的入口函数
2.1 WinMain函数,与Win32程序一致.
2.2 在WinMain函数中,调用了AfxWinMain
函数.
2.3 AfxWinMain函数
2.3.1 调用AfxWinInit初始化应用程序
2.3.2 调用CWinApp的InitApplication
初始MFC内部数据
2.3.3 调用CWinThread的InitInstance
函数做初始化操作
2.3.4 调用CWinThread的Run函数进行
消息循环
2.3.5 调用AfxWinTerm函数做退出处理.
3 程序的启动
3.1 CWinApp在构造过程中, 将自己的this
指针分别保存到全局变量中.
3.2 在AfxWinMain执行中,首先从全局变量
中将保存CWinApp的地址获取到.
3.3 调用CWinApp的InitInstance函数,进行
初始化.我们在InitInstance函数中,创建
窗口等初始化操作.
3.4 调用Run函数,进行消息循环.
七 窗口创建及窗口处理函数
1 窗口创建
1.1 窗口的参数初始化,包括窗口类.风格
窗口处理函数等信息.
注意:
将DefWindowProc注册成窗口处理函数.
1.2 设置 创建HOOK (钩子)
当窗口创建的时候,调用这个HOOK函数.
Wnd -> HOOK -> WndProc
1.3 创建窗口
CreateWindowEx
1.4 卸载创建HOOK
将HOOK程序从当前程序中移除
2 HOOK(钩子)程序
2.1 使用AfxGetAfxWndProc函数获取了
一个WNDPROC函数指针, 也就是
AfxWndProc(AfxWndProcBase)函数
地址.
2.2 将这个WNDPROC函数设置成当前窗口的
处理函数
2.3 将窗口句柄和窗口类的指针保存到
MFC的映射数据中.(afxMapHWND函数)
3 AfxWndProc(Base)窗口处理函数
3.1 根据窗口句柄获取了相对应的窗口
的CWnd *类型的指针,从映射数据中
根据窗口句柄查找CWnd *指针.
(afxMapHWND函数)
3.2 调用AfxCallWndProc函数
3.3 在AfxCallWndProc函数中,调用CWnd
的WindowProc函数
注意: 在MFC程序当中,所有窗口处理都是
使用一个函数.
4 窗口的创建及处理过程
4.1 将DefWindowProc函数注册成当前
窗口的处理函数
4.2 设置钩子函数
4.3 创建窗口,并执行钩子函数
4.4 将窗口类指针和窗口句柄的对应关系
保存.
4.5 在钩子函数将AfxWndProc(Base)函数
设置当前窗口的窗口处理函数
4.6 在AfxWndProc(Base)收到窗口消息,
从窗口对应关系中,查询相应的窗
口类指针.
4.7 调用窗口类WindowProc函数处理消息
八 消息映射
1 消息映射添加
1.1 在FrameWnd添加消息宏定义
DECLARE_MESSAGE_MAP
1.2 添加消息宏实现
1.3 添加消息处理函数
1.4 添加消息和处理函数的对应
2 消息宏的实现
2.1 数据类型
2.1.1 AFX_MSGMAP_ENTRY 是用于保存
消息ID与对应函数指针,及相关的信息
struct AFX_MSGMAP_ENTRY
{
UINT nMessage; //消息ID
UINT nCode;//通知代码
UINT nID; //控件的ID
UINT nLastID;//控件的ID范围的最后
UINT nSig;//操作类型或pfn函数类型
AFX_PMSG pfn;//消息处理函数的函数指针
};
2.1.2 AFX_MSGMAP 用于保存GetBaseMap
的函数地址及AFX_MSGMAP_ENTRY数组的
地址.
struct AFX_MSGMAP
{
const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
//函数指针
const AFX_MSGMAP_ENTRY* lpEntries;
//AFX_MSGMAP_ENTRY类型指针
};
2.2 代码
class CMsgFrame : public CFrameWnd
{
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;
}
const AFX_MSGMAP* PASCAL CMsgFrame::_GetBaseMessageMap()
{
return &CFrameWnd::messageMap;
}
const AFX_MSGMAP* CMsgFrame::GetMessageMap() const
{
return &CMsgFrame::messageMap;
}
AFX_COMDAT AFX_DATADEF const AFX_MSGMAP CMsgFrame::messageMap =
{
&CMsgFrame::_GetBaseMessageMap,
&CMsgFrame::_messageEntries[0]
};
AFX_COMDAT const AFX_MSGMAP_ENTRY CMsgFrame::_messageEntries[] =
{
{ 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 }
};