点击b
会切换a
可用状态:
添加 Menu 选项
a
对应 ID ID_DEMO_A
,b
对应 ID ID_DEMO_B
。
弹式菜单无法编辑 ID。
▲ 右键添加事件处理程序
▲ 路由传递路径
frame 给到 view 如果 view 处理好了,就返回给 frame;如果没处理的话, view 会给这个路由消息给 doc,如果doc没有处理,再返回给 view, view 在给 frame,frame 给 app(应用程序)。消息处理后就不会传递下去了。
消息分为三类
1)菜单的命令响应函数
a)弹式菜单,ID不可编辑,按下去,弹出一个菜单项
b)非弹式菜单,ID可编辑
c)菜单响应命令消息的路由(顺序)
d)消息类型
非标准消息 WM_COMMAND,命令消息、通告消息,CCmdTarget、CWnd子类子类能接收到非标准消息 // 只有菜单有
标准消息 WM_XXXX CWnd子类才能接收到标准消息
命令消息WM_COMMAND:菜单处理函数选中
标准消息: 属性 -> 消息
通告消息:点击按钮,处理函数 // 点击按钮等控件的时候有
CWnd 可以接受任何消息
CCmdTarget 不能接受标准消息
头文件
// 生成的消息映射函数
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnTestDemo();
afx_msg void OnUpdateFileOpen(CCmdUI* pCmdUI);
private:
bool m_isEnable;
public:
afx_msg void OnFileSave();
afx_msg void OnDemoB();
afx_msg void OnUpdateDemoA(CCmdUI* pCmdUI);
在 Frame 静态处理
▲ IDR_MENU1 Menu IDR_MAINFRAME这个是默认的
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("未能创建工具栏\n");
return -1; // 未能创建
}
if (!m_wndStatusBar.Create(this))
{
TRACE0("未能创建状态栏\n");
return -1; // 未能创建
}
m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));
// TODO: 如果不需要可停靠工具栏,则删除这三行
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
// 获取主菜单
CMenu* menu = GetMenu();
CMenu* fileMenu = menu->GetSubMenu(0); // 第 0 个,也可以通过 ID
// 标志 "新建"
fileMenu->CheckMenuItem(0, MF_BYPOSITION | MF_CHECKED); // 前面会有个 勾
// 打开
fileMenu->CheckMenuItem(ID_FILE_OPEN, MF_BYCOMMAND | MF_CHECKED); // 通过 ID的方式
// 设置默认项, 加粗,一个菜单只能一个默认菜单
// FASLE: 用ID
// TRUE: 用位置
fileMenu->SetDefaultItem(ID_FILE_SAVE, FALSE); // 这个效果是,加粗变黑。
fileMenu->SetDefaultItem(3, TRUE);
// 变灰
//需要把 CFrameWnd::m_bAutoMenuEnable 设置 false 才能真正变灰,可在构造函数置 false
fileMenu->EnableMenuItem(5, MF_BYPOSITION | MF_DISABLED); // 这个效果禁用变灰 分割线也算一个索引位置
SetMenu(NULL); // 移除菜单
CMenu menu2;
// 加载菜单 菜单的加载
menu2.LoadMenuW(IDR_MENU1);
SetMenu(&menu2);
menu2.Detach(); // 分离,不会局部变量回收的效果
return 0;
}
菜单更新机制
// b 的处理函数
void CMainFrame::OnDemoB()
{
m_isEnable = !m_isEnable;
}
// a 的更新 这个会自动更新
void CMainFrame::OnUpdateDemoA(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_isEnable);
}
参考:
笔记定位:
- MFC 菜单响应路由 // 这个记录的可能还详细一点