托盘简介

所谓的“托盘”,在Windows系统界面中,指的就是下面任务条右侧的程序小图标位置。在程序最小化时又不希望占据任务栏的话,就可以把程序放到托盘区。

相关函数

介绍:向任务栏的状态区域发送消息。
微软官方文档:https://docs.microsoft.com/zh-cn/windows/win32/api/shellapi/nf-shellapi-shell_notifyicona

1
2
3
4
BOOL Shell_NotifyIconA(
[in] DWORD dwMessage,
[in] PNOTIFYICONDATAA lpData
);

参数

dwMessage:一个值,指定此函数要执行的操作,它可以具有以下值之一。
lpData:指向NOTIFYICONDATA结构的指针。结构的内容取决于dwMessage的值。它可以定义要添加到通知区域的图标,使该图标显示通知,或标识要修改或删除的图标。

NOTIFYICONDATA简介

介绍:包含系统在通知区域中显示通知所需的信息。
微软官方文档:https://docs.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataa

示例代码

第一步

在OnInitDialog函数中填写初始化代码,并且添加自定义消息ID,这样我们可以通过该消息ID收到托盘图标的消息内容了。将lpData参数定义为成员变量,这样方便我们对托盘图标的后续操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 自定义消息,当鼠标移动至图标处就会发送该消息
#define WM_SYSTEMTRAY WM_USER + 1

BOOL CxxxDlg::OnInitDialog() {
CDialogEx::OnInitDialog();

// ...省略其他初始化步骤

// 置托盘图标
// 此处m_nid类型为NOTIFYICONDATA,定义在该类的成员变量处
m_nid.cbSize = sizeof(NOTIFYICONDATA);
m_nid.hWnd = GetSafeHwnd();
m_nid.uID = IDR_MAINFRAME;
m_nid.uFlags = NIF_MESSAGE NIF_ICON NIF_TIP;
m_nid.uCallbackMessage = WM_SYSTEMTRAY; //自定义消息
m_nid.hIcon = m_hIcon;
strcpy_s(m_nid.szTip, "tip");
// 将图标添加至托盘处
::Shell_NotifyIcon(NIM_ADD, &m_nid);

return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}

第二步

添加自定义消息处理函数,处理的消息ID为我们上述自定义的消息ID:WM_SYSTEMTRAY。这里我们一共处理了两个消息类型,一个是右键弹起,负责右键弹出菜单。另一个是鼠标左键双击消息,负责打开程序主界面。

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
afx_msg LRESULT CxxxDlg::OnSystemtray(WPARAM wParam, LPARAM lParam) {
switch (lParam) {
case WM_RBUTTONUP:
{
//右击弹出托盘菜单
CMenu menu;
menu.LoadMenu(MN_TRAYICON); // MN_TRAYICON为你自定义的菜单ID
CMenu* pPopUp = menu.GetSubMenu(0);
CPoint pt;
GetCursorPos(&pt);

SetForegroundWindow();
pPopUp->TrackPopupMenu(TPM_RIGHTBUTTON, pt.x, pt.y, this);
PostMessage(WM_NULL, 0, 0);
}
break;
case WM_LBUTTONDBLCLK:
{
// 双击托盘图标显示主界面
this->ShowWindow(SW_SHOW);
}
break;
}
return 0;
}

第三步

因为我们使用了托盘图标,所以我们最好将WM_CLOSE消息也进行一次处理,具体代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
// 因为系统库没有定义MB_YES和MB_NO所以我们需要自己定义一下
#define MB_YES 6
#define MB_NO 7
void CxxxDlg::OnClose() {
int nRet = AfxMessageBox("是否关闭程序?是【关闭程序】,否【最小化置托盘图标】", MB_YESNO);
if (nRet == MB_YES) {
Shell_NotifyIcon(NIM_DELETE, &m_nid);
CDialogEx::OnClose();
} else {
this->ShowWindow(SW_HIDE);
}
return;
}

结束语

经过上述代码,一步一步按照要求来编写那么你就完成了MFC置托盘图标功能,如果本文章对你有用,请点赞加评论哦~