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. 右键单击托盘图标以显示上下文菜单,允许用户恢复窗口或退出应用程序。
相关推荐
钟离墨笺2 小时前
【c++】四种类型转换形式
开发语言·c++
汤姆和杰瑞在瑞士吃糯米粑粑2 小时前
【C++学习篇】C++11
开发语言·c++
_extraordinary_2 小时前
C++智能指针的使用
c++·智能指针
zjkzjk77112 小时前
C++ 左值引用 & 右值引用 && std::move()左值改右值 移动构造函数()
开发语言·c++
knowledgebao3 小时前
OHOS(HarmonyOS) 编译 C/C++ 库
c语言·c++·harmonyos
HL_LOVE_C3 小时前
全面理解-c++11中的智能指针
开发语言·c++
KAI77383 小时前
2月10日QT
c++
獨枭5 小时前
在 MFC 应用中集成 WebView2
c++·mfc
清泓y6 小时前
UE5--浅析委托原理(Delegate)
c++·ue5·ue4
RangoLei_Lzs6 小时前
C++性能优化—AI润色版
开发语言·c++·性能优化