孙鑫MFC 6.菜单 (2)

来源:互联网 发布:apache spark logo 编辑:程序博客网 时间:2024/05/05 08:47

一、首先是对动态菜单的创建,删除,命令响应等操作方法:

菜单的创建是MainFrame类的OnCreate函数中进行的。

 

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("Failed to create toolbar/n");
  return -1;      // fail to create
 }

 if (!m_wndStatusBar.Create(this) ||
  !m_wndStatusBar.SetIndicators(indicators,
    sizeof(indicators)/sizeof(UINT)))
 {
  TRACE0("Failed to create status bar/n");
  return -1;      // fail to create
 }

 // TODO: Delete these three lines if you don't want the toolbar to
 //  be dockable
 m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
 EnableDocking(CBRS_ALIGN_ANY);
 DockControlBar(&m_wndToolBar);


//  //1.动态添加菜单
//  CMenu menu;
//  menu.CreateMenu();
//  //GetMenu()->AppendMenu(MF_POPUP,(UINT)menu.m_hMenu, "guopeng");
//  GetMenu()->InsertMenu(2, MF_POPUP|MF_BYPOSITION, (UINT)menu.m_hMenu, "测试");
// // menu.AppendMenu(MF_STRING,111, "问候");
//  menu.AppendMenu(MF_STRING, IDM_HELLO,"问候"); // 在已经在Resources.h中定义了资源ID情况下使用
//  menu.AppendMenu(MF_STRING,222, "致谢");
//  menu.InsertMenu(1, MF_STRING | MF_BYPOSITION, 333, "插入项1");
//  menu.Detach(); //因为创建的menu是局部变量
//  // 以下方式可用于对menu或其他的子菜单添加菜单项
//  GetMenu()->GetSubMenu(2)->AppendMenu(MF_STRING, 444, "再见");
//  GetMenu()->GetSubMenu(2)->InsertMenu(3, MF_BYPOSITION | MF_STRING, 555, "插入项2");

 //2.删除菜单
// GetMenu()->DeleteMenu(3, MF_BYPOSITION); // 删除子菜单"查看"
// GetMenu()->GetSubMenu(3)->DeleteMenu(0,MF_BYPOSITION); //删除菜单项就“查看”的"工具栏"

//3.

 //为动态添加的菜单添加响应命令,因为不是静态的,在resources的menu视图中看不到菜单项
 //也就无法用classWizard创建响应命令函数。必须手工添加
 //(1).创建资源ID.文件FileView中找到REsource.h,在其中定义自己的资源ID。eg. #define IDM_HELLO 111
 //(2).头文件中添加命令响应函数的原型.在DECLARE_MESSAGE_MAP()前添加afx_msg void OnHello();
 //(3).源文件中添加命令映射函数.在END_MESSAGE_MAP()前面添加ON_COMMAND(IDM_HELLO,OnHello) 注意没有分号
 //(4).源文件中添加处理函数OnHello(). eg: void CMainFrame::OnHello(){MessageBox("Hello world!");}
 
 return 0;
}

二、简单电话本功能实现。

描述:1、当在窗口中输入一个姓名和电话号码(二者以空格分开)后,回车。在菜单栏中增加一个弹出菜单(只在第一次回车时),并且菜单项中添加姓名,然后再输入姓名电话,可依次加入。

2、当点击电话本菜单中的姓名时,菜单中可显示该姓名和电话。(这种方式能进行的消息响应个数有限)。

 

输入字符是在view中显示:

CMenu2View::CMenu2View()
{
 // TODO: add construction code here
 m_nIndex = -1;  //手动增加的int变量,记录输入的电话条数
 m_strLine = ""; //用于保存输入的字符串
}

void CMenu2View::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
 // TODO: Add your message handler code here and/or call default
 
 CClientDC dc(this);
 if (0x0d == nChar) //按下回车键
 {
  //第一次回车
  if (0 == ++ m_nIndex)
  {
   m_menu.CreatePopupMenu();
   //因为菜单栏是属于MainFrame类的,所以要想添加菜单栏,必须先获得MainFrame类的指针
   GetParent()->GetMenu()->AppendMenu(MF_POPUP,(UINT)m_menu.m_hMenu,"电话本");
   //在windows创建完菜单后再对菜单栏进行操作之后,一定要调用Frame类的重绘菜单栏函数
   GetParent()->DrawMenuBar();
  }

  int i = m_strLine.Find(' '); //返回' ' 的索引值(base 0)
  CString str = m_strLine.Left(i); // i截取的字符数
  m_menu.AppendMenu(MF_STRING,IDM_PHONE1 + m_nIndex,str); // 添加菜单项
  m_strArray.Add(m_strLine);  //将输入的字符串添加到字符串数组中
  m_strLine.Empty(); // 输入完一次回车后,下次再输入字母时字符串应该已经为空。
  Invalidate(); // 将客户区的内容擦除
 }
 else //按下的不是回车键
 {
  m_strLine += nChar;
  dc.TextOut(0, 0, m_strLine);
 }

 CView::OnChar(nChar, nRepCnt, nFlags);
}

void CMenu2View::OnPhone1()
{
 // TODO: Add your command handler code here
 //先随便建一个弹出子菜单并为两个子菜单在view类中添加响应,修改上面增加菜单项的ID号,
 //然后删除子菜单,注意要将源文件的映射函数移出到自己增加函数映射的位置,放到END_MESSAGE_MAP()之前
 CClientDC dc(this);
 dc.TextOut(0, 0, m_strArray.GetAt(0));
}

void CMenu2View::OnPhone2()
{
 // TODO: Add your command handler code here
 CClientDC dc(this);
 dc.TextOut(0, 0, m_strArray.GetAt(1));
}

 

三。MainFrame类截获本应传给view类处理的OnCommand命令

 

//手动增加的OnCommand虚函数来截获本来要先传给view类出理的消息
BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam)
{
 // TODO: Add your specialized code here and/or call the base class
 int MenuCmdId = LOWORD(wParam); //取wParam的低字节区
 CMenu2View * pView = (CMenu2View *)GetActiveView(); //CMenu2View类要包含在mainFrame类的源文件中
 if (MenuCmdId >= IDM_PHONE1 && MenuCmdId < IDM_PHONE1 + pView->m_strArray.GetSize())
 {
//  MessageBox("testing!");
  CClientDC dc(pView);
  dc.TextOut(0,0,pView->m_strArray.GetAt(MenuCmdId - IDM_PHONE1));
 }
 return CFrameWnd::OnCommand(wParam, lParam);
}