MFC第三天

Windows消息机制
应用程序的输入由Windows系统以消息的形式发送给应用程序的窗口
MFC消息机制
使用MFC框架编程时,消息发送和处理的本质仍然是Windows消息机制,
MFC简化了程序员编程时处理消息的复杂性
MFC消息映射<程序启动机制,窗口创建机制,这是第三个机制,消息映射机制>
就是让程序员可以方便的指定要某个有消息处理能力的MFC类,能够处理某个消息

先写段代码吧,仍然用Win32来改吧。
// MFCBase.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "MFCBase.h"
class CMyFrameWnd:public CFrameWnd{
DECLARE_MESSAGE_MAP()   //声明宏
public:
LRESULT OnCreate(WPARAM wParam,LPARAM lParam);
};


BEGIN_MESSAGE_MAP(CMyFrameWnd,CFrameWnd) //实现宏这三个宏实现了消息映射机制
     ON_MESSAGE(WM_CREATE,OnCreate)
END_MESSAGE_MAP()
LRESULT CMyFrameWnd::OnCreate(WPARAM wParam,LPARAM lParam){
AfxMessageBox(_T("wm_create"));
return 0;
}
class CMyWinApp: public CWinApp{
public:
   virtual BOOL InitInstance();
};
CMyWinApp theApp;
BOOL CMyWinApp::InitInstance(){
CMyFrameWnd *pFrame=new CMyFrameWnd;
CString str=_T("this is a window");
LPCTSTR lpszWindowName=str;
pFrame->Create(NULL,lpszWindowName);
pFrame->ShowWindow(SW_NORMAL);
pFrame->UpdateWindow();
m_pMainWnd=pFrame;
return TRUE;
}



在FrameWnd添加消息宏定义
DECLARE_MESSAGE_MAP
添加消息宏实现
BEGIN_MESSAGE_MAP( theClass, parentClass )
END_MESSAGE_MAP( )
添加消息处理函数
afx_msg LRESULT OnPaint( WPARAM wParam, LPARAM lParam );
添加消息和处理函数的对应
ON_MESSAGE( WM_PAINT, OnPaint )
//
DECLARE_MESSAGE_MAP实际上是替换成了:
private:
static const AFX_MSGMAP_ENTRY _messageEntries[];
protected:
static AFX_DATA const AFX_MSGMAP messageMap;
virtual const AFX_MSGMAP* GetMessageMap() const;


BEGIN_MESSAGE_MAP(theClass,baseClass)实际上是替换成了:
PTM_WARNING_DISABLE 
const AFX_MSGMAP* theClass::GetMessageMap() const
{ return GetThisMessageMap(); }
const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() 

typedef theClass ThisClass;  
typedef baseClass TheBaseClass;  
static const AFX_MSGMAP_ENTRY _messageEntries[] =  
{
/OnMEssage
{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } 
}; 
static const AFX_MSGMAP messageMap = 
{ &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; 
return &messageMap; 
}  
//
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;//消息处理函数的函数指针
};
AFX_MSGMAP结构
用于保存GetBaseMap的函数地址,以及AFX_MSGMAP_ENTRY数组的地址.
struct AFX_MSGMAP
{
      //函数指针
      const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
      //AFX_MSGMAP_ENTRY类型指针
     const AFX_MSGMAP_ENTRY* lpEntries;
};

class CMsgFrame : public CFrameWnd 
{
private:
      static const FX_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 } 
}; 
/
_messageEntries[]
静态数组
类型为 AFX_MSGMAP_ENTRY
保存CMsgFrame中消息ID和对应的消息处理函数的数组
messageMap
静态变量
类型为 AFX_MSGMAP
保存了CMsgFrame中的_GetBaseMessageMap函数指针以及_messageEntries数组地址
GetBaseMessageMap
静态函数
获取父类的messageMap的地址
GetMessageMap
虚函数
获取本身的messageMap地址
//
消息处理函数WindowProc收到消息后,调用OnWndMsg处理消息
OnWndMsg如果不处理消息,WindowProc函数调用DefWindowProc默认处理消息并返回,否则OnWndMsg处理消息继续执行。
使用GetMessageMap函数获取该窗口类的messageMap变量的地址
const AFX_MSGMAP* pMessageMap; 
pMessageMap = GetMessageMap();//拿到链表的尾结点,遍历找东西 。
在messageMap中的lpEntries数组中,查找消息ID所对应的数组元素
如果未找到,获取父类的messageMap指针,从父类的lpEntries数组继续查找
如果找到,获取找到的数组元素的地址lpEntry,退出查找过程,执行下一步
在messageMap中的lpEntries数组中,查找消息ID所对应的数组元素。
根据找到的消息处理函数的类型标识,调用对应的的函数指针,处理消息。

pWnd->WindowProc(nMsg,)//函数内部this指针为pFrame
{
OnWndMsg(nMsg)//函数内部this指针为pFrame
{
const AFX_MSGMAP* pMessageMap=GetMessageMap();//获取本类的静态变量地址(链表的尾结点)
const AFX_MSGMAP_ENTRY* lpEntry;
for(链表尾结点,pMessageMap!=NULL,pMessageMap=pMessageMap->pBaseMap)//遍历链表
{
lpEntry=AfxFindMessageEntry(pMessageMap->lpEntries,message,0,0);//找消息所对应 的数据元素
if(lpEntry!=NULL)
goto LDispatch;
}
LDispatch:
union MessageMapFunctions mmf;//联合体
mmf.pfn=lpEntry->pfn;//将数组元素最后一个成员函数指针OnCreate赋给mmf第一个成员
int nSig=lpEntry->nSig;//AfxSig_lwl.决定调用联合体的哪个成员
switch(nSig){
case AfxSig_lwl:
lResult=(this->*mmf.pfn_lwl)(wParam,lParam);
break;
}
}}
//
LRESULT CMyFrameWnd::OnPaint(WPARAM wParam,LPARAM lParam){
PAINTSTRUCT ps={0};
HDC hDC=::BeginPaint(this->m_hWnd,&ps);
::TextOut(hDC,100,100,"WM_PAINT",strlen("adfafd"));
::EndPaint(m_hwnd,&ps);
}
/
窗口消息
例如WM_CREATE、WM_PAINT、鼠标、键盘等消息,这些消息的处理方式是直接调用消息处理函数.
这类消息使用的宏
ON_MESSAGE(  )
ON_WM_XXXXX( )
ON_WM_CREATE()
消息处理
基本采用前述的方式。
命令消息
菜单、工具栏、按钮等点击时的命令
消息首先发送到主窗口,由主窗口逐层向子窗口派发。
这类的消息使用的宏
ON_COMMAND(id,memberFxn )
ON_COMMAND_RANGE( )//多个按钮使用同一个处理函数
消息处理
在OnWndMsg中调用OnCommand处理函数进行消息处理。
通知消息
子窗口对父窗口的通知消息。
控件消息宏,例如: 
EDIT控件 ON_EN_CHANGE
ON_NOTIFY/ON_NOTIFY_RANGE
消息处理
在OnWndMsg中调用OnNotify (OnCommand)处理函数进行消息处理
用户自定义消息
用户自注册消息的处理。
用户需调用RegisterWindowMessage函数注册消息,然后在消息映射中使用。
返回注册成功的消息ID(0xC000-0xFFFF)
消息映射宏: 
ON_REGISTERED_MESSAGE
消息处理
与窗口消息处理类似,但是在查找消息处理函数和执行消息处理函数时不同。

// MFCBase.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "MFCBase.h"
#define WM_MYMESSAGE WM_USER+100  //自定义消息
//自注册消息
UINT WM_USERMSG=RegisterWindowMessage(_T("sadasd"));//自注册消息,与自定义消息差不多
class CMyFrameWnd:public CFrameWnd{
DECLARE_MESSAGE_MAP()
public:
//LRESULT OnCreate(WPARAM wParam,LPARAM lParam);
afx_msg int OnCreate(LPCREATESTRUCT cs);//afx_msg为占位符,表明这个函数处理消息的
afx_msg void OnPaint();
afx_msg void OnTest1();
afx_msg void OnTest(UINT nid);
afx_msg void OnEnChange();
afx_msg LRESULT OnMyMessage(WPARAM wParam,LPARAM lParam);
afx_msg LRESULT OnUserMsg(WPARAM wParam,LPARAM lParam);
};


BEGIN_MESSAGE_MAP(CMyFrameWnd,CFrameWnd)
     //ON_MESSAGE(WM_CREATE,OnCreate)
ON_WM_CREATE()
ON_WM_PAINT()
ON_COMMAND(1001,OnTest1)//控件命令
ON_COMMAND_RANGE(1002,1003,OnTest)
ON_EN_CHANGE(1004,OnEnChange)//编辑框通知消息
ON_MESSAGE(WM_MYMESSAGE,OnMyMessage)//自定义消息
ON_REGISTERED_MESSAGE(WM_USERMSG,OnUserMsg)//自注册消息
END_MESSAGE_MAP()
LRESULT CMyFrameWnd::OnUserMsg(WPARAM wParam,LPARAM lParam){
AfxMessageBox(_T("自己注册的消息"));
return 0;


}
LRESULT CMyFrameWnd::OnMyMessage(WPARAM wParam,LPARAM lParam){
AfxMessageBox(_T("自己的消息"));
return 0;
}
void CMyFrameWnd::OnEnChange(){
AfxMessageBox(_T("内容有变"));
}
void CMyFrameWnd::OnTest(UINT nid){
    CString str;
str.Format(_T("%d"),nid);
AfxMessageBox(str);
}
void CMyFrameWnd::OnTest1(){
AfxMessageBox(_T("test1被点击"));
::SendMessage(m_hWnd,WM_MYMESSAGE,0,0);
::SendMessage(m_hWnd,WM_USERMSG,0,0);
}
int CMyFrameWnd::OnCreate(LPCREATESTRUCT cs){
//AfxMessageBox(_T("wm_create"));
//创建三个按钮控件
CreateWindowEx(0,_T("BUTTON"),_T("Text1"),WS_CHILD|WS_VISIBLE,50,50,100,100,m_hWnd,(HMENU)1001,AfxGetInstanceHandle(),NULL);
CreateWindowEx(0,_T("BUTTON"),_T("Text2"),WS_CHILD|WS_VISIBLE,250,250,100,100,m_hWnd,(HMENU)1002,AfxGetInstanceHandle(),NULL);
CreateWindowEx(0,_T("BUTTON"),_T("Text3"),WS_CHILD|WS_VISIBLE,450,250,100,100,m_hWnd,(HMENU)1003,AfxGetInstanceHandle(),NULL);
    //文本编辑框
CreateWindowEx(WS_EX_CLIENTEDGE,_T("EDIT"),_T(""),WS_VISIBLE|WS_CHILD,300,100,50,50,m_hWnd,(HMENU)1004,AfxGetInstanceHandle(),NULL);
return 0;
}
void CMyFrameWnd::OnPaint(){
PAINTSTRUCT ps={0};
HDC hDC=::BeginPaint(m_hWnd,&ps);
::TextOut(hDC,0,0,_T("WM_PAINT"),strlen("WM_PAINT"));
::EndPaint(m_hWnd,&ps);
}
class CMyWinApp: public CWinApp{
public:
   virtual BOOL InitInstance();
};
CMyWinApp theApp;
BOOL CMyWinApp::InitInstance(){
CMyFrameWnd *pFrame=new CMyFrameWnd;
CString str=_T("this is a window");
LPCTSTR lpszWindowName=str;
pFrame->Create(NULL,lpszWindowName);
pFrame->ShowWindow(SW_NORMAL);
pFrame->UpdateWindow();
m_pMainWnd=pFrame;
return TRUE;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值