• MFC 如何启用/禁用菜单(返灰/不可点击状态)


    1、为页面(窗口)添加一个菜单栏和子菜单

    2、在XXDlg.h文件中定义一个菜单栏变量和bool变量

    CMenu m_Menu;	//菜单变量
    bool m_EnableMenu;//菜单栏中某个子菜单禁用/启用(变灰)的控制变量
    
    • 1
    • 2

    3、在OnInitDialog函数中进行初始化:(即将菜单栏植入主界面)

    m_Menu.LoadMenu(IDR_MENU_MAIN);//菜单栏的ID
    SetMenu(&m_Menu);//添加入到界面
    m_EnableMenu =false;//初始化为禁用子菜单
    
    • 1
    • 2
    • 3

    4、添加菜单ID的ON_UPDATE_COMMAND_UI消息,点击菜单,在子菜单上右键点击,添加事件处理程序,选择你的对话框类,在左边的消息类型中选择UPDATE_COMMAND_UI添加如下代码:
    在这里插入图片描述

    void CXXDlg::OnUpdateDisconnectAll(CCmdUI *pCmdUI)
    {
    	pCmdUI->Enable(m_EnableMenu); //m_EnableMenu的值对应禁用和启用,1是启用,0是禁用
    } 
    
    • 1
    • 2
    • 3
    • 4

    根据网上资料,对于视图文档类MFC程序,在主框架类CMainFrame的构造函数中把成员变量m_bAutoMenuEnable=FALSE就可以解决问题了。但是基于对话框的MFC应用程序没有m_bAutoMenuEnable变量。解决方法:

    5、在对话框类的消息中加入OnInitMenuPopup()消息:
    在这里插入图片描述

    消息函数内重载如下:

    void CXXXDlg::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
    {
         CDialog::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);
    
       	// TODO: 在此处添加消息处理程序代码
       
    	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;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79

    如果想在其他程序中改变菜单的启用/禁用属性,改变m_EnableMenu的值即可实现。

  • 相关阅读:
    如何在 Protocol Buffers (Proto) 文件中弃用一个字段
    【C++ STL】-- deque与vector相比的优势与劣势
    slambook2(ch2)—— Ubuntu20.04 使用cmake + make自动化编译过程
    Window11专业版安装Java环境
    CSS学习笔记
    解析ajax服务请求——客户端的数据配置解析——服务端node的接收数据的解析——其他状态——fetch——ajax封装fetch
    洛谷 P5058 [ZJOI2004]嗅探器(割点)
    【es6】解决箭头函数所有的问题,箭头函数的 this 指针,使用 new 操作符
    请求地址‘/operlog‘,发生未知异常
    C++ 与 QML 之间进行数据交互的几种方法
  • 原文地址:https://blog.csdn.net/qq_33723441/article/details/132874461