消息映射的最基类就是CCmdTarget,只要派生于这个类的都具有消息映射功能。
WM_COMMAND是按照视图类,文档类,框架类,应用程序类的顺序来查找消息的。消息网。
今天主要研究从框架类到应用程序类这两个类的支脉是怎么走的。
MFC菜单
MFC菜单相关类
CMenu类 - 封装HMENU句柄及相关的菜单的Win32 API函数
菜单的用法
在项目中,添加菜单资源
在窗口创建时,添加菜单项到窗口
两种方式挂载菜单,现在是第一种,都先添加资源文件,然后添加资源头文件resource.h
int CMyFrameWnd::OnCreate(LPCREATESTRUCT lpCreateStruct){
CMenu menu;
menu.LoadMenu(IDC_MFCBASE);
SetMenu(&menu);
return CFrameWnd::OnCreate(lpCreateStruct);
}
《〈〈〈〈〈〈〈〈〈使用上述方法挂载菜单后出来单击下拉菜单,导致异常发生。现仍不知是什么原因造成的。〉〉〉〉。
//////////////////////////////////////////////////////////
原因是显而易见的,menu是一个局部变量,当函数结束时便销毁 了,于是将其static加上,或者定义为全局变量即可。终于解决了。static CMenu menu;
//////////////////////////////////////////////////////////
使用另一种方式挂载菜单:
pFrame->Create(NULL,lpszWindowName,WS_OVERLAPPEDWINDOW,CFrameWnd::rectDefault,NULL,MAKEINTRESOURCE(IDR_MENU1));
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
菜单项的命令响应
ON_COMMAND
注意
只要是CCmdTarget的子类,都可以添加菜单的消息映射机制.
afx_msg void OnExit();
afx_msg void OnOpen();
};
BEGIN_MESSAGE_MAP(CMyFrameWnd,CFrameWnd)
ON_WM_CREATE()
ON_COMMAND(IDM_EXIT,OnExit)//菜单添加消息映射
ON_COMMAND(IDM_ABOUT,OnOpen)
END_MESSAGE_MAP()
void CMyFrameWnd::OnExit(){
AfxMessageBox(_T("退出"));
}
void CMyFrameWnd::OnOpen(){
AfxMessageBox(_T("打开"));
}
//////////////////////////////////////////////////////////////////////////
以上我们是在框架类中处理WM_COMMAND消息的,我们也可以在应用程序类中添加消息映射处理WM_COMMAND消息。
调用堆栈---OnWndMsg--if(message==WM_COMMAND)
之前步骤和WM_CREATE完全一致。
OnCommand(wParam,lParam()//函数内部指针为pFrame
{
CWnd::OnCommand(wParam,lParam)//函数内部指针为pFrame
{
UINT nId=LOWORD(wparam);//获取到菜单项点击ID
OnCmdMsg(nid,ncode, ,)//函数内部指针为pFrame
{
框架类没有处理该消息
CWinApp *pApp=AfxGetApp();//全局变量theApp地址。
pApp->OnCmdMsg()//函数内部指针为全局变量theApp地址
{
for(pMessageMap=GetMessageMap();pMessageMap!=NULL;pMessageMap=pMessageMap->pBaseMap)
{
lpEntry=AfxfindMessageEntry();
以后步骤和WM_CREATE基本一致。
}
}
}
}
}
//右键菜单
// MFCBase.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "MFCBase.h"
#include "resource.h"
class CMyFrameWnd:public CFrameWnd{
DECLARE_MESSAGE_MAP()
public:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnExit();
afx_msg void OnOpen();
afx_msg void OnContextMenu(CWnd*, CPoint);
};
BEGIN_MESSAGE_MAP(CMyFrameWnd,CFrameWnd)
ON_WM_CREATE()
ON_COMMAND(IDM_EXIT,OnExit)//菜单添加消息映射
ON_COMMAND(IDM_ABOUT,OnOpen)
ON_WM_CONTEXTMENU()//右键菜单
END_MESSAGE_MAP()
//创建右键菜单
void CMyFrameWnd::OnContextMenu(CWnd*pWnd, CPoint pt){
CMenu menu;
menu.LoadMenu(IDR_MENU1);
CMenu *popmenu=menu.GetSubMenu(0);
popmenu->TrackPopupMenu(TPM_LEFTALIGN,pt.x,pt.y,pWnd);
}
void CMyFrameWnd::OnExit(){
AfxMessageBox(_T("退出"));
}
void CMyFrameWnd::OnOpen(){
AfxMessageBox(_T("打开"));
}
int CMyFrameWnd::OnCreate(LPCREATESTRUCT lpCreateStruct){
//static CMenu menu;
//menu.LoadMenu(IDC_MFCBASE);
//SetMenu(&menu);
return CFrameWnd::OnCreate(lpCreateStruct);
}
class CMyWinApp: public CWinApp{
DECLARE_MESSAGE_MAP()
public:
virtual BOOL InitInstance();
};
BEGIN_MESSAGE_MAP(CMyWinApp,CWinApp)
END_MESSAGE_MAP()
CMyWinApp theApp;
BOOL CMyWinApp::InitInstance(){
CMyFrameWnd *pFrame=new CMyFrameWnd;
CString str=_T("this is a window");
LPCTSTR lpszWindowName=str;
pFrame->Create(NULL,lpszWindowName,WS_OVERLAPPEDWINDOW,CFrameWnd::rectDefault,NULL,MAKEINTRESOURCE(IDC_MFCBASE));
pFrame->ShowWindow(SW_NORMAL);
pFrame->UpdateWindow();
m_pMainWnd=pFrame;
return TRUE;
}
WM_COMMAND是按照视图类,文档类,框架类,应用程序类的顺序来查找消息的。消息网。
今天主要研究从框架类到应用程序类这两个类的支脉是怎么走的。
MFC菜单
MFC菜单相关类
CMenu类 - 封装HMENU句柄及相关的菜单的Win32 API函数
菜单的用法
在项目中,添加菜单资源
在窗口创建时,添加菜单项到窗口
两种方式挂载菜单,现在是第一种,都先添加资源文件,然后添加资源头文件resource.h
int CMyFrameWnd::OnCreate(LPCREATESTRUCT lpCreateStruct){
CMenu menu;
menu.LoadMenu(IDC_MFCBASE);
SetMenu(&menu);
return CFrameWnd::OnCreate(lpCreateStruct);
}
《〈〈〈〈〈〈〈〈〈使用上述方法挂载菜单后出来单击下拉菜单,导致异常发生。现仍不知是什么原因造成的。〉〉〉〉。
//////////////////////////////////////////////////////////
原因是显而易见的,menu是一个局部变量,当函数结束时便销毁 了,于是将其static加上,或者定义为全局变量即可。终于解决了。static CMenu menu;
//////////////////////////////////////////////////////////
使用另一种方式挂载菜单:
pFrame->Create(NULL,lpszWindowName,WS_OVERLAPPEDWINDOW,CFrameWnd::rectDefault,NULL,MAKEINTRESOURCE(IDR_MENU1));
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
菜单项的命令响应
ON_COMMAND
注意
只要是CCmdTarget的子类,都可以添加菜单的消息映射机制.
afx_msg void OnExit();
afx_msg void OnOpen();
};
BEGIN_MESSAGE_MAP(CMyFrameWnd,CFrameWnd)
ON_WM_CREATE()
ON_COMMAND(IDM_EXIT,OnExit)//菜单添加消息映射
ON_COMMAND(IDM_ABOUT,OnOpen)
END_MESSAGE_MAP()
void CMyFrameWnd::OnExit(){
AfxMessageBox(_T("退出"));
}
void CMyFrameWnd::OnOpen(){
AfxMessageBox(_T("打开"));
}
//////////////////////////////////////////////////////////////////////////
以上我们是在框架类中处理WM_COMMAND消息的,我们也可以在应用程序类中添加消息映射处理WM_COMMAND消息。
调用堆栈---OnWndMsg--if(message==WM_COMMAND)
之前步骤和WM_CREATE完全一致。
OnCommand(wParam,lParam()//函数内部指针为pFrame
{
CWnd::OnCommand(wParam,lParam)//函数内部指针为pFrame
{
UINT nId=LOWORD(wparam);//获取到菜单项点击ID
OnCmdMsg(nid,ncode, ,)//函数内部指针为pFrame
{
框架类没有处理该消息
CWinApp *pApp=AfxGetApp();//全局变量theApp地址。
pApp->OnCmdMsg()//函数内部指针为全局变量theApp地址
{
for(pMessageMap=GetMessageMap();pMessageMap!=NULL;pMessageMap=pMessageMap->pBaseMap)
{
lpEntry=AfxfindMessageEntry();
以后步骤和WM_CREATE基本一致。
}
}
}
}
}
//右键菜单
// MFCBase.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "MFCBase.h"
#include "resource.h"
class CMyFrameWnd:public CFrameWnd{
DECLARE_MESSAGE_MAP()
public:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnExit();
afx_msg void OnOpen();
afx_msg void OnContextMenu(CWnd*, CPoint);
};
BEGIN_MESSAGE_MAP(CMyFrameWnd,CFrameWnd)
ON_WM_CREATE()
ON_COMMAND(IDM_EXIT,OnExit)//菜单添加消息映射
ON_COMMAND(IDM_ABOUT,OnOpen)
ON_WM_CONTEXTMENU()//右键菜单
END_MESSAGE_MAP()
//创建右键菜单
void CMyFrameWnd::OnContextMenu(CWnd*pWnd, CPoint pt){
CMenu menu;
menu.LoadMenu(IDR_MENU1);
CMenu *popmenu=menu.GetSubMenu(0);
popmenu->TrackPopupMenu(TPM_LEFTALIGN,pt.x,pt.y,pWnd);
}
void CMyFrameWnd::OnExit(){
AfxMessageBox(_T("退出"));
}
void CMyFrameWnd::OnOpen(){
AfxMessageBox(_T("打开"));
}
int CMyFrameWnd::OnCreate(LPCREATESTRUCT lpCreateStruct){
//static CMenu menu;
//menu.LoadMenu(IDC_MFCBASE);
//SetMenu(&menu);
return CFrameWnd::OnCreate(lpCreateStruct);
}
class CMyWinApp: public CWinApp{
DECLARE_MESSAGE_MAP()
public:
virtual BOOL InitInstance();
};
BEGIN_MESSAGE_MAP(CMyWinApp,CWinApp)
END_MESSAGE_MAP()
CMyWinApp theApp;
BOOL CMyWinApp::InitInstance(){
CMyFrameWnd *pFrame=new CMyFrameWnd;
CString str=_T("this is a window");
LPCTSTR lpszWindowName=str;
pFrame->Create(NULL,lpszWindowName,WS_OVERLAPPEDWINDOW,CFrameWnd::rectDefault,NULL,MAKEINTRESOURCE(IDC_MFCBASE));
pFrame->ShowWindow(SW_NORMAL);
pFrame->UpdateWindow();
m_pMainWnd=pFrame;
return TRUE;
}