MFC small note: the system tray to achieve

First, demand

Paper implements the program in the system tray.

Second, the interface

The main interface is a dialog with minimize, maximize, close the other functions.

Third, the principle

Class using the NOTIFYICONDATA system tray, custom response message, processing tray mouse events.

Fourth, the coding

4.1 Message Definition

Defined message ID, of WM_USER must be greater than, for convenience, can be defined in the stdafx.h:

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

In the dialog header file declare a message response function:

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

In the dialog implementation file, add a message associated with the response function:

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 Variable declaration

Declared in the class

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

4.3 Initialization

In OnInitDialog function to initialize:

// 系统托盘
        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;

The same document, implement response WM_SHOWTASK message, including handling the left mouse button, right-:

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 response minimized window destroy events


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);
}

This paper implemented the system tray, right-only "exit" option can be added as appropriate.
Further, when starting minimized flickering window for an instant, in the acceptable range, it is not solved.

Published 481 original articles · won praise 244 · Views 1.1 million +

Guess you like

Origin blog.csdn.net/subfate/article/details/103651171