当前位置: 首页 > article >正文

MFC 应用最小化到系统托盘

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

目标:

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

步骤详解:

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

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

#define ID_TRAY_RESTORE 1001  // 恢复窗口
#define ID_TRAY_EXIT 1002     // 退出程序

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

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

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 映射来处理菜单项的选择:

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() 中初始化托盘图标数据:

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 的值判断是左键点击还是右键点击。

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. 实现右键菜单项处理方法

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

5. 实现关闭窗口

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

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 中删除托盘图标,并释放资源:

Shell_NotifyIcon(NIM_DELETE, &m_trayIconData);  // 删除托盘图标

总结:

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

  1. 当用户关闭窗口时,询问是要最小化到系统托盘还是退出应用程序。
  2. 左键单击托盘图标以恢复窗口。
  3. 右键单击托盘图标以显示上下文菜单,允许用户恢复窗口或退出应用程序。

http://www.kler.cn/a/536575.html

相关文章:

  • CPU的基本结构
  • DeepSeek 模型发展脉络全解析
  • 力扣刷题思路
  • 车载以太网__传输层
  • 机器学习模型--线性回归、逻辑回归、分类
  • LabVIEW2025中文版软件安装包、工具包、安装教程下载
  • NetCore Consul动态伸缩+Ocelot 网关 缓存 自定义缓存 + 限流、熔断、超时 等服务治理
  • 如何轻松将Matlab生成的图表嵌入PowerPoint演示文稿
  • 23、深入理解 Java Stream:高效处理数据的利器
  • 什么是高光谱成像相机?
  • .NET周刊【1月第3期 2025-01-19】
  • 网站改HTTPS方法
  • YOLOv11-ultralytics-8.3.67部分代码阅读笔记-downloads.py
  • PHP云调查考试问卷系统小程序
  • C++开发(软件开发)常见面试题
  • 【QT】控件 -- 多元素类 | 容器类 | 布局类
  • 日志级别修改不慎引发的一场CPU灾难
  • Elasticsearch 高级技巧
  • 基于机器学习时序库pmdarima实现时序预测
  • 使用 `WITH` 子句优化复杂 SQL 查询
  • 6 maven工具的使用、maven项目中使用日志
  • RISC-V芯片与扩展医疗影像处理边缘设备编程探析
  • SQL Server 数据库迁移到 MySQL 的完整指南
  • BCrypt加密密码和md5加密哪个更好一点///jwt和rsa有什么区别//为什么spring中经常要用个r类
  • 优惠券平台(十一):布隆过滤器、缓存空值、分布式组合的双重判定锁解决缓存穿透问题
  • 区块链技术:Facebook 重塑社交媒体信任的新篇章