文章目录
- MFC - 给系统菜单(About Dialog)发消息
- 概述
- 笔记
- resource.h
- 菜单的建立
- 菜单项的处理
- MSDN上关于系统菜单项值的说法
- END
MFC - 给系统菜单(About Dialog)发消息
概述
做了一个对话框程序, 在系统菜单(在程序上面的标题栏右击)中有"关于"的菜单.
这个是程序框架自带的, 自己没写代码.
这个Dlg程序, 因为简单, 没加啥菜单. 将授权也放到"关于"对话框中一并处理.
怕用户看不到咋进入"关于"菜单, 在UI上加了一个"关于"的按钮.
在这个按钮实现中, 就是调用系统菜单中的"关于"菜单项.
是可以自己再照着框架模板生成的代码, 将About Dlg 的调用代码抄过来, 感觉不怎么好(已经有的代码写2遍?).
想想, 是否可以给About菜单项发个消息, 模拟手工点击菜单的效果. 这样好像优雅一点.
试了几次, 整出来了, 就一句话.
void CxxDlg::OnBnClickedButtonLicense()
{
// https://learn.microsoft.com/zh-cn/windows/win32/menurc/wm-syscommand
this->PostMessageW(WM_SYSCOMMAND, IDM_ABOUTBOX, 0);
}
笔记
结合MSDN, 看看IDM_ABOUTBOX这个菜单项相关的东西.
resource.h
#define IDM_ABOUTBOX 0x0010
IDM_ABOUTBOX是一个很小的值.
菜单的建立
BOOL CxxDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
// IDM_ABOUTBOX 值定义的范围有要求, 不过都是MFC模板来预先定义好, 我们不用管
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != nullptr)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
这个添加系统菜单的实现, 如果我们要新增系统菜单项上的条目, 也可以这样加.
菜单项的处理
void CxxDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
// 这里能看出来, 系统菜单项的值不能乱定义, 有范围的.
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
MSDN上关于系统菜单项值的说法
https://learn.microsoft.com/zh-cn/windows/win32/menurc/wm-syscommand
PostMessage的参数:
参数1 : message = WM_SYSCOMMAND
参数2 : wParam = IDM_ABOUTBOX // msdn上给的wParam范围, 都是SC_XX, 没有系统菜单项的例子
参数3 : lParam = 0, 按照msdn的说法, lParam是鼠标点击时所在的坐标, 看程序框架中的系统菜单项处理, 没有用lParam, 所以我们也不用填(给0).
- 可以看出系统菜单项的ID范围 from 0x0010 ~ 0xFFF0
- 如果自己定义了菜单项, 就必须自己处理, 不能传给框架.