托盘简介

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

相关函数

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

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参数定义为成员变量,这样方便我们对托盘图标的后续操作。

// 自定义消息,当鼠标移动至图标处就会发送该消息
#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。这里我们一共处理了两个消息类型,一个是右键弹起,负责右键弹出菜单。另一个是鼠标左键双击消息,负责打开程序主界面。

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消息也进行一次处理,具体代码如下。

// 因为系统库没有定义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置托盘图标功能,如果本文章对你有用,请点赞加评论哦~