Q1:APP、CFrame、CDoc、CView 消息捕获的顺序
测试:在资源中添加测试菜单
右键菜单中的 Test 添加消息响应:
依次为APP、CFrame、CDoc、CView都添加一个 OnTest(), 在消息响应函数中弹出一个 MessageBox() ,可以看到,消息最先被CView 拦截,如果注释掉CView的OnTest(), 然后被响应的是 CDoc,然后是 CFrame,最后是 APP。
注意!
APP 和 CDoc 不是从 CWnd 继承,没有MessageBox 这个成员函数。
为什么响应的顺序是这样的?(类之间的父子关系不同)
消息的分类
- 标准消息:包括除 WM_COMMAND 以外,所有 WM_ 开头的消息。从 CWnd 派生处的类都能接收这个消息
- 命令消息:
- 通知消息:
CWnd 能接收所有消息
设置菜单项勾选标记
CWnd::GetMenu();
CMenu* GetMenu() const;
// 两种逐级访问菜单的方式:获得整个菜单指针 》 获得第一个菜单项 》 对第一个菜单项下的第一个子项进行勾选
GetMenu()->GetSubMenu(0)->CheckMenuItem(0, MF_BYPOSITION | MF_CHECKED); // by 位置
GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_NEW, MF_BYCOMMAND | MF_CHECKED); // by ID
// 两种设置 缺省(加粗)菜单的方式 (只能有一项缺省)
GetMenu()->GetSubMenu(0)->SetDefaultItem(1, TRUE); // 通过索引,则 TRUE
GetMenu()->GetSubMenu(0)->SetDefaultItem(ID_FILE_OPEN, FALSE); // 通过索引,则 FALSE
// 注意! 菜单中的分隔符也算一个索引号,在计算索引号的时候不可忽略
在菜单前面加上图标
CMenu::SetMenuItemBitmaps()
CBitMap m_bitMap1, m_bitMap2;
m_bitMap1.LoadBitmap(IDB_BITMAP1);
m_bitMap2.LoadBitmap(IDB_BITMAP2);
// 两种访问方式,MF_BYPOSITION MF_BYCOMMAND
GetMenu()->GetSubMenu(0)->SetMenuItemBitmaps(0, MF_BYPOSITION, &m_bitMap1, &m_bitMap2);
一个重要辅助函数:获得系统信息 GetSystemMetrics()
GetSystemMetrics() // 具体获得什么信息,则需要输入不同的宏,例如:获得菜单勾选框大小
int X = GetSystemMetrics(SM_CXMENUCHECK);
int Y = GetSystemMetrics(SM_CYMENUCHECK);
禁用 / 启用菜单项
// 禁用菜单:两个步骤!CMainFrame 框架类有个成员函数,要手动在在构造函数中设为 FALSE
GetMenu()->GetSubMenu(0)->EnableMenuItem(1, MF_BYPOSITION| MF_DISABLED | MF_GRAYED);
m_bAutoMenuEnable = FALSE;
GetMenu()->GetSubMenu(0)->EnableMenuItem(1, MF_BYPOSITION | MF_ENABLED); // 还原
m_bAutoMenuEnable = TRUE;
// 另一种禁用菜单的方式
// 在资源视图中选中一个子菜单 》 右键添加消息处理函数 》 选择 CMainFrame 类 》 先择 ON_UPDATE_COMMAND_UI 》 添加
// 在生成的消息响应函数中
pCmdUI->Enable(FALSE);
CCmdUI *pCmdUI; 还提供了很多其他操作
// 注意!菜单选线如何与工具栏关联,只需要讲ID号设置一样就行!(但是相关操作必须用 ID 号来进行,而不能用索引号)
删除 / 更换 / 插入 菜单/菜单项
SetMenu(NULL); // 删除菜单
CMenu menu;// 注意此处要定义为成员/全局
menu.LoadMenu(ID_..新菜单ID...);
SetMenu(&menu);
动态创建菜单
// 如果要动态创建菜单,CMenu menu 为局部的,那么,使用完后,要使用
menu.Detach();
添加弹出式菜单(静态/动态)
// 只能添加到 CView
ON_WM_CONTEXTMENU
// 注意消息响应的优先级:子窗口优先响应,如果子窗口没有消息响应函数,则交由父窗口响应
// 所以弹出式菜单的父窗口最好是 CMainFrame, 这样在父窗口才能响应到
Cmenu::AppendMenu()
Cmenu::CreatePopupMenu()
120 min