基于对话框灰化菜单栏

问题一:   我没有添加菜单处理事件,菜单却是可以点的,也就是Enabled.  
   
  问题二:我添加了菜单更新事件却不能灰化菜单。很不解,也很着急。  
   
  void   CMyDlg::OnUpdateTranpan(CCmdUI   *pCmdUI)  
  {  
  //   TODO:   在此添加命令更新用户界面处理程序代码  
  if(m_bConnected)   pCmdUI->Enable(true);  
  else   pCmdUI->Enable(false);  
  }  
   
  没有一点变化。

错误的关键是你是在对话框中使用菜单。而对话框和框架类是不同的,对菜单的缺省支持也不同。因此在对话框中如果和在框架类中一样处理菜单,就会出现你现在这种结果。  
  =========================================  
  问题:一般情况下我们用UPDATE_COMMAND_UI来修改菜单的状态(enable/disable,check/uncheck,   change   text),但这个方法在一个基于对话框上的菜单却没有效果。  
  void   CTestDlg::OnUpdateFileExit(CCmdUI*   pCmdUI)    
  {  
          pCmdUI->Enable(FALSE);    
          pCmdUI->SetCheck(TRUE);    
          pCmdUI->SetRadio(TRUE);    
          pCmdUI->SetText("Close");    
  //以上方法在MDI、SDI程序中都能起作用,在对话框中却没有效果,根本没有调用这个函数。  
  }  
   
  原因分析:当显示一个下拉的菜单的时候,在显示菜单前会发送WM_INITMENUPOPUP消息。而 CFrameWnd::OnInitMenuPopup函数会刷新这个菜单项,同时如果有UPDATE_COMMAND_UI响应函数,则调用它。通过它来更新反应每个菜单的外观效果(enabled/disabled,   checked/unchecked).  
  在一个基于对话框的程序中,因为没有OnInitMenuPopup函数,所以不会调用UPDATE_COMMAND_UI响应函数,而是使用了CWnd类的默认处理,   这种处理没有调用UPDATE_COMMAND_UI响应函数。  
   
  解决方法如下:  
  第一步:  
  在对话框类的.cpp文件,添加一个ON_WM_INITMENUPOPUP入口到消息映射里面  
  BEGIN_MESSAGE_MAP(CTestDlg,   CDialog)  
  //}}AFX_MSG_MAP  
  ON_WM_INITMENUPOPUP()  
  END_MESSAGE_MAP()  
  第二步:  
  在对话框类的.h文件添加消息函数声明。  
  //   Generated   message   map   functions  
  //{{AFX_MSG(CDisableDlgMenuDlg)  
  afx_msg   void   OnInitMenuPopup(CMenu   *pPopupMenu,   UINT   nIndex,BOOL   bSysMenu);  
  //}}AFX_MSG  
  DECLARE_MESSAGE_MAP()  
  第三步:  
  在对话框类的.cpp文件添加如下函数代码(大部分代码取自WinFrm.cpp文件的函数CFrameWnd::OnInitMenuPopup):  
  void   C******Dlg::OnInitMenuPopup(CMenu   *pPopupMenu,   UINT   nIndex,BOOL   bSysMenu)  
  {  
          ASSERT(pPopupMenu   !=   NULL);  
          //   Check   the   enabled   state   of   various   menu   items.  
   
          CCmdUI   state;  
          state.m_pMenu   =   pPopupMenu;  
          ASSERT(state.m_pOther   ==   NULL);  
          ASSERT(state.m_pParentMenu   ==   NULL);  
   
          //   Determine   if   menu   is   popup   in   top-level   menu   and   set   m_pOther   to  
          //   it   if   so   (m_pParentMenu   ==   NULL   indicates   that   it   is   secondary   popup).  
          HMENU   hParentMenu;  
          if   (AfxGetThreadState()->m_hTrackingMenu   ==   pPopupMenu->m_hMenu)  
                  state.m_pParentMenu   =   pPopupMenu;         //   Parent   ==   child   for   tracking   popup.  
          else   if   ((hParentMenu   =   ::GetMenu(m_hWnd))   !=   NULL)  
          {  
                  CWnd*   pParent   =   this;  
                        //   Child   windows   don't   have   menus--need   to   go   to   the   top!  
                  if   (pParent   !=   NULL   &&  
                        (hParentMenu   =   ::GetMenu(pParent->m_hWnd))   !=   NULL)  
                  {  
                        int   nIndexMax   =   ::GetMenuItemCount(hParentMenu);  
                        for   (int   nIndex   =   0;   nIndex   <   nIndexMax;   nIndex++)  
                        {  
                          if   (::GetSubMenu(hParentMenu,   nIndex)   ==   pPopupMenu->m_hMenu)  
                          {  
                                  //   When   popup   is   found,   m_pParentMenu   is   containing   menu.  
                                  state.m_pParentMenu   =   CMenu::FromHandle(hParentMenu);  
                                  break;  
                          }  
                        }  
                  }  
          }  
   
          state.m_nIndexMax   =   pPopupMenu->GetMenuItemCount();  
          for   (state.m_nIndex   =   0;   state.m_nIndex   <   state.m_nIndexMax;  
              state.m_nIndex++)  
          {  
                  state.m_nID   =   pPopupMenu->GetMenuItemID(state.m_nIndex);  
                  if   (state.m_nID   ==   0)  
                        continue;   //   Menu   separator   or   invalid   cmd   -   ignore   it.  
   
                  ASSERT(state.m_pOther   ==   NULL);  
                  ASSERT(state.m_pMenu   !=   NULL);  
                  if   (state.m_nID   ==   (UINT)-1)  
                  {  
                        //   Possibly   a   popup   menu,   route   to   first   item   of   that   popup.  
                        state.m_pSubMenu   =   pPopupMenu->GetSubMenu(state.m_nIndex);  
                        if   (state.m_pSubMenu   ==   NULL   ||  
                          (state.m_nID   =   state.m_pSubMenu->GetMenuItemID(0))   ==   0   ||  
                          state.m_nID   ==   (UINT)-1)  
                        {  
                          continue;               //   First   item   of   popup   can't   be   routed   to.  
                        }  
                        state.DoUpdate(this,   TRUE);       //   Popups   are   never   auto   disabled.  
                  }  
                  else  
                  {  
                        //   Normal   menu   item.  
                        //   Auto   enable/disable   if   frame   window   has   m_bAutoMenuEnable  
                        //   set   and   command   is   _not_   a   system   command.  
                        state.m_pSubMenu   =   NULL;  
                        state.DoUpdate(this,   FALSE);  
                  }  
   
                  //   Adjust   for   menu   deletions   and   additions.  
                  UINT   nCount   =   pPopupMenu->GetMenuItemCount();  
                  if   (nCount   <   state.m_nIndexMax)  
                  {  
                        state.m_nIndex   -=   (state.m_nIndexMax   -   nCount);  
                        while   (state.m_nIndex   <   nCount   &&  
                          pPopupMenu->GetMenuItemID(state.m_nIndex)   ==   state.m_nID)  
                        {  
                          state.m_nIndex++;  
                        }  
                  }  
                  state.m_nIndexMax   =   nCount;  
          }  
  }  

增加WM_KICKIDLE消息的响应。   
在里面调用UpdateDialogControls,   
在基于对话框程序中使用WM_KICKIDLE消息

在VC基于对话框程序中,似乎不能使用OnIdle。从网上查了一下,可以用WM_KICKIDLE消息实现相同功能。WM_KICKIDLE消息响应需要自己手动添加代码。下面是步骤:

1.MyDlg.cpp文件添加包含:

#include   <afxpriv.h>

2.MyDlg.h文件添加声明

afx_msg   LRESULT   OnKickIdle(WPARAM   wParam,   LPARAM   lParam);

3.MyDlg.cpp文件添加消息映射:

ON_MESSAGE(WM_KICKIDLE,OnKickIdle)

4.MyDlg.cpp添加函数的实现:
  LRESULT   CTabDialog::OnKickIdle(WPARAM   wp,  
                                                                  LPARAM   lCount)  
    {  
            UpdateDialogControls(this,   TRUE);  
            return   0;  
    }  

 

整个过程我已使用,并且成功,就是在前面和后面在源文件和头文件之中加入消息循环之后,再加入函数的时候,他会提示你函数已存在,这时需要把函数delete(点击右键选),然后再添加函数,这时编译得时候会说头文件中的两个afx。。。已定义,这时只需在其前面将其加//,即可编译通过。。。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yacper/archive/2009/12/31/5106251.aspx

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值