1. 消息的分类
    1. 标准消息:除了WM_COMMAND消息外,其他以WM_开头的消息都是标准消息。从CWnd派生的类都可以接收这类消息。
    2. 命令消息:来自菜单、加速键和工具栏按钮的消息。这类消息都以WM_COMMAND消息呈现。在MFC中通过菜单项的标识(ID)标识不同的消息;在SDK中通过消息的wParam来识别不同的消息。从CCmdTarget类派生的类都能接收这类消息。
    3. 通告消息:由控件产生的消息,例如,按钮的单击和列表框选择的改变。为的是向父窗口通知某个事件的发生。也是以WM_COMMAND消息呈现的。从CCmdTarget类派生的类都可以接收到该类消息。
  2. 标记菜单、缺省菜单的实现原理、图形菜单的实现。

     

    1 GetMenu()->GetSubMenu(0)->CheckMenuItem(0, MF_BYPOSITION | MF_CHECKED);
    2 GetMenu()->GetSubMenu(0)->CheckMenuRadioItem(0, 2, 1, MF_BYPOSITION);
    3 GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_OPEN, MF_BYCOMMAND | MF_CHECKED);
    4
    5 GetMenu()->GetSubMenu(1)->SetDefaultItem(0, true);
    6 GetMenu()->GetSubMenu(0)->SetDefaultItem(ID_FILE_OPEN);
    7
    8 /*CString str;
    9 str.Format("x=%d, y=%d", ::GetSystemMetrics(SM_CXMENUCHECK), ::GetSystemMetrics(SM_CXMENUCHECK));
    10 MessageBox(str);*/
    11 m_bmap.LoadBitmap(IDB_BITMAP1);
    12 GetMenu()->GetSubMenu(0)->SetMenuItemBitmaps(3, MF_BYPOSITION, &m_bmap, &m_bmap);
    13 //GetMenu()->DeleteMenu(0, MF_BYPOSITION);
    14   GetMenu()->GetSubMenu(0)->EnableMenuItem(1,MF_BYPOSITION | MF_ENABLED | MF_GRAYED);
    15
    16 SetMenu(NULL);
    17 CMenu menu;
    18 menu.LoadMenu(IDR_MAINFRAME);
    19 SetMenu(&menu);
    20 menu.Detach();

      GetSystemMetrics() 函数用来返回系统相关的各种属性值,这里用来返回标记菜单中图标的最小尺寸。menu.Detach();这个函数可以将局部变量与资源分开,使用该函数后这个资源可以在整个窗口销毁时一块销毁。SetMenu(NULL);可以取消菜单栏。

    • 那个CN_UPDATE_COMMAND_UI消息实在是看不懂有啥用,先把它放到一边吧!
    • 在VC6.0中点击工程->添加到工程->最后一个 然后选择popMenu就可以实现一个右键点击出来的菜单了。当然我们也可以自己写出来一个,代码在下面:
    1 void CMenuView::OnRButtonDown(UINT nFlags, CPoint point)
    2 {
    3 // TODO: Add your message handler code here and/or call default
    4   CMenu menu;
    5 menu.LoadMenu(IDR_MENU1);
    6 CMenu *popUP = menu.GetSubMenu(0);
    7 ClientToScreen(&point);
    8 popUP->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,
    9 this->GetParent());
    10 CView::OnRButtonDown(nFlags, point);
    11 }

     

    值得注意的是ClientToScreen(&point);函数,这个函数是将用户区的一个点坐标转换成整个屏幕范围的坐标值。TrackPopupMenu()函数的第四个参数的作用是指定弹出菜单的拥有者,但是不管谁是拥有者,都是有最底部的继承者来首先响应。

    • 动态创建菜单

    1 CMenu menu;
    2 menu.CreatePopupMenu();
    3 //GetMenu()->AppendMenu(MF_POPUP, (UINT)menu.m_hMenu, "wocao");
    4   GetMenu()->InsertMenu(2, MF_POPUP | MF_BYPOSITION, (UINT)menu.m_hMenu, "wocao");
    5 menu.AppendMenu(MF_STRING, 110, "wori");
    6 menu.AppendMenu(MF_STRING, 111, "wocei");
    7 menu.AppendMenu(MF_STRING, 112, "wokao");
    8 GetMenu()->GetSubMenu(0)->InsertMenu(0,
    9 MF_BYPOSITION | MF_STRING,115,"世界杯");
    10 menu.Detach();

     

    可以手动为这些动态添加的菜单添加响应函数,但是个人觉得觉得这个好像没有什么很大的用处。即使一定要添加这个应该也不是很困难,可以仿照自动产生的响应函数编码。

     

    • 实现一个简单的通讯录小程序。

    1 void CMenuView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
    2 {
    3 // TODO: Add your message handler code here and/or call default
    4   CClientDC dc(this);
    5 if(0x0d == nChar){
    6 if(0 == ++this->m_nIndex){
    7 m_menu.CreatePopupMenu();
    8 GetParent()->GetMenu()->AppendMenu(MF_POPUP,
    9 (UINT)m_menu.m_hMenu, "PhoneBook");
    10 GetParent()->DrawMenuBar();
    11 }
    12 m_menu.AppendMenu(MF_STRING, 201+m_nIndex, m_strLine.Left(m_strLine.Find(' ')));
    13 m_strArray.Add(m_strLine);
    14 m_strLine.Empty();
    15 Invalidate();
    16 }else{
    17 this->m_strLine += nChar;
    18 dc.TextOut(0, 0, m_strLine);
    19 }
    20 CView::OnChar(nChar, nRepCnt, nFlags);
    21 }

     

    1 BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam)
    2 {
    3 // TODO: Add your specialized code here and/or call the base class
    4   int menuCmdID = LOWORD(wParam);
    5
    6 CMenuView *pView = (CMenuView*)this->GetActiveView();
    7 if(menuCmdID >= 201 && menuCmdID < 201+pView->m_strArray.GetSize()){
    8 CClientDC dc(pView);
    9 dc.TextOut(0, 0, pView->m_strArray.GetAt(menuCmdID-201));
    10 }
    11 return CFrameWnd::OnCommand(wParam, lParam);
    12 }
    13  

     

    菜单栏动态创建后一定要用GetParent()->DrawMenuBar()来显示它;Invalidate();这个函数用来使整个用户区域变得无效,默认参数是TRUE意思是使背景清空,反之则保留背景。

     

    OnCommand(WPARAM wParam, LPARAM lParam)函数的参数wParam值得注意,它的低字节序用来表示命令消息的ID,高字节序用来表示通告消息的ID。可以用LOWORD(wParam)获得它的低字节序,用HIWORD(wParam)获得它的高字节序。

    使用CMainFrame实现虚函数OnCommand()来拦截所添加的菜单的响应消息。这里我所不理解的是你动态添加几个菜单岂不是要手动添加多少个响应函数,显然这是不现实的。


    PS:这几天真点背,今天我的MSDN又不能用了,整了好久也没整好,到最后只能重装一个MSDN2008. 最后问题终于是解决了。现在我才发现看起来很简单的东西,真要是动手去做的话,还真是不一定就顺利,不管怎么样吧,这一天总算是没白过,O(∩_∩)O哈哈~    

      相关文章:

      • 2021-10-16
      • 2022-12-23
      • 2021-12-14
      • 2022-12-23
      • 2021-11-28
      • 2022-12-23
      • 2022-12-23
      猜你喜欢
      • 2022-12-23
      • 2022-01-02
      • 2022-02-08
      • 2021-04-19
      • 2021-12-27
      • 2021-12-06
      • 2021-05-29
      相关资源
      相似解决方案