MFC小笔记:系统托盘实现

一、需求

本文实现程序系统托盘。

二、界面

主界面为对话框,有最小化、最大化、关闭等功能。

三、原理

利用系统托盘类NOTIFYICONDATA,响应自定义消息,处理托盘鼠标事件。

四、编码

4.1 消息定义

定义消息ID,必须大于WM_USER,为方便起见,可在stdafx.h中定义:

#define WM_SHOWTASK (WM_USER+1)  // 系统托盘事件

在对话框头文件声明消息响应函数:

    afx_msg LRESULT OnSystemtray(WPARAM wParam, LPARAM lParam);
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnDestroy();
    

在对话框实现文件,添加消息与响应函数的关联:

BEGIN_MESSAGE_MAP(CMyTestDlg, CDialogEx)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    // ...
    ON_MESSAGE(WM_SHOWTASK, OnSystemtray) // 托盘
    ON_WM_SIZE()
    ON_WM_DESTROY() // 销毁
END_MESSAGE_MAP()

4.2 变量声明

在类中声明

private: 
    NOTIFYICONDATA m_nid;
    BOOL m_fMainWinShow; // 托盘 双击左键显示/隐藏窗口

4.3 初始化

在OnInitDialog函数中初始化:

// 系统托盘
        m_nid.cbSize = (DWORD)sizeof(NOTIFYICONDATA);
        m_nid.hWnd = this->m_hWnd;
        m_nid.uID = IDR_MAINFRAME;
        m_nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO;
        m_nid.uCallbackMessage = WM_SHOWTASK; // 自定义的消息名称
        m_nid.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));
        wcscpy_s(m_nid.szTip, L"主程序"); // 提示程序名称
        Shell_NotifyIcon(NIM_ADD, &m_nid); // 在托盘区添加图标

// 如此实现,任务栏没有图标,但窗口没有最小化按钮
#if 0
//ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW); // 不在任务栏中显示
// ShowWindow(SW_MINIMIZE);
#endif
        //ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW); // 不在任务栏中显示

        // 可以实现,但界面会闪烁
        ShowWindow(SW_MINIMIZE); // 不能使用SW_HIDE
        PostMessage(WM_SYSCOMMAND, SC_MINIMIZE, 0);

        m_fMainWinShow = FALSE;

同一文件,实现WM_SHOWTASK消息的响应,包括鼠标左键、右键的处理:

LRESULT CMyTestDlg::OnSystemtray(WPARAM wParam, LPARAM lParam)
{
    if (wParam != IDR_MAINFRAME)
        return 1;
    switch (lParam)
    {
    case WM_RBUTTONUP: // 右键起来时弹出菜单
    {
        LPPOINT lpoint = new tagPOINT;
        GetCursorPos(lpoint); // 得到鼠标位置
        CMenu menu;
        menu.CreatePopupMenu(); // 声明一个弹出式菜单
        menu.AppendMenu(MF_STRING, WM_DESTROY, L"退出");
        SetForegroundWindow();
        menu.TrackPopupMenu(TPM_LEFTALIGN, lpoint->x, lpoint->y, this);
        HMENU hmenu = menu.Detach();
        menu.DestroyMenu();
        delete lpoint;
    }
    break;
    case WM_LBUTTONDBLCLK: // 双击左键的处理
    {
        if (!m_fMainWinShow)
        {
            ShowWindow(SW_SHOWNORMAL); // 显示主窗口
            SetForegroundWindow();
            m_fMainWinShow = TRUE;
        }
        else
        {
            ShowWindow(SW_HIDE); // 隐藏主窗口
            SetForegroundWindow();
            m_fMainWinShow = FALSE;
        }
    }
    break;
    }
    return 0;
}

4.4 响应最小化、窗口销毁事件


void CMyTestDlg::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);

    if (nType == SIZE_MINIMIZED)
    {
        ShowWindow(SW_HIDE); // 当最小化时,隐藏主窗口
    }
}

void CMyTestDlg::OnDestroy()
{
    CDialogEx::OnDestroy();

    // 在托盘区删除图标
    Shell_NotifyIcon(NIM_DELETE, &m_nid);
}

本文实现的系统托盘,右键只有“退出”一个选项,可酌情添加。
另外,在启动时最小化,窗口会有瞬间闪烁的现象,在可接受范围,故不解决。

发布了481 篇原创文章 · 获赞 244 · 访问量 110万+

猜你喜欢

转载自blog.csdn.net/subfate/article/details/103651171