菜单和工具栏的实现都是通过对其相应类(CMenu和CToolBar)的使用来实现的。(VS2010实际上用的是CMFCMenu类和CMFCToolBar类)
菜单分为两类:窗口菜单和上下文菜单。
自定义菜单的方式有两种:
1. 在原有的菜单上进行增添删除菜单项,以符合自己的要求;
2. 在资源->Menu中插入新的菜单,进行编辑。然后在相应的代码处用新菜单ID替换旧的ID。
a.窗口菜单(单文档):
BOOL CMenuApp::InitInstance()
{
...
// 注册应用程序的文档模板。文档模板
// 将用作文档、框架窗口和视图之间的连接
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,//>>>>>>在这里进行替换,比如IDR_NEWMENU
RUNTIME_CLASS(CMenuDoc),
RUNTIME_CLASS(CMainFrame), // 主 SDI 框架窗口
RUNTIME_CLASS(CMenuView));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
...
}
b.上下文菜单:
//1.首先注释掉以下代码,保证原来的弹出菜单失效
void CMenuView::OnRButtonUp(UINT /* nFlags */, CPoint point)
{
//ClientToScreen(&point);
//OnContextMenu(this, point);
}
//2.添加WM_RBUTTONDOWN的消息映射函数,实现新窗口的加载和弹出
void CMenuView::OnRButtonDown(UINT nFlags, CPoint point)
{
CMenu menu;//菜单(包括主菜单)
CMenu *pSubMenu;//菜单的子菜单,要显示的
menu.LoadMenu(IDR_POPUP_EDIT);//载入编辑好的菜单
pSubMenu=menu.GetSubMenu(0);//获得子菜单的指针
ClientToScreen(&point); //坐标转换
//该函数用于弹出一个菜单
pSubMenu->TrackPopupMenu(TPM_LEFTALIGN,point.x,
point.y,this);
CView::OnRButtonDown(nFlags, point);
}
ps:还可以自绘菜单,在菜单项上加图标等。通过创建一个自绘菜单类来实现。
此外,菜单栏的停靠等属性的设置与工具栏相似。
ps1:菜单项的消息映射函数可以直接在资源编辑时,右键添加。
工具栏的创建是在OnCreate函数中完成的:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWndEx::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_TOOLBAR1))
{
TRACE0("未能创建工具栏\n");
return -1; // 未能创建
}
/*去掉一些不必要的东西
CString strToolBarName;
bNameValid =strToolBarName.LoadString(IDS_TOOLBAR_STANDARD);
ASSERT(bNameValid);
m_wndToolBar.SetWindowText(strToolBarName);
CString strCustomize;
bNameValid = strCustomize.LoadString(IDS_TOOLBAR_CUSTOMIZE);
ASSERT(bNameValid);
m_wndToolBar.EnableCustomizeButton(TRUE, ID_VIEW_CUSTOMIZE, strCustomize);
// 允许用户定义的工具栏操作:
InitUserToolbars(NULL, uiFirstUserToolBarId, uiLastUserToolBarId);
*/
// TODO: 如果您不希望工具栏和菜单栏可停靠,请删除这五行
m_wndMenuBar.EnableDocking(CBRS_ALIGN_ANY);
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);//启用工具栏停靠
EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_wndMenuBar);
DockPane(&m_wndToolBar);//停靠工具栏
...
//注释掉一些其他不必要的代码
return 0;
}
ps:工具栏的消息映射函数通过类向导和其ID进行添加。
状态栏的创建与菜单栏和工具栏的类似,都是在CMainFrame的OnCreate函数中进行。
//创建状态栏
if (!m_wndStatusBar.Create(this))
{
TRACE0("未能创建状态栏\n");
return -1; // 未能创建
}
//设置要显示的变量,indicators是一个存储变量的结构体
m_wndStatusBar.SetIndicators(indicators,sizeof(indicators)/sizeof(UINT));
实战:
1.在资源中的String Table添加一个新的字符串资源:
ID_INDICATOR 101 00:00:00
2.在indicator数组中添加:
static UINT indicators[] =
{
ID_SEPARATOR, // 状态行指示器
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
ID_INDICATOR_TIME, //添加项
};
3.运行程序后可以看到状态栏多了一项00:00:00,要设置显示系统时间,添加一个定时器(用于定时刷新时间)和OnTimer函数,将获得的系统时间赋值给状态栏的第4个元素即可:
CTime curTime=CTime::GetCurrentTiem();
CString strTime=curTime.Format(_T"%H:%M:%S");
m_wndStatusBar.SetPaneText(4,strTime);