MFC之在对话框创建菜单、工具栏、状态栏

原创 2015年06月03日 19:11:22

这篇博客主要解决3个问题:

1、如何在对话框资源上创建菜单,用菜单项控制工具栏和状态栏的显示与隐藏;

2、如何在对话框资源上创建工具栏,并实现工具栏上按钮的响应;

3、如何在对话框资源上创建状态栏,在状态栏分别获取系统时间、鼠标位置、进度条。

希望对读者提供参考价值,也方便自己以后查阅。


首先用MFC向导创建对话框资源class CAddSourceDlg,然后在对话框类中声明需要创建的资源:

  1. private:  
  2.     CMenu m_menu;                //菜单  
  3.     CToolBar m_toolbar;          //工具栏  
  4.     CStatusBar m_statusbar;      //状态栏  
  5.     CProgressCtrl m_progress;    //进度条  
private:
	CMenu m_menu;                //菜单
	CToolBar m_toolbar;          //工具栏
	CStatusBar m_statusbar;      //状态栏
	CProgressCtrl m_progress;    //进度条

在资源窗口编辑菜单资源,如下:


接下来在成员函数OnInitDialog中将菜单资源添加到对话框。对菜单项的索引有两种方式,一种是通过位置索引,另一种是通过资源ID索引,

第一个参数的值取决于第二个参数,这在上一篇博文中有提到。

  1. //创建菜单  
  2. m_menu.LoadMenu(IDR_MENU1);  
  3. SetMenu(&m_menu);  
  4. //设置标记菜单  
  5. GetMenu()->GetSubMenu(0)->CheckMenuItem(2, MF_CHECKED|MF_BYPOSITION);  
  6. GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_DISP_STATUSBAR, MF_CHECKED|MF_BYCOMMAND);  
    //创建菜单
    m_menu.LoadMenu(IDR_MENU1);
    SetMenu(&m_menu);
    //设置标记菜单
    GetMenu()->GetSubMenu(0)->CheckMenuItem(2, MF_CHECKED|MF_BYPOSITION);
    GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_DISP_STATUSBAR, MF_CHECKED|MF_BYCOMMAND);
菜单创建好了,添加前两个菜单项的响应函数如下:
  1. void CAddSourceDlg::OnPrintT()   
  2. {  
  3.     // TODO: Add your command handler code here  
  4.     MessageBox("print T");  
  5. }  
  6.   
  7. void CAddSourceDlg::OnPrintI()   
  8. {  
  9.     // TODO: Add your command handler code here  
  10.     MessageBox("print I");  
  11. }  
void CAddSourceDlg::OnPrintT() 
{
	// TODO: Add your command handler code here
	MessageBox("print T");
}

void CAddSourceDlg::OnPrintI() 
{
	// TODO: Add your command handler code here
	MessageBox("print I");
}

然后在资源窗口编辑工具栏资源。由于工具栏相当于菜单的快捷方式,所以工具栏的按钮ID必须和关联菜

单项的ID一致,共用同一个响应函数。这里讲将工具栏按钮T和按钮I的ID分别设置成菜单项“打印“T””和打印“I”的ID。


然后在成员函数OnInitDialog中将工具栏资源添加到对话框。

  1.       //创建工具栏  
  2. m_toolbar.CreateEx(this);                     //创建空白工具栏  
  3. m_toolbar.LoadToolBar(IDR_TOOLBAR1);          //加载工具栏资源  
  4. CRect rect;   
  5. GetClientRect(&rect);                         //计算客户区大小  
  6. m_toolbar.MoveWindow(0,0,rect.Width(), 25);   //必须设置工具栏显示位置  
       //创建工具栏
	m_toolbar.CreateEx(this);                     //创建空白工具栏
	m_toolbar.LoadToolBar(IDR_TOOLBAR1);          //加载工具栏资源
	CRect rect; 
	GetClientRect(&rect);                         //计算客户区大小
	m_toolbar.MoveWindow(0,0,rect.Width(), 25);   //必须设置工具栏显示位置

运行程序,发现点击工具栏按钮和点击对应菜单项都会调用相同的响应函数,证明创建的工具栏没有问题。

由于在创建状态栏时需要设置各元素的ID,所以现在头文件resource.h中定义好然后在成员函数OnInitDialog中将状态栏资源添加到对话框。其中状态栏第一个元素用来显示系统时间,第二个元素用来指示鼠标位置,第三个元素用来表示进度条。

  1. //创建状态栏  
  2. //创建定时器,由于重载了基类消息响应函数,因此第三个参数可以为NULL  
  3. SetTimer(ID_TIMER, 1000, NULL);  
  4. static UINT indicators[] =    //指定状态栏上三个元素的ID  
  5. {  
  6.     IDS_TIME,  
  7.     IDS_PROGRESS,  
  8.     IDS_MOUSE  
  9. };  
  10.   
  11.        m_statusbar.Create(this);           //创建空白状态栏  
  12. //设置状态栏上元素的ID及元素数量  
  13.        m_statusbar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));  
  14. //设置状态栏3个元素的宽度  
  15.        m_statusbar.SetPaneInfo(0, IDS_TIME, SBPS_NORMAL, rect.Width()/3);  
  16.        m_statusbar.SetPaneInfo(1, IDS_MOUSE, SBPS_NORMAL, 80);  
  17. m_statusbar.SetPaneInfo(2, IDS_PROGRESS, SBPS_STRETCH, 100);  
  18. //必须重新设置和调整状态栏大小,否则无法显示  
  19. RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0);  
	//创建状态栏
	//创建定时器,由于重载了基类消息响应函数,因此第三个参数可以为NULL
	SetTimer(ID_TIMER, 1000, NULL);
	static UINT indicators[] =    //指定状态栏上三个元素的ID
	{
		IDS_TIME,
		IDS_PROGRESS,
		IDS_MOUSE
	};

        m_statusbar.Create(this);           //创建空白状态栏
	//设置状态栏上元素的ID及元素数量
        m_statusbar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));
	//设置状态栏3个元素的宽度
        m_statusbar.SetPaneInfo(0, IDS_TIME, SBPS_NORMAL, rect.Width()/3);
        m_statusbar.SetPaneInfo(1, IDS_MOUSE, SBPS_NORMAL, 80);
	m_statusbar.SetPaneInfo(2, IDS_PROGRESS, SBPS_STRETCH, 100);
	//必须重新设置和调整状态栏大小,否则无法显示
	RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0);

因为显示系统时间要不断刷新,所一上面创建了一个时间间隔为1秒触发事件的定时器,响应函数为基类的虚函数。这里可以重写虚函数,定义我们自己的虚函数。每隔1秒钟,重新获取系统时钟,并显示在对应状态栏上。

  1. void CAddSourceDlg::OnTimer(UINT nIDEvent)   
  2. {  
  3.     // TODO: Add your message handler code here and/or call default  
  4.     CString strTime;  
  5.     CTime time = CTime::GetCurrentTime();  
  6.     strTime.Format("%d:%d:%d", time.GetHour(),time.GetMinute(),time.GetSecond());  
  7.     //确定字符串长度  
  8. //  CClientDC dc(this);  
  9. //  CSize sz = dc.GetTextExtent(strTime);  
  10. //  m_statusbar.SetPaneInfo(0, IDS_TIME, SBPS_NORMAL, sz.cx);  
  11.     m_statusbar.SetPaneText(0, strTime);  
  12.       
  13.     //每过1s,进度条自动增长  
  14.     //m_progress.StepIt();  
  15.     CDialog::OnTimer(nIDEvent);  
  16. }  
void CAddSourceDlg::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	CString strTime;
	CTime time = CTime::GetCurrentTime();
	strTime.Format("%d:%d:%d", time.GetHour(),time.GetMinute(),time.GetSecond());
	//确定字符串长度
// 	CClientDC dc(this);
// 	CSize sz = dc.GetTextExtent(strTime);
// 	m_statusbar.SetPaneInfo(0, IDS_TIME, SBPS_NORMAL, sz.cx);
	m_statusbar.SetPaneText(0, strTime);
    
	//每过1s,进度条自动增长
	//m_progress.StepIt();
	CDialog::OnTimer(nIDEvent);
}
因为要在状态栏上显示鼠标位置,这里在对话框类中定义一个鼠标移动的消息响应函数
  1. void CAddSourceDlg::OnMouseMove(UINT nFlags, CPoint point)   
  2. {  
  3.     // TODO: Add your message handler code here and/or call default  
  4.     CString strPoint;  
  5.     strPoint.Format("%d,%d", point.x,point.y);  
  6.     m_statusbar.SetPaneText(1, strPoint);  
  7.     CDialog::OnMouseMove(nFlags, point);  
  8. }  
void CAddSourceDlg::OnMouseMove(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	CString strPoint;
	strPoint.Format("%d,%d", point.x,point.y);
	m_statusbar.SetPaneText(1, strPoint);
	CDialog::OnMouseMove(nFlags, point);
}
然后成员函数OnInitDialog中创建进度条资源
  1. //创建进度条  
  2. CRect rectPro;  
  3. m_statusbar.GetItemRect(2, &rectPro);   //获取状态栏元素2的区间大小  
  4. //注意此处进度条的父窗口设置为状态栏  
  5. m_progress.Create(WS_CHILD|WS_VISIBLE, rectPro, &m_statusbar, ID_PROGRESS);  
  6. //设置初始位置  
  7. m_progress.SetPos(50);  
  8. //设置步长  
  9. m_progress.SetStep(5);  
	//创建进度条
	CRect rectPro;
	m_statusbar.GetItemRect(2, &rectPro);   //获取状态栏元素2的区间大小
	//注意此处进度条的父窗口设置为状态栏
	m_progress.Create(WS_CHILD|WS_VISIBLE, rectPro, &m_statusbar, ID_PROGRESS);
	//设置初始位置
	m_progress.SetPos(50);
	//设置步长
	m_progress.SetStep(5);
也可以在定时响应函数中递增进度。

最后还要实现菜单项控制工具栏和状态栏的显示、隐藏,添加其余两个菜单项的消息响应函数如下:

  1. void CAddSourceDlg::OnDispToolbar()   
  2. {  
  3.     // TODO: Add your command handler code here  
  4.     if (m_toolbar.IsVisible())  
  5.     {   //如果工具栏处于可见状态,则隐藏,并将菜单的标记撤除  
  6.         m_toolbar.ShowWindow(SW_HIDE);  
  7.         GetMenu()->GetSubMenu(0)->CheckMenuItem(2, MF_UNCHECKED|MF_BYPOSITION);  
  8.     }  
  9.     else  
  10.     {  
  11.         //如果工具栏处于不可见状态,则消失,并添加菜单标记  
  12.         m_toolbar.ShowWindow(SW_SHOW);  
  13.         GetMenu()->GetSubMenu(0)->CheckMenuItem(2, MF_CHECKED|MF_BYPOSITION);  
  14.     }  
  15. }  
  16.   
  17. void CAddSourceDlg::OnDispStatusbar()   
  18. {  
  19.     // TODO: Add your command handler code here  
  20.     if (m_statusbar.IsVisible())  
  21.     {  
  22.         m_statusbar.ShowWindow(SW_HIDE);  
  23.         GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_DISP_STATUSBAR, MF_UNCHECKED|MF_BYCOMMAND);  
  24.     }  
  25.     else  
  26.     {  
  27.         m_statusbar.ShowWindow(SW_SHOW);  
  28.         GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_DISP_STATUSBAR, MF_CHECKED|MF_BYCOMMAND);  
  29.     }  
  30. }  
void CAddSourceDlg::OnDispToolbar() 
{
	// TODO: Add your command handler code here
	if (m_toolbar.IsVisible())
	{   //如果工具栏处于可见状态,则隐藏,并将菜单的标记撤除
		m_toolbar.ShowWindow(SW_HIDE);
		GetMenu()->GetSubMenu(0)->CheckMenuItem(2, MF_UNCHECKED|MF_BYPOSITION);
	}
	else
	{
		//如果工具栏处于不可见状态,则消失,并添加菜单标记
		m_toolbar.ShowWindow(SW_SHOW);
		GetMenu()->GetSubMenu(0)->CheckMenuItem(2, MF_CHECKED|MF_BYPOSITION);
	}
}

void CAddSourceDlg::OnDispStatusbar() 
{
	// TODO: Add your command handler code here
	if (m_statusbar.IsVisible())
	{
		m_statusbar.ShowWindow(SW_HIDE);
		GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_DISP_STATUSBAR, MF_UNCHECKED|MF_BYCOMMAND);
	}
	else
	{
		m_statusbar.ShowWindow(SW_SHOW);
		GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_DISP_STATUSBAR, MF_CHECKED|MF_BYCOMMAND);
	}
}
运行程序,显示正常,虽然简陋,但是方法还算易懂。













  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值