MFC 应用最小化到系统托盘

本指南将实现 MFC 应用程序在关闭时最小化系统托盘的功能,并左键和右键系统托盘图标进行交互。

目标:

  • 左键点击托盘图标:恢复对话框窗口。
  • 右键点击托盘图标 :弹出右键菜单,提供 恢复窗口退出程序 两个选项。
  • 退出时删除托盘图标,并关闭对话框。

步骤详解:

1. 定义托盘图标的 ID 和所需资源

定义托盘图标的菜单项 ID,例如:

cpp 复制代码
#define ID_TRAY_RESTORE 1001  // 恢复窗口
#define ID_TRAY_EXIT 1002     // 退出程序

2. 定义成员变量和消息映射

CDlgMFCApplicationDlg 类的头文件中,定义托盘图标的数据结构和处理方法。

cpp 复制代码
private:
    NOTIFYICONDATA m_trayIconData;  // 托盘图标数据
    UINT m_nTrayIconID;             // 托盘图标ID
    BOOL m_bTrayIconCreated;        // 标记托盘图标是否创建成功

protected:
    afx_msg void OnClose();               	// 关闭窗口时的处理
    afx_msg LRESULT OnTrayIconClick(WPARAM wParam, LPARAM lParam);  // 托盘图标点击事件
    afx_msg void OnTrayRestore();          	// 恢复窗口
    afx_msg void OnTrayExit();             	// 退出应用

通过 ON_COMMAND 映射来处理菜单项的选择:

cpp 复制代码
BEGIN_MESSAGE_MAP(CDlgMFCApplicationDlg, CDialogEx)
    ON_WM_CLOSE()
    ON_MESSAGE(WM_USER + 1, &CDlgMFCApplicationDlg::OnTrayIconClick)  	// 托盘图标点击事件
    ON_COMMAND(ID_TRAY_RESTORE, &CDlgMFCApplicationDlg::OnTrayRestore)  // 恢复窗口
    ON_COMMAND(ID_TRAY_EXIT, &CDlgMFCApplicationDlg::OnTrayExit)  		// 退出程序
END_MESSAGE_MAP()

OnInitDialog() 中初始化托盘图标数据:

cpp 复制代码
m_trayIconData.cbSize = sizeof(NOTIFYICONDATA);  				// 设置托盘图标数据结构的大小
m_trayIconData.hWnd = m_hWnd;                    				// 设置窗口句柄
m_trayIconData.uID = m_nTrayIconID;              				// 设置托盘图标 ID
m_trayIconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;  		// 设置托盘图标的标志(图标、消息、提示文本)
m_trayIconData.uCallbackMessage = WM_USER + 1;   				// 设置回调消息(WM_USER + 1)
m_trayIconData.hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);  	// 加载托盘图标
lstrcpy(m_trayIconData.szTip, _T("MFC Tray App"));   			// 设置托盘提示文本

// 添加托盘图标
Shell_NotifyIcon(NIM_ADD, &m_trayIconData);
m_bTrayIconCreated = TRUE;

3. 处理托盘图标点击事件

通过 OnTrayIconClick() 来响应托盘图标的点击事件。根据 lParam 的值判断是左键点击还是右键点击。

cpp 复制代码
LRESULT CDlgMFCApplicationDlg::OnTrayIconClick(WPARAM wParam, LPARAM lParam) {
    if (wParam == m_nTrayIconID) {
        if (LOWORD(lParam) == WM_LBUTTONUP) {
            // 左键点击恢复窗口
            ShowWindow(SW_SHOW);
            SetForegroundWindow();
        } else if (LOWORD(lParam) == WM_RBUTTONUP) {
            // 右键点击弹出菜单
            CMenu menu;
            menu.CreatePopupMenu();
            menu.AppendMenu(MF_STRING, ID_TRAY_RESTORE, _T("Restore"));
            menu.AppendMenu(MF_STRING, ID_TRAY_EXIT, _T("Exit"));

			// 获取鼠标当前位置,并显示菜单
            POINT pt;
            GetCursorPos(&pt);  
            menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, this);
        }
    }
    return 0;
}

4. 实现右键菜单项处理方法

  • 恢复窗口
cpp 复制代码
void CDlgMFCApplicationDlg::OnTrayRestore() {
    ShowWindow(SW_SHOW);  	// 恢复窗口
    SetForegroundWindow();  // 将窗口置于前端
}
  • 退出程序
cpp 复制代码
void CDlgMFCApplicationDlg::OnTrayExit() {
    Shell_NotifyIcon(NIM_DELETE, &m_trayIconData);  // 删除托盘图标
    PostMessage(WM_CLOSE);  						// 关闭窗口并退出应用
}

5. 实现关闭窗口

OnClose() 中,询问用户是否希望将应用最小化到系统托盘,如果选择是,则隐藏窗口并保留托盘图标;否则直接退出。

cpp 复制代码
void CDlgMFCApplicationDlg::OnClose() {
    int nResult = AfxMessageBox(_T("Do you want to minimize the application to the system tray?"), MB_YESNO | MB_ICONQUESTION);
    
    if (nResult == IDYES) {
        ShowWindow(SW_HIDE);  // 隐藏窗口
    } else {
        Shell_NotifyIcon(NIM_DELETE, &m_trayIconData);  // 删除托盘图标
        CDialogEx::OnClose(); // 关闭对话框
    }
}

6. 清理托盘图标

OnTrayExitOnClose 中删除托盘图标,并释放资源:

cpp 复制代码
Shell_NotifyIcon(NIM_DELETE, &m_trayIconData);  // 删除托盘图标

总结:

通过以上步骤,已经实现了以下功能:

  1. 当用户关闭窗口时,询问是要最小化到系统托盘还是退出应用程序。
  2. 左键单击托盘图标以恢复窗口。
  3. 右键单击托盘图标以显示上下文菜单,允许用户恢复窗口或退出应用程序。
相关推荐
贫道绝缘子3 小时前
Leetcode-132.Palindrome Partitioning II [C++][Java]
java·c++·算法·leetcode
饼干帅成渣6 小时前
我又又又又又又更新了~~纯手工编写C++画图,有注释~~~
开发语言·c++
mit6.8247 小时前
[Sum] C++STL oj常用API
c++·算法·leetcode
槐月初叁8 小时前
C++洛谷基础练习题及解答
开发语言·c++·算法
誓约酱8 小时前
linux 下消息队列
linux·运维·服务器·c语言·c++
Archer1948 小时前
C++基础——从C语言快速入门
数据结构·c++·算法
Hetertopia9 小时前
C++ QT零基础教学(二)
开发语言·c++·qt
一匹电信狗9 小时前
【Linux我做主】基础命令完全指南下篇
linux·运维·服务器·c++·开源·centos·unix
Maple_land9 小时前
C++初阶——类和对象(三) 构造函数、析构函数
c++
张胤尘9 小时前
C/C++ | 每日一练 (6)
c语言·c++·面试