MFC开发中如何在系统菜单“始终置顶”项旁添加复选框
MFC系统菜单自定义置顶项带复选标记实现
不用折腾自定义位图,直接用Win32菜单自带的复选标记接口就能实现,全是原生API,没有兼容问题,改完就能跑:
- 首先在对话框类头文件加一个成员变量,记录当前窗口的置顶状态,初始值设为
FALSE(默认非置顶)
// DiagDlg.h 类内私有成员 BOOL m_bIsTopMost = FALSE;
- 给对话框类添加
WM_INITMENUPOPUP消息处理,每次系统菜单弹出前,自动同步菜单项的勾选状态,避免标记和实际窗口状态不一致。这个消息可以直接在MFC类向导里找到添加,不用手动写消息映射。
void CDiagDlg::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu) { CDialogEx::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu); if (bSysMenu) { pPopupMenu->CheckMenuItem(IDM_SYSCOMMAND_CUSTOM, m_bIsTopMost ? MF_CHECKED : MF_UNCHECKED); } }
- 修改
OnInitDialog里的菜单添加逻辑,初始状态设为未勾选即可,其他原有初始化逻辑不用动
BOOL CDiagDlg::OnInitDialog() { CDialogEx::OnInitDialog(); CMenu * pSystemMenu = GetSystemMenu(FALSE); pSystemMenu->AppendMenu(MF_ENABLED | MF_UNCHECKED, IDM_SYSCOMMAND_CUSTOM,_T("Always on top")); return TRUE; }
- 重写
OnSysCommand的自定义项处理逻辑,删掉原来的确认消息框代码,点击菜单项时直接翻转置顶状态,调用SetWindowPos生效即可
void CDiagDlg::OnSysCommand(UINT nID, LPARAM lParam) { if (nID == IDM_SYSCOMMAND_CUSTOM) { m_bIsTopMost = !m_bIsTopMost; SetWindowPos( m_bIsTopMost ? &CWnd::wndTopMost : &CWnd::wndNoTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE ); } else { CDialog::OnSysCommand(nID, lParam); } }
实现说明:系统自带的
CheckMenuItem会自动渲染和当前系统主题一致的菜单勾选标记,不需要手动加载位图资源,视觉上和系统原生菜单项的复选效果完全统一,也不会出现不同Windows版本下的兼容问题。SetWindowPos参数里加了SWP_NOMOVE标记,切换置顶状态时不会改变窗口当前位置,比原有写法更稳定。
内容的提问来源于stack exchange,提问作者Tough cookie
相关产品推荐
相关产品推荐

