如何简便判断CMFCMenuButton关联菜单项无MF_CHECKED选中状态
简化判断菜单选中状态的方案
因为你的过滤菜单项ID是连续的,仅中间存在一个分隔符,你可以直接遍历ID区间快速判断是否有选中项,代码如下:
// 放在你的对话框类里作为成员函数即可 bool IsAnyFilterChecked() { // 从最小的过滤ID遍历到最大的过滤ID for (UINT id = ID_PUBLISHERS_DATABASE_EXTRA_FILTER_PUBLISHER; id <= ID_PUBLISHERS_DATABASE_EXTRA_FILTER_OTHER; id++) { UINT menuState = m_menuExtraPublisherFilter.GetMenuState(id, MF_BYCOMMAND); // 跳过不存在的分隔符,同时判断是否选中 if (menuState != -1 && (menuState & MF_CHECKED) != 0) { return true; } } return false; }
你可以在遍历aryStrNames之前先调用这个函数,如果返回false,说明没有任何过滤项被选中,直接把所有条目加入列表即可,完全跳过GetPublisher相关的耗时逻辑。
如果还要简化你现有的过滤逻辑,也可以用结构体数组映射ID和判断条件,避免重复写if:
struct FilterRule { UINT id; std::function<bool(MSAToolsLibrary::Serving, MSAToolsLibrary::Appointed)> condition; }; const FilterRule rules[] = { {ID_PUBLISHERS_DATABASE_EXTRA_FILTER_UNBAPTISED_PUBLISHER, [](auto s, auto) { return s == MSAToolsLibrary::Serving_UnbaptisedPublisher; }}, {ID_PUBLISHERS_DATABASE_EXTRA_FILTER_PUBLISHER, [](auto s, auto) { return s == MSAToolsLibrary::Serving_Publisher; }}, {ID_PUBLISHERS_DATABASE_EXTRA_FILTER_REGULAR_PIONEER, [](auto s, auto) { return s == MSAToolsLibrary::Serving_RegularPioneer; }}, {ID_PUBLISHERS_DATABASE_EXTRA_FILTER_OTHER, [](auto s, auto) { return s == MSAToolsLibrary::Serving_Other; }}, {ID_PUBLISHERS_DATABASE_EXTRA_FILTER_NOT_APPOINTED, [](auto, auto a) { return a == MSAToolsLibrary::Appointed_NotAppointed; }}, {ID_PUBLISHERS_DATABASE_EXTRA_FILTER_MINISTERIAL_SERVANT, [](auto, auto a) { return a == MSAToolsLibrary::Appointed_MinisterialServant; }}, {ID_PUBLISHERS_DATABASE_EXTRA_FILTER_ELDER, [](auto, auto a) { return a == MSAToolsLibrary::Appointed_Elder; }}, }; // 原来的一大段if可以替换成: bool bNoExtraPublisherFilter = true; bool bAdd = false; for (const auto& rule : rules) { if (m_menuExtraPublisherFilter.GetMenuState(rule.id, MF_BYCOMMAND) == MF_CHECKED) { bNoExtraPublisherFilter = false; if (rule.condition(eServing, eAppointed)) { bAdd = true; } } }
后续加新过滤项只需要往rules数组加条目即可,维护更方便。
宏崩溃问题的原因
崩溃的核心原因是你作为成员变量的CMenu m_menuExtraPublisherFilter没有正确初始化,是空句柄状态,调用GetMenuState时访问无效句柄导致崩溃。
你需要在OnInitDialog中先加载对应的菜单资源,再绑定到CMFCMenuButton控件,示例代码:
BOOL YourDialog::OnInitDialog() { CDialogEx::OnInitDialog(); // 先加载菜单资源,IDR_YOUR_FILTER_MENU替换成你实际的菜单资源ID m_menuExtraPublisherFilter.LoadMenu(IDR_YOUR_FILTER_MENU); // 绑定到CMFCMenuButton控件,m_menuBtn是你界面上的CMFCMenuButton控件变量 m_menuBtn.m_hMenu = m_menuExtraPublisherFilter.GetSubMenu(0)->GetSafeHmenu(); // 后面再调用宏就不会崩溃了 PROCESSFILTER(ID_TEST, 5 > 4); return TRUE; }
另外要注意你自定义的ID_TEST必须存在于你加载的菜单资源中,否则GetMenuState会返回-1,但不会直接导致崩溃。
内容的提问来源于stack exchange,提问作者Andrew Truckle
相关产品推荐
相关产品推荐

