[MFC]MFC程序结构(二)

窗口创建过程

1.1 加载菜单
1.2 调用CWnd::CreateEx创建窗口
    1.2.1 调用 PreCreateWindow 设计并注册窗口类  
    1.2.2 调用AfxHookWindowCreate设置钩子————HOOK(钩子)-将自己的处理函数,挂接入系统的处理过程。
           调用SetWindowsHookEx,创建了一个WH_CBT类型的钩子,_AfxCbtFilterHook钩子的回调函数。
    1.2.3 调用CreateWindowEx创建窗口,立即调用_AfxCbtFilterHook
    1.2.4 调用AfxUnhookWindowCreate 卸载钩子
1.3 _AfxCbtFilterHook函数执行
    1.3.1 获取MFC提供的窗口处理函数的地址(AfxWndProcBase的地址)
    1.3.2 使用SetWindowLong将窗口的处理函数由原来的DefWindowProc替换为AfxWndProcBase

消息映射机制

Windows程序中的消息处理是在winproc函数中,通过switch结构实现的。但当处理的消息比较多时,switch-case结构将变得分支很多,影响程序的可读性。而在MFC中,则采用消息映射的结构进行结构化消息处理。进行MFC消息处理,程序员要做的就是为每个要处理的消息提供一个消息处理函数,然后系统通过MFC提供的一套消息映射系统来调用相应的消息处理函数。消息映射就是消息与消息处理函数一对一的联系。MFC的消息映射采用消息映射宏的方式,把消息和消息处理函数一一对应起来。在其头文件中可以找到DECLARE_MESSAGE_MAP()宏。

消息映射机制的使用    

     1.1 在窗口类的定义中添加消息映射的声明宏
         DECLARE_MESSAGE_MAP()  
     1.2 在窗口类的实现中添加消息映射的实现宏
         BEGIN_MESSAGE_MAP(CMsgFrame,CFrameWnd)
         END_MESSAGE_MAP() 
     1.3 添加消息处理函数的定义和实现 
     1.4 添加消息标识与消息处理函数的映射关系
         BEGIN_MESSAGE_MAP(CMsgFrame,CFrameWnd)
          ON_MESSAGE(WM_CREATE,OnCreate)
          ON_MESSAGE(WM_PAINT,OnPaint)
         END_MESSAGE_MAP()

MFC对消息的分类

MFC把消息分为5类:窗口消息,控件通知消息,命令消息,用户自定义消息,系统注册消息

  • 窗口消息(标准消息)

大部分的窗口,键盘,鼠标等消息,如当创建窗口,绘制窗口,移动窗口,销毁窗口,以及使用键盘,鼠标等与操作窗口有关的动作时,产生的消息均属于窗口消息。窗口消息有MFC的窗口(CWnd)对象来处理。系统提供了标准的消息处理函数。
消息映射宏:ON_WM_XXX()

  • 控件通知消息

控件是一个windows的一个子窗口(eg:对话框中的按钮,编辑框等),控件通知消息是指在事件发生时,由控件或其他类型的子窗口发送到父窗口的消息。它通知父窗口,该控件接受了某操作,为父窗口进一步控制子窗口提供了条件。
消息映射宏:ON_xx_CLICKED/DBCLK(控件ID,响应函数)

  • 命令消息

菜单,工具栏以及按钮等消息。一般与处理用户的请求有关,主要是来自菜单,工具栏和加速键的通知消息。从CCmdTarget派生的类(eg:文档,文档模板,应用程序对象,窗口和视图等)都能处理命令消息。
消息映射宏:ON_COMMAND(命令ID,响应函数)
ON_COMMAND_RANGE(起始ID,终止ID,响应函数)
响应函数基本是:afx_msg void memberFun()
所有由用户定义的命令消息也由ON_COMMAND定义消息映射关系。
命令消息的执行过程:
2.1在CWnd::OnWndMsg函数中,判断消息如果是WM_COMMAND调用OnCommand函数
2.2 在OnCommand函数,调用CCmdTarget::OnCmdMsg函数
2.3 在OnCmdMsg函数中,查找消息映射。

  • 用户自定义消息

通过#define定义消息标识,eg #define WM_USERDEFMSG (WM_USER+101)
消息映射宏:ON_MESSAGE(命令ID,响应函数)
响应函数的原型:afx_msg LRESULT memberFun(WPARAM,LPARAM)

  • 系统注册消息

UINT RegisterWindowMessage(LPCTSTR lpString   //消息名称);//返回值消息标识
消息映射宏:ON_REGISTERED_MESSAGE(注册ID,响应函数)
响应函数的原型:afx_msg LRESULT memberFun(WPARAM,LPARAM)
eg:const UINT WM_USERDEFMSG=::RegisterWindowMessage(_T("UserDefMsg"));
ON_REGISTERED_MESSAGE(WM_USERDEFMSG,OnUserDefMsg)

实例

1.新建工程MFCBase

新建MFC工程(view或者dialog),删除系统生产的文件,就剩下stdafx.h和stdafx.cpp,新建MFCBase.cpp文件,

或者,新建Win32工程来改成MFC工程,删除系统生产的文件,就剩下stdafx.h(在其内部添加afxwin.h头文件)和stdafx.cpp,新建MFCBase.cpp文件;并修改工程的属性,常规-->MFC的使用:把使用标准windows库 改成 在静态库中使用MFC

#include "stdafx.h"
class CMainFrame:public CFrameWnd
{
public:
	virtual LRESULT WindowProc( UINT message, WPARAM wParam, LPARAM lParam );
};
LRESULT CMainFrame::WindowProc( UINT message, WPARAM wParam, LPARAM lParam )
{
	switch (message)
	{
	case WM_CREATE:
		MessageBox(L"OnCreate");
		break;
	case WM_PAINT:
		PAINTSTRUCT ps={0};
		CDC* pDC=BeginPaint(&ps);
		pDC->TextOut(50,100,L"Hello MFC");
		EndPaint(&ps);
		break;
	}
	return CFrameWnd::WindowProc(message,wParam,lParam);
}  
class CMyWinApp:public CWinApp
{
public:
	virtual BOOL InitInstance();
};
BOOL CMyWinApp::InitInstance()
{
	CMainFrame* pFrame=new CMainFrame;
	pFrame->Create(NULL,L"MFCWnd");
	m_pMainWnd=pFrame;
	pFrame->ShowWindow(SW_SHOW);
	pFrame->UpdateWindow();
	return TRUE;
}
CMyWinApp theApp; 

结果:先出现对话框:[MFC]MFC程序结构(二)_第1张图片再出现框架窗口:[MFC]MFC程序结构(二)_第2张图片

2.新建工程MFCCmd

创建工程同上,新建文件MFCCmd.cpp文件

// MyMFCCmd.cpp : 定义应用程序的入口点。 
#include "stdafx.h"  
#define ON_CMD_T1 1025//菜单消息标识
#define ON_CMD_T2 1026//菜单消息标识
#define ON_CMD_T3 1027//菜单消息标识
#define ON_CMD_EDIT 1028//菜单消息标识
#define WM_USERDEFMSG (WM_USER+101)//用户自定义消息标识
const UINT WM_USERDEFMSG2=RegisterWindowMessage(L"UserDefMsg2");//系统注册消息标识
class CMainFrame:public CFrameWnd
{
	DECLARE_MESSAGE_MAP()
protected:
	afx_msg int OnCreate( LPCREATESTRUCT lpCreateStruct );
	afx_msg void OnTest1();
	afx_msg void OnTestRange(UINT nID);
	afx_msg void OnEditChange();
	afx_msg LRESULT OnUserDefMsg(WPARAM wParam,LPARAM lParam);//用户自定义消息函数
	afx_msg LRESULT OnUserDefMsg2(WPARAM wParam,LPARAM lParam);//系统注册消息函数
}; 
BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)
	ON_WM_CREATE()//窗口消息
	ON_COMMAND(ON_CMD_T1,OnTest1)//命令消息
	ON_MESSAGE(WM_USERDEFMSG,OnUserDefMsg)//用户自定义消息
	ON_REGISTERED_MESSAGE(WM_USERDEFMSG2,OnUserDefMsg2)//系统注册消息
	ON_EN_CHANGE(ON_CMD_EDIT,OnEditChange)//控件消息
	ON_COMMAND_RANGE(ON_CMD_T2,ON_CMD_T3,OnTestRange)
END_MESSAGE_MAP() 
int CMainFrame::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
	//创建按钮
	CreateWindow(L"BUTTON",L"Test1",WS_CHILD|WS_VISIBLE,50,50,60,40,m_hWnd,(HMENU)ON_CMD_T1,AfxGetInstanceHandle(),NULL);
	CreateWindow(L"BUTTON",L"Test2",WS_CHILD|WS_VISIBLE,50,100,60,40,m_hWnd,(HMENU)ON_CMD_T2,AfxGetInstanceHandle(),NULL);
	CreateWindow(L"BUTTON",L"Test3",WS_CHILD|WS_VISIBLE,50,150,60,40,m_hWnd,(HMENU)ON_CMD_T3,AfxGetInstanceHandle(),NULL);
	CreateWindow(L"EDIT",L"",WS_CHILD|WS_VISIBLE|WS_BORDER,150,90,70,50,m_hWnd,(HMENU)ON_CMD_EDIT,AfxGetInstanceHandle(),NULL);
	return 0;
}
LRESULT CMainFrame::OnUserDefMsg(WPARAM wParam,LPARAM lParam)
{
	MessageBox(L"OnUserDefMsg");
	return 0;
}
LRESULT CMainFrame::OnUserDefMsg2(WPARAM wParam,LPARAM lParam)
{
	MessageBox(L"OnUserDefMsg2");
	return 0;
}
void CMainFrame::OnTest1()
{
	//MessageBox(L"OnTest1");	
	SendMessage(WM_USERDEFMSG,NULL,NULL);//发送系统注册消息 	
	SendMessage(WM_USERDEFMSG2,NULL,NULL);//发送用户自定义消息
}
void CMainFrame::OnTestRange(UINT nID)
{
	CString strID;
	strID.Format(L"%d",nID);
	MessageBox(strID); 
}  
void CMainFrame::OnEditChange()
{
	CWnd* pWnd=GetDlgItem(ON_CMD_EDIT);
	CString strContent;
	pWnd->GetWindowTextW(strContent);
	MessageBox(strContent);
}

class CCmdApp:public CWinApp
{
public:
	virtual BOOL InitInstance();
};
BOOL CCmdApp::InitInstance()
{
	CMainFrame* pFrame=new CMainFrame;
	pFrame->Create(NULL,L"MFCCmd");
	m_pMainWnd=pFrame;
    pFrame->ShowWindow(SW_SHOW);
	pFrame->UpdateWindow();
	return TRUE;
}
CCmdApp theApp; 

结果:点击test2按钮[MFC]MFC程序结构(二)_第3张图片输入e:[MFC]MFC程序结构(二)_第4张图片

3.分析这两个工程的异同

相同点:各自都创建了CFrameWin框架窗口子类和CWinApp窗口应用子类,且重写窗口应用的初始化成员函数InitInstance()基本相同

不同点:主要表现在创建创建窗口的过程和消息的处理方面。工程MFCBase主要根据win32窗口应用程序的思想来创建窗口和处理消息的。而工程MFCCmd用到了MFC的消息映射来创建窗口和处理消息的。

你可能感兴趣的:([MFC]MFC程序结构(二))