系统托盘图标

系统托盘图标的创建主要使用 Shell_NotifyIcon 函数来实现,实现过程比较简单。

注意:
要创建系统托盘图标,必须要有窗口;要创建窗口,必须要有窗口过程函数。
一个窗口可以有多个系统托盘图标;图标彼此间用 hWnd 和 uID 区分;
窗口过程函数接收到事件后, wParam 表示 uID,lParam 表示 message;

以下是封装的托盘类代码:

// notifyicon.h

#ifndef _NOTIFYICON_H_
#define _NOTIFYICON_H_
#include <windows.h>
#include <shellapi.h>
#include <map>

typedef VOID (*NotifyIconCallback) (UINT uID, UINT message);

class NotifyIcon
{
public:
    static UINT AddIcon(HICON hIcon, WCHAR* szTip);
    static VOID DelIcon(UINT uID);
    static VOID ModIcon(UINT uID, HICON hIcon, WCHAR* szTip);
    static UINT Attach(NotifyIconCallback pCallback);
    static VOID Detach(UINT uCookie);

private:
    static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

private:
    static HWND m_hWnd;
    static UINT m_uCookieCount;
    static std::map<UINT,NotifyIconCallback> m_mapCallback;
    static UINT m_uIDCount;
    static std::map<UINT,NOTIFYICONDATA> m_mapNotifyData;
};

#endif

 

 

// notifyicon.cpp

#include "notifyicon.h"

HWND NotifyIcon::m_hWnd = NULL;
UINT NotifyIcon::m_uCookieCount = 0;
std::map<UINT,NotifyIconCallback> NotifyIcon::m_mapCallback;
UINT NotifyIcon::m_uIDCount = 0;
std::map<UINT,NOTIFYICONDATA> NotifyIcon::m_mapNotifyData;

UINT NotifyIcon::AddIcon( HICON hIcon, WCHAR* szTip )
{
    // 创建窗口
    LPCTSTR pszClassName = TEXT("NotifyIcon_ClassName");
    LPCTSTR pszWndName = TEXT("NotifyIcon_WndName");
    HINSTANCE hInstance = GetModuleHandle(NULL);
    WNDCLASS wndClass;
    if (GetClassInfo(hInstance, pszClassName, &wndClass) == 0)
    {
        wndClass.style = CS_HREDRAW | CS_VREDRAW;
        wndClass.lpfnWndProc = NotifyIcon::WndProc;
        wndClass.cbClsExtra = 0;
        wndClass.cbWndExtra = 0;
        wndClass.hInstance = hInstance;
        wndClass.hIcon = NULL;
        wndClass.hCursor = NULL;
        wndClass.hbrBackground = NULL;
        wndClass.lpszClassName = pszClassName;
        wndClass.lpszMenuName = NULL;
        if (RegisterClass(&wndClass) == NULL)
        {
            return NULL;
        }
    }
    if (FindWindow(pszClassName, pszWndName) == NULL)
    {
        m_hWnd = CreateWindowEx(WS_EX_TOOLWINDOW,
            pszClassName, pszWndName,
            WS_POPUP,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            NULL, NULL, hInstance, NULL);
        if (m_hWnd == NULL)
        {
            return NULL;
        }
    }

    UINT uID = m_uIDCount;
    m_uIDCount++;

    NOTIFYICONDATA nd;
    nd.cbSize = sizeof(nd);
    nd.hWnd = m_hWnd;
    nd.uID = uID;
    nd.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
    nd.uCallbackMessage = WM_USER;
    nd.hIcon = hIcon;
    if (szTip != NULL && lstrlen(szTip) < 127)
    {
        lstrcpy(nd.szTip, szTip);
    }
    if(Shell_NotifyIcon(NIM_ADD, &nd) == TRUE)
    {
        m_mapNotifyData.insert(std::make_pair(uID, nd));
        return uID;
    }

    return NULL;
}

VOID NotifyIcon::DelIcon( UINT uID )
{
    if (m_hWnd == NULL)
    {
        return;
    }
    std::map<UINT, NOTIFYICONDATA>::iterator iter = m_mapNotifyData.find(uID);
    if (iter != m_mapNotifyData.end())
    {
        Shell_NotifyIcon(NIM_DELETE, &(iter->second));
        m_mapNotifyData.erase(iter);
    }
}

VOID NotifyIcon::ModIcon( UINT uID, HICON hIcon, WCHAR* szTip )
{
    if (m_hWnd == NULL)
    {
        return;
    }
    std::map<UINT, NOTIFYICONDATA>::iterator iter = m_mapNotifyData.find(uID);
    if (iter != m_mapNotifyData.end())
    {
        if (hIcon != NULL)
        {
            iter->second.hIcon = hIcon;
        }
        if (szTip && lstrlen(szTip) < 127)
        {
            lstrcpy(iter->second.szTip, szTip);
        }
        else
        {
            lstrcpy(iter->second.szTip, L"");
        }
        Shell_NotifyIcon(NIM_MODIFY, &(iter->second));
    }
}

UINT NotifyIcon::Attach( NotifyIconCallback pCallback )
{
    if (pCallback == NULL)
    {
        return NULL;
    }
    UINT uCookie = m_uCookieCount;
    m_uCookieCount ++;

    m_mapCallback.insert(std::make_pair(uCookie, pCallback));
    return uCookie;
}

VOID NotifyIcon::Detach( UINT uCookie )
{
    std::map<UINT, NotifyIconCallback>::iterator iter = m_mapCallback.find(uCookie);
    if (iter != m_mapCallback.end())
    {
        m_mapCallback.erase(iter);
    }
}

LRESULT CALLBACK NotifyIcon::WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
    switch(message)
    {
    case WM_CREATE:
        break;
    case WM_DESTROY:
        break;
    case WM_USER:
        for (std::map<UINT, NotifyIconCallback>::iterator iter = m_mapCallback.begin(); iter != m_mapCallback.end(); ++iter)
        {
            NotifyIconCallback pCallback = iter->second;
            pCallback(wParam, lParam);        // wParam --> uID, lParam --> message
        }
        break;
    default:
        break;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

 

 

// main.cpp 测试

#include <windows.h>
#include "notifyicon.h"

void callbackFunc(UINT uID, UINT message);

int main()
{
    HINSTANCE hInstance = GetModuleHandle(NULL);
    HICON hIcon = LoadIcon(hInstance, IDI_APPLICATION);
    WCHAR szTip[128] = L"哈哈哈";
    UINT uID1 = NotifyIcon::AddIcon(hIcon, szTip);
    UINT uID2 = NotifyIcon::AddIcon(hIcon, szTip);
    UINT uID3 = NotifyIcon::AddIcon(hIcon, szTip);
    NotifyIcon::ModIcon(uID3, hIcon, NULL);
    NotifyIcon::DelIcon(uID2);
    UINT uCookie = NotifyIcon::Attach(callbackFunc);
    NotifyIcon::Detach(uCookie);

    MSG msg;

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

void callbackFunc(UINT uID, UINT message)
{
    if (message == WM_LBUTTONDOWN || message == WM_LBUTTONUP || message == WM_LBUTTONDBLCLK ||
        message == WM_RBUTTONDOWN || message == WM_RBUTTONUP || message == WM_RBUTTONDBLCLK)
    {
        WCHAR szDbg[256];
        ZeroMemory(szDbg,256);
        wsprintf(szDbg, L"[Dongyu] uID = %d, message = %x", uID, message);
        OutputDebugString(szDbg);
    }
}

 

 

参考文章:

http://www.nowamagic.net/librarys/veda/detail/227

系统托盘图标,布布扣,bubuko.com

时间: 2024-10-13 18:29:45

系统托盘图标的相关文章

JavaFx 添加系统托盘图标

//添加系统托盘图标. SystemTray tray = SystemTray.getSystemTray(); BufferedImage image = ImageIO.read(mainUi.class .getResourceAsStream("orange-ball.png")); trayIcon = new TrayIcon(image, "自动备份工具"); trayIcon.setToolTip("自动备份工具"); tray

Ubuntu 14.04系统托盘图标问题,skype托盘图标显示

Ubuntu?14.04系统托盘图标问题,skype托盘图标显示_瑞波支付_新浪博客 Ubuntu 14.04 取消了系统托盘白名单机制,导致使用传统系统托盘技术的程序无法显示出托盘图标,dconf-editor也无力解决这个问题 .Ubuntu Unity桌面目前使用的技术是indicator-application-service.那么如何继续让传统程序显示托盘图标呢?执行如下命令即可解决: ? sudo apt-get install libappindicator1 ? sudo apt

MFC 系统托盘图标实现(转载)

首先,必须知道一个结构体NOTIFYICONDATA ,这是MFC中包含系统需要的用来传递托盘区域消息的信息结构体,有了它,我们今 天的任务就完全可以轻松完成了! 这时候,我们可以在我们的类中申明一个NOTIFYICONDATA的成员变量为m_nid. 接下来,我们可以给这个结构体变量赋我们想要的值了,记住赋值语句要写在OnInitDialog初始化窗口函数里,不要写在构造函 数中,否则将会无效.m_nid.cbSize = sizeof( NOTIFYICONDATA );m_nid.hWnd

Ubuntu:如何显示系统托盘图标(systray)

1. 问题说明 Ubuntu 11版本开始,默认关闭了托盘图标的显示,需要手动执行命令或额外工具配置,添加到白名单.Ubuntu 13.04更彻底,默认配置根本没有托盘图标,除了java和wine等几个系统自带的程序可以显示,其它任何应用程序都不能显示,以前的命令也不支持了,例如QQ也显示不了了. Ubuntu 14.04 取消了系统托盘白名单机制,导致使用传统系统托盘技术的程序无法显示出托盘图标,dconf-editor也无力解决这个问题.Ubuntu Unity桌面目前使用的技术是indic

实现动态系统托盘图标

实现效果: 知识运用: TcpListener TcpClient  和  NetworkStream类 及  Timer组件 1> TcpListener类 //用来从Tcp网络客户端侦听连接 2> TcpClient类 //为Tcp网络服务提供客户端连接 public TcpClient(string hostname,int port) //远程主机的DNS名 端口号 3> NetworkStream类 //提供在阻止模式下通过Stream套接字发送和接受数据的方法 //其Read

动态系统托盘图标

实现效果: 知识运用: TcpListener TcpClient  和  NetworkStream类 及  Timer组件 1> TcpListener类 //用来从Tcp网络客户端侦听连接 2> TcpClient类 //为Tcp网络服务提供客户端连接 public TcpClient(string hostname,int port) //远程主机的DNS名 端口号 3> NetworkStream类 //提供在阻止模式下通过Stream套接字发送和接受数据的方法 //其Read

Qt系统托盘

Qt的系统托盘的使用,可比mfc中好多了!他封装了一个专门的QSystemTrayIcon类,建立系统托盘图标.其实在Qt提供的示例程序已经很不错了,$QTDIR\examples\desktop\systray在这里简单的实现一个系统托盘功能,对其系统托盘类的使用做以演示. #include <QtGui>class Window: public QWidget{    Q_OBJECT        public:    Window(); private:    void showMes

WinForm实现最小化窗体时隐藏到系统托盘中

1.首先在工具栏中选择NotifyIcon控件拖入窗体中: 2.设置NotifyIcon控件的相关属性: Icon:在系统托盘中显示的图标: Text:当鼠标移动到系统托盘图标上时显示的文本: ContextMenuStrip:设置系统托盘的右键菜单,这个实现很简单,拖入一个右键菜单的控件,并在下拉列表框中选择就可以了. 3.添加相关代码 /// <summary> /// 窗体SizeChanged事件 /// </summary> /// <param name=&quo

系统托盘编程完全指南

原文:http://www.hellocpp.net/Articles/Article/574.aspx 第一部分 自从Windows 95面市以来,系统托盘应用作为一种极具吸引力的UI深受广大用户的喜爱.使用系统托盘UI的Windows应用程序数不胜数,比如"金山词 霸"."Winamp"."RealPlayer"等等.那么如何编写自己的托盘应用呢?本文是系列文章中的第一篇,这些文章将比较系统地描述托盘应用的 编程.并创建自己的C++类来增强系