菜单
一般菜单的使用步骤:
1.编辑菜单资源,设置菜单属性(包括菜单名和ID);
2.用ClassWizard自动映射菜单消息和成员函数;
3.手工编辑成员函数,加入菜单消息处理代码。
单文档窗口可以设置默认的主菜单,在资源视图中可以进行修改:
类向导中可以很方便点挂上消息处理函数:
值得注意的是更新菜单命令是用于响应菜单命令后对菜单项进行更新的消息(比如勾选、变灰等等)
在视图类中响应菜单命令,做一个简单测试:
......
void CMFC07View::OnPause()
{
// TODO: 在此添加命令处理程序代码
::AfxMessageBox("暂停");
state=1;
}
void CMFC07View::OnStart()
{
// TODO: 在此添加命令处理程序代码
::AfxMessageBox("启动");
state=0;
}
.....
void CMFC07View::OnUpdatePause(CCmdUI *pCmdUI)
{
// TODO: 在此添加命令更新用户界面处理程序代码
pCmdUI->SetCheck(state==1);
}
void CMFC07View::OnUpdateStart(CCmdUI *pCmdUI)
{
// TODO: 在此添加命令更新用户界面处理程序代码
pCmdUI->SetCheck(state==0);
}
其中 state定义在视图类中,标记当前状态,实现菜单显示勾选。
设置快捷键:打开资源视图,设置菜单ID对应的快捷键
这样也可以通过键盘输入来启动菜单命令。
菜单命令的更新也可以利用代码来动态实现:如停止(退出)菜单的更新
void CMFC07View::OnStop()
{
// TODO: 在此添加命令处理程序代码
static bool flag=true; //静态变量
::AfxMessageBox("退出");
CMenu *menu=::AfxGetMainWnd()->GetMenu();
if(menu)
{
if(flag) menu->CheckMenuItem(ID_STOP,MF_BYCOMMAND|MF_CHECKED);
else menu->CheckMenuItem(ID_STOP,MF_BYCOMMAND|MF_UNCHECKED);
}
flag=!flag;
}
右键菜单:类向导中OnContextMenu可以响应右键菜单
当然,弹出右键菜单需要自己来动态加载:
新建一个菜单(当然可以可以使用主菜单)
动态加载菜单代码:
void CMFC07View::OnContextMenu(CWnd* pWnd, CPoint point)
{
// TODO: 在此处添加消息处理程序代码
CMenu menu;
menu.LoadMenu(IDR_TEST);
CMenu* pPopup = menu.GetSubMenu(0);
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,pWnd);
}
如果需要利用快捷键打开右键菜单则需要丢point进行处理(因为按键的时候,鼠标点位置可能不在窗口区域)。另外,默认添加的右键菜单响应函数屏蔽了pWnd 和 point,手动取消即可。
状态栏
状态栏实际上是个窗口,一般分为几个窗格,每个窗格显示不同的信息。AppWizard会为应用程序自动创建一个状态栏,该状态栏包括几个窗格,分别用来显示状态栏提示和CAPS LOCK、NUM LOCK 、SCROLL LOCK键的状态。在MFC中,状态栏的功能由CStatusBar类实现。
ID数组
static UINT indicators[] =
{
ID_SEPARATOR, // status line indicator
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
indicator数组提供了状态栏窗格的分配信息,它的第一项一般为ID_SEPARATOR,该ID对应的窗格用来显示命令提示信息,后三项都是字符串ID,可以在StringTable中找到:
添加状态栏显示信息,以添加动态更新的时钟为例:
首先在主框架类中添加时钟响应消息:(主框架管理状态栏)
然后,在StringTable里添加一个字符串:显示格式为 00:00:00
在主框架类的indicators中添加对应的ID(可能报错,添加resource.h可以解决问题)
OnCreate 函数中启动定时(不能在构造函数里,窗口没有创建)
this->SetTimer(1,100,NULL); //100毫秒刷新定时,可以换成1000
修改定时消息响应函数:
void CMainFrame::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CTime time;
time=CTime::GetCurrentTime();
CString s=time.Format("%H:%M:%S");
m_wndStatusBar.SetPaneText(m_wndStatusBar.CommandToIndex(ID_INDICATOR_CLOCK),s);
CFrameWnd::OnTimer(nIDEvent);
}
获取当前时间,格式化成字符串,然后更新到状态栏。可以在析构函数或者WM_CLOSE消息响应中清除定时:this->KillTimer(1); // 1 是SetTimer 的定时编号,可以设置多个定时
定时消息也可以自定义处理函数,在动画、刷新等等处理中经常用到。