《Windows核心编程》の托盘程序的编写(CSystemTray类)

来源:互联网 发布:广联达装修预算软件 编辑:程序博客网 时间:2024/05/21 10:22

http://blog.csdn.net/asce1885/article/details/5863785

研究下托盘程序,或者说:任务栏通知区域(Tray)图标。

很多应用程序在系统Shell任务栏通知区域有图标提示。通知区域图标适用于长时间运行但无需用户过多操作,并在有事件发生时可随时根据情况通知用户的应用程序(如即时通信工具、下载工具等)。

使用任务通知区域图标的好处如下:

1)  窗口程序可以在后台运行,窗口退出,但是程序仍然在运行,减少窗口数量,便于用户操作;

2) 窗口最小化后,不占用任务栏的位置,使用户在操作主机时将精力集中在需关注的窗口;

3) 在新事件发生时(如新的即时消息、文件下载完成等),可以即时通知到用户;

4) 用户通过单击、双击图标、图标菜单等可以很方便地配置应用程序,控制应用程序的运行。

 

下面的代码是在网上找到的封装上述功能的类,一个是用于Win32的,一个是用户MFC的,可根据自己的代码选用咯!

 

MFC类的头文件SystemTray.h

/////////////////////////////////////////////////////////////////////////////

// SystemTray.h : header file

//

// Written by Chris Maunder (chrismaunder@codeguru.com)

// Copyright (c) 1998.

//

// This code may be used in compiled form in any way you desire. This

// file may be redistributed unmodified by any means PROVIDING it is

// not sold for profit without the authors written consent, and

// providing that this notice and the authors name is included. If

// the source code in  this file is used in any commercial application

// then acknowledgement must be made to the author of this file

// (in whatever form you wish).

//

// This file is provided "as is" with no expressed or implied warranty.

// The author accepts no liability if it causes any damage to your

// computer, causes your pet cat to fall ill, increases baldness or

// makes you car start emitting strange noises when you start it up.

//

// Expect bugs.

//

// Please use and enjoy. Please let me know of any bugs/mods/improvements

// that you have found/implemented and I will fix/incorporate them into this

// file.

 

#ifndef _INCLUDED_SYSTEMTRAY_H_

#define _INCLUDED_SYSTEMTRAY_H_

 

#include <afxtempl.h>

 

/////////////////////////////////////////////////////////////////////////////

// CSystemTray window

class CSystemTray : public CWnd

{

// Construction/destruction

public:

    CSystemTray();

    CSystemTray(CWnd* pWnd, UINT uCallbackMessage, LPCTSTR szTip, HICON icon, UINT uID);

    virtual ~CSystemTray();

 

    DECLARE_DYNAMIC(CSystemTray)

 

// Operations

public:

    BOOL Enabled() { return m_bEnabled; }

    BOOL Visible() { return !m_bHidden; }

 

    // Create the tray icon

    BOOL Create(CWnd* pParent, UINT uCallbackMessage, LPCTSTR szTip, HICON icon, UINT uID);

 

    // Change or retrieve the Tooltip text

    BOOL    SetTooltipText(LPCTSTR pszTooltipText);

    BOOL    SetTooltipText(UINT nID);

    CString GetTooltipText() const;

 

    // Change or retrieve the icon displayed

    BOOL  SetIcon(HICON hIcon);

    BOOL  SetIcon(LPCTSTR lpszIconName);

    BOOL  SetIcon(UINT nIDResource);

    BOOL  SetStandardIcon(LPCTSTR lpIconName);

    BOOL  SetStandardIcon(UINT nIDResource);

    HICON GetIcon() const;

    void  HideIcon();

    void  ShowIcon();

    void  RemoveIcon();

    void  MoveToRight();

 

    // For icon animation

    BOOL  SetIconList(UINT uFirstIconID, UINT uLastIconID);

    BOOL  SetIconList(HICON* pHIconList, UINT nNumIcons);

    BOOL  Animate(UINT nDelayMilliSeconds, int nNumSeconds = -1);

    BOOL  StepAnimation();

    BOOL  StopAnimation();

 

    // Change menu default item

    void GetMenuDefaultItem(UINT& uItem, BOOL& bByPos);

    BOOL SetMenuDefaultItem(UINT uItem, BOOL bByPos);

 

    // Change or retrieve the window to send notification messages to

    BOOL  SetNotificationWnd(CWnd* pNotifyWnd);

    CWnd* GetNotificationWnd() const;

 

    // Default handler for tray notification message

    virtual LRESULT OnTrayNotification(WPARAM uID, LPARAM lEvent);

 

// Overrides

    // ClassWizard generated virtual function overrides

    //{{AFX_VIRTUAL(CSystemTray)

         protected:

         virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);

         //}}AFX_VIRTUAL

 

// Implementation

protected:

    void Initialise();

 

    BOOL            m_bEnabled;   // does O/S support tray icon?

    BOOL            m_bHidden;    // Has the icon been hidden?

    NOTIFYICONDATA  m_tnd;

 

    CArray<HICON, HICON> m_IconList;

    static UINT  m_nIDEvent;

    UINT         m_uIDTimer;

    int          m_nCurrentIcon;

    COleDateTime m_StartTime;

    int          m_nAnimationPeriod;

    HICON        m_hSavedIcon;

    UINT         m_DefaultMenuItemID;

    BOOL         m_DefaultMenuItemByPos;

 

// Generated message map functions

protected:

         //{{AFX_MSG(CSystemTray)

         afx_msg void OnTimer(UINT nIDEvent);

         //}}AFX_MSG

 

    DECLARE_MESSAGE_MAP()

};

 

 

#endif

 

/////////////////////////////////////////////////////////////////////////////

 

MFC类的实现文件SystemTray.cpp

/////////////////////////////////////////////////////////////////////////////

// SystemTray.cpp : implementation file

//

// This is a conglomeration of ideas from the MSJ "Webster" application,

// sniffing round the online docs, and from other implementations such

// as PJ Naughter's "CTrayNotifyIcon" (http://indigo.ie/~pjn/ntray.html)

// especially the "CSystemTray::OnTrayNotification" member function.

// Joerg Koenig suggested the icon animation stuff

//

// This class is a light wrapper around the windows system tray stuff. It

// adds an icon to the system tray with the specified ToolTip text and

// callback notification value, which is sent back to the Parent window.

//

// The tray icon can be instantiated using either the constructor or by

// declaring the object and creating (and displaying) it later on in the

// program. eg.

//

//        CSystemTray m_SystemTray;    // Member variable of some class

//       

//        ...

//        // in some member function maybe...

//        m_SystemTray.Create(pParentWnd, WM_MY_NOTIFY, "Click here",

//                          hIcon, nSystemTrayID);

//

// Written by Chris Maunder (chrismaunder@codeguru.com)

// Copyright (c) 1998.

//

// Updated: 25 Jul 1998 - Added icon animation, and derived class

//                        from CWnd in order to handle messages. (CJM)

//                        (icon animation suggested by Joerg Koenig.

//                        Added API to set default menu item. Code provided

//                        by Enrico Lelina.

//

// This code may be used in compiled form in any way you desire. This

// file may be redistributed unmodified by any means PROVIDING it is

// not sold for profit without the authors written consent, and

// providing that this notice and the authors name is included. If

// the source code in  this file is used in any commercial application

// then acknowledgement must be made to the author of this file

// (in whatever form you wish).

//

// This file is provided "as is" with no expressed or implied warranty.

// The author accepts no liability if it causes any damage to your

// computer, causes your pet cat to fall ill, increases baldness or

// makes you car start emitting strange noises when you start it up.

//

// Expect bugs.

//

// Please use and enjoy. Please let me know of any bugs/mods/improvements

// that you have found/implemented and I will fix/incorporate them into this

// file.

//

/////////////////////////////////////////////////////////////////////////////

   

#include "stdafx.h"

#include "SystemTray.h"

 

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

 

IMPLEMENT_DYNAMIC(CSystemTray, CWnd)

 

UINT CSystemTray::m_nIDEvent = 4567;

 

/////////////////////////////////////////////////////////////////////////////

// CSystemTray construction/creation/destruction

 

CSystemTray::CSystemTray()

{

    Initialise();

}

 

CSystemTray::CSystemTray(CWnd* pParent, UINT uCallbackMessage, LPCTSTR szToolTip,

                         HICON icon, UINT uID)

{

    Initialise();

    Create(pParent, uCallbackMessage, szToolTip, icon, uID);

}

 

void CSystemTray::Initialise()

{

    memset(&m_tnd, 0, sizeof(m_tnd));

    m_bEnabled   = FALSE;

    m_bHidden    = FALSE;

    m_uIDTimer   = 0;

    m_hSavedIcon = NULL;

    m_DefaultMenuItemID = 0;

    m_DefaultMenuItemByPos = TRUE;

}

 

BOOL CSystemTray::Create(CWnd* pParent, UINT uCallbackMessage, LPCTSTR szToolTip,

                         HICON icon, UINT uID)

{

    // this is only for Windows 95 (or higher)

    VERIFY(m_bEnabled = ( GetVersion() & 0xff ) >= 4);

    if (!m_bEnabled) return FALSE;

 

    // Make sure Notification window is valid (not needed - CJM)

    // VERIFY(m_bEnabled = (pParent && ::IsWindow(pParent->GetSafeHwnd())));

    // if (!m_bEnabled) return FALSE;

   

    // Make sure we avoid conflict with other messages

    ASSERT(uCallbackMessage >= WM_USER);

 

    // Tray only supports tooltip text up to 64 characters

    ASSERT(_tcslen(szToolTip) <= 64);

 

    // Create an invisible window

    CWnd::CreateEx(0, AfxRegisterWndClass(0), _T(""), WS_POPUP, 0,0,10,10, NULL, 0);

 

    // load up the NOTIFYICONDATA structure

    m_tnd.cbSize = sizeof(NOTIFYICONDATA);

    m_tnd.hWnd   = pParent->GetSafeHwnd()? pParent->GetSafeHwnd() : m_hWnd;

    m_tnd.uID    = uID;

    m_tnd.hIcon  = icon;

    m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;

    m_tnd.uCallbackMessage = uCallbackMessage;

    _tcscpy(m_tnd.szTip, szToolTip);

 

    // Set the tray icon

    VERIFY(m_bEnabled = Shell_NotifyIcon(NIM_ADD, &m_tnd));

    return m_bEnabled;

}

 

CSystemTray::~CSystemTray()

{

    RemoveIcon();

    m_IconList.RemoveAll();

    DestroyWindow();

}

 

/////////////////////////////////////////////////////////////////////////////

// CSystemTray icon manipulation

 

void CSystemTray::MoveToRight()

{

    HideIcon();

    ShowIcon();

}

 

void CSystemTray::RemoveIcon()

{

    if (!m_bEnabled) return;

 

    m_tnd.uFlags = 0;

    Shell_NotifyIcon(NIM_DELETE, &m_tnd);

    m_bEnabled = FALSE;

}

 

void CSystemTray::HideIcon()

{

    if (m_bEnabled && !m_bHidden) {

        m_tnd.uFlags = NIF_ICON;

        Shell_NotifyIcon (NIM_DELETE, &m_tnd);

        m_bHidden = TRUE;

    }

}

 

void CSystemTray::ShowIcon()

{

    if (m_bEnabled && m_bHidden) {

        m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;

        Shell_NotifyIcon(NIM_ADD, &m_tnd);

        m_bHidden = FALSE;

    }

}

 

BOOL CSystemTray::SetIcon(HICON hIcon)

{

    if (!m_bEnabled) return FALSE;

 

    m_tnd.uFlags = NIF_ICON;

    m_tnd.hIcon = hIcon;

 

    return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);

}

 

BOOL CSystemTray::SetIcon(LPCTSTR lpszIconName)

{

    HICON hIcon = AfxGetApp()->LoadIcon(lpszIconName);

 

    return SetIcon(hIcon);

}

 

BOOL CSystemTray::SetIcon(UINT nIDResource)

{

    HICON hIcon = AfxGetApp()->LoadIcon(nIDResource);

 

    return SetIcon(hIcon);

}

 

BOOL CSystemTray::SetStandardIcon(LPCTSTR lpIconName)

{

    HICON hIcon = LoadIcon(NULL, lpIconName);

 

    return SetIcon(hIcon);

}

 

BOOL CSystemTray::SetStandardIcon(UINT nIDResource)

{

    HICON hIcon = LoadIcon(NULL, MAKEINTRESOURCE(nIDResource));

 

    return SetIcon(hIcon);

}

 

HICON CSystemTray::GetIcon() const

{

    return (m_bEnabled)? m_tnd.hIcon : NULL;

}

 

BOOL CSystemTray::SetIconList(UINT uFirstIconID, UINT uLastIconID)

{

         if (uFirstIconID > uLastIconID)

        return FALSE;

 

         UINT uIconArraySize = uLastIconID - uFirstIconID + 1;

         const CWinApp * pApp = AfxGetApp();

    ASSERT(pApp != 0);

 

    m_IconList.RemoveAll();

    try {

             for (UINT i = uFirstIconID; i <= uLastIconID; i++)

                       m_IconList.Add(pApp->LoadIcon(i));

    }

    catch (CMemoryException *e)

    {

        e->ReportError();

        e->Delete();

        m_IconList.RemoveAll();

        return FALSE;

    }

 

    return TRUE;

}

 

BOOL CSystemTray::SetIconList(HICON* pHIconList, UINT nNumIcons)

{

    m_IconList.RemoveAll();

 

    try {

             for (UINT i = 0; i <= nNumIcons; i++)

                       m_IconList.Add(pHIconList[i]);

    }

    catch (CMemoryException *e)

    {

        e->ReportError();

        e->Delete();

        m_IconList.RemoveAll();

        return FALSE;

    }

 

    return TRUE;

}

 

BOOL CSystemTray::Animate(UINT nDelayMilliSeconds, int nNumSeconds /*=-1*/)

{

    StopAnimation();

 

    m_nCurrentIcon = 0;

    m_StartTime = COleDateTime::GetCurrentTime();

    m_nAnimationPeriod = nNumSeconds;

    m_hSavedIcon = GetIcon();

 

         // Setup a timer for the animation

         m_uIDTimer = SetTimer(m_nIDEvent, nDelayMilliSeconds, NULL);

 

    return (m_uIDTimer != 0);

}

 

BOOL CSystemTray::StepAnimation()

{

    if (!m_IconList.GetSize())

        return FALSE;

 

    m_nCurrentIcon++;

    if (m_nCurrentIcon >= m_IconList.GetSize())

        m_nCurrentIcon = 0;

 

    return SetIcon(m_IconList[m_nCurrentIcon]);

}

 

BOOL CSystemTray::StopAnimation()

{

    BOOL bResult = FALSE;

 

    if (m_uIDTimer)

             bResult = KillTimer(m_uIDTimer);

    m_uIDTimer = 0;

 

    if (m_hSavedIcon)

        SetIcon(m_hSavedIcon);

    m_hSavedIcon = NULL;

 

    return bResult;

}

 

/////////////////////////////////////////////////////////////////////////////

// CSystemTray tooltip text manipulation

 

BOOL CSystemTray::SetTooltipText(LPCTSTR pszTip)

{

    if (!m_bEnabled) return FALSE;

 

    m_tnd.uFlags = NIF_TIP;

    _tcscpy(m_tnd.szTip, pszTip);

 

    return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);

}

 

BOOL CSystemTray::SetTooltipText(UINT nID)

{

    CString strText;

    VERIFY(strText.LoadString(nID));

 

    return SetTooltipText(strText);

}

 

CString CSystemTray::GetTooltipText() const

{

    CString strText;

    if (m_bEnabled)

        strText = m_tnd.szTip;

 

    return strText;

}

 

/////////////////////////////////////////////////////////////////////////////

// CSystemTray notification window stuff

 

BOOL CSystemTray::SetNotificationWnd(CWnd* pWnd)

{

    if (!m_bEnabled) return FALSE;

 

    // Make sure Notification window is valid

    ASSERT(pWnd && ::IsWindow(pWnd->GetSafeHwnd()));

 

    m_tnd.hWnd = pWnd->GetSafeHwnd();

    m_tnd.uFlags = 0;

 

    return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);

}

 

CWnd* CSystemTray::GetNotificationWnd() const

{

    return CWnd::FromHandle(m_tnd.hWnd);

}

 

/////////////////////////////////////////////////////////////////////////////

// CSystemTray menu manipulation

 

BOOL CSystemTray::SetMenuDefaultItem(UINT uItem, BOOL bByPos)

{

    if ((m_DefaultMenuItemID == uItem) && (m_DefaultMenuItemByPos == bByPos))

        return TRUE;

 

    m_DefaultMenuItemID = uItem;

    m_DefaultMenuItemByPos = bByPos;  

 

    CMenu menu, *pSubMenu;

 

    if (!menu.LoadMenu(m_tnd.uID)) return FALSE;

    if (!(pSubMenu = menu.GetSubMenu(0))) return FALSE;

 

    ::SetMenuDefaultItem(pSubMenu->m_hMenu, m_DefaultMenuItemID, m_DefaultMenuItemByPos);

 

    return TRUE;

}

 

void CSystemTray::GetMenuDefaultItem(UINT& uItem, BOOL& bByPos)

{

    uItem = m_DefaultMenuItemID;

    bByPos = m_DefaultMenuItemByPos;

}

 

/////////////////////////////////////////////////////////////////////////////

// CSystemTray message handlers

 

BEGIN_MESSAGE_MAP(CSystemTray, CWnd)

         //{{AFX_MSG_MAP(CSystemTray)

         ON_WM_TIMER()

         //}}AFX_MSG_MAP

END_MESSAGE_MAP()

 

void CSystemTray::OnTimer(UINT nIDEvent)

{

    ASSERT(nIDEvent == m_nIDEvent);

 

    COleDateTime CurrentTime = COleDateTime::GetCurrentTime();

    COleDateTimeSpan period = CurrentTime - m_StartTime;

    if (m_nAnimationPeriod > 0 && m_nAnimationPeriod < period.GetTotalSeconds())

    {

        StopAnimation();

        return;

    }

 

    StepAnimation();

}

 

LRESULT CSystemTray::OnTrayNotification(UINT wParam, LONG lParam)

{

    //Return quickly if its not for this tray icon

    if (wParam != m_tnd.uID)

        return 0L;

 

    CMenu menu, *pSubMenu;

    CWnd* pTarget = AfxGetMainWnd();

 

    // Clicking with right button brings up a context menu

    if (LOWORD(lParam) == WM_RBUTTONUP)

    {   

        if (!menu.LoadMenu(m_tnd.uID)) return 0;

        if (!(pSubMenu = menu.GetSubMenu(0))) return 0;

 

        // Make chosen menu item the default (bold font)

        ::SetMenuDefaultItem(pSubMenu->m_hMenu, m_DefaultMenuItemID, m_DefaultMenuItemByPos);

 

        // Display and track the popup menu

        CPoint pos;

        GetCursorPos(&pos);

 

        pTarget->SetForegroundWindow(); 

        ::TrackPopupMenu(pSubMenu->m_hMenu, 0, pos.x, pos.y, 0,

                         pTarget->GetSafeHwnd(), NULL);

 

        // BUGFIX: See "PRB: Menus for Notification Icons Don't Work Correctly"

        pTarget->PostMessage(WM_NULL, 0, 0);

 

        menu.DestroyMenu();

    }

    else if (LOWORD(lParam) == WM_LBUTTONDBLCLK)

    {

        // double click received, the default action is to execute default menu item

        pTarget->SetForegroundWindow(); 

 

        UINT uItem;

        if (m_DefaultMenuItemByPos)

        {

            if (!menu.LoadMenu(m_tnd.uID)) return 0;

            if (!(pSubMenu = menu.GetSubMenu(0))) return 0;

            uItem = pSubMenu->GetMenuItemID(m_DefaultMenuItemID);

        }

        else

            uItem = m_DefaultMenuItemID;

       

        pTarget->SendMessage(WM_COMMAND, uItem, 0);

 

        menu.DestroyMenu();

    }

 

    return 1;

}

 

LRESULT CSystemTray::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)

{

    if (message == m_tnd.uCallbackMessage)

        return OnTrayNotification(wParam, lParam);

        

         return CWnd::WindowProc(message, wParam, lParam);

}

 

Win32类的头文件SystemTraySDK.h

#include <ShellAPI.h>

 

#pragma once

 

#pragma warning(disable:4786)

#include <time.h>

#include <vector>

using namespace std;

typedef vector<HICON> ICONVECTOR;

 

class CSystemTray

{

public:

    CSystemTray();

    CSystemTray(HINSTANCE hInst, HWND hParent, UINT uCallbackMessage,

              LPCTSTR szTip, HICON icon, UINT uID,

              BOOL bhidden = FALSE,

              LPCTSTR szBalloonTip = NULL, LPCTSTR szBalloonTitle = NULL,

              DWORD dwBalloonIcon = NIIF_NONE, UINT uBalloonTimeout = 10);

    virtual ~CSystemTray();

 

// Operations

public:

    BOOL Enabled() { return m_bEnabled; }

    BOOL Visible() { return !m_bHidden; }

 

    // Create the tray icon

    BOOL Create(HINSTANCE hInst, HWND hParent, UINT uCallbackMessage, LPCTSTR szTip,

                      HICON icon, UINT uID, BOOL bHidden = FALSE,

           LPCTSTR szBalloonTip = NULL, LPCTSTR szBalloonTitle = NULL,

           DWORD dwBalloonIcon = NIIF_NONE, UINT uBalloonTimeout = 10);

 

    // Change or retrieve the Tooltip text

    BOOL   SetTooltipText(LPCTSTR pszTooltipText);

    BOOL   SetTooltipText(UINT nID);

    LPTSTR GetTooltipText() const;

 

    // Change or retrieve the icon displayed

    BOOL  SetIcon(HICON hIcon);

    BOOL  SetIcon(LPCTSTR lpszIconName);

    BOOL  SetIcon(UINT nIDResource);

    BOOL  SetStandardIcon(LPCTSTR lpIconName);

    BOOL  SetStandardIcon(UINT nIDResource);

    HICON GetIcon() const;

 

    void  SetFocus();

    BOOL  HideIcon();

    BOOL  ShowIcon();

    BOOL  AddIcon();

    BOOL  RemoveIcon();

    BOOL  MoveToRight();

 

    BOOL ShowBalloon(LPCTSTR szText, LPCTSTR szTitle = NULL,

                     DWORD dwIcon = NIIF_NONE, UINT uTimeout = 10);

 

    // For icon animation

    BOOL  SetIconList(UINT uFirstIconID, UINT uLastIconID);

    BOOL  SetIconList(HICON* pHIconList, UINT nNumIcons);

    BOOL  Animate(UINT nDelayMilliSeconds, int nNumSeconds = -1);

    BOOL  StepAnimation();

    BOOL  StopAnimation();

 

    // Change menu default item

    void  GetMenuDefaultItem(UINT& uItem, BOOL& bByPos);

    BOOL  SetMenuDefaultItem(UINT uItem, BOOL bByPos);

 

    // Change or retrieve the window to send icon notification messages to

    BOOL  SetNotificationWnd(HWND hNotifyWnd);

    HWND  GetNotificationWnd() const;

 

    // Change or retrieve the window to send menu commands to

    BOOL  SetTargetWnd(HWND hTargetWnd);

    HWND  GetTargetWnd() const;

 

    // Change or retrieve  notification messages sent to the window

    BOOL  SetCallbackMessage(UINT uCallbackMessage);

    UINT  GetCallbackMessage() const;

 

    HWND  GetSafeHwnd() const  { return (this)? m_hWnd : NULL; }

    UINT_PTR GetTimerID() const   { return m_nTimerID; }

 

         // Static functions

public:

    static void MinimiseToTray(HWND hWnd);

    static void MaximiseFromTray(HWND hWnd);

 

public:

    // Default handler for tray notification message

    virtual LRESULT OnTrayNotification(WPARAM uID, LPARAM lEvent);

 

// Static callback functions and data

public:

    static LRESULT PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

    static CSystemTray* m_pThis;

 

// Implementation

protected:

    void Initialise();

    void InstallIconPending();

    ATOM RegisterClass(HINSTANCE hInstance);

 

    virtual void CustomizeMenu(HMENU) {}

 

// Implementation

protected:

    NOTIFYICONDATA  m_tnd;

    HINSTANCE       m_hInstance;

    HWND            m_hWnd;

         HWND            m_hTargetWnd;       // Window that menu commands are sent

 

    BOOL            m_bEnabled;         // does O/S support tray icon?

    BOOL            m_bHidden;          // Has the icon been hidden?

    BOOL            m_bRemoved;         // Has the icon been removed?

    BOOL            m_bShowIconPending; // Show the icon once tha taskbar has been created

    BOOL            m_bWin2K;           // Use new W2K features?

 

    ICONVECTOR      m_IconList;

    UINT_PTR        m_uIDTimer;

    int                                m_nCurrentIcon;

    time_t                        m_StartTime;

    int                                m_nAnimationPeriod;

    HICON                      m_hSavedIcon;

    UINT                          m_DefaultMenuItemID;

    BOOL                        m_DefaultMenuItemByPos;

         UINT                          m_uCreationFlags;

 

// Static data

protected:

    static BOOL RemoveTaskbarIcon(HWND hWnd);

 

    static const UINT_PTR m_nTimerID;

    static UINT  m_nMaxTooltipLength;

    static const UINT m_nTaskbarCreatedMsg;

    static HWND  m_hWndInvisible;

 

    static BOOL GetW2K();

 

    static void GetTrayWndRect(LPRECT lprect);

    static BOOL GetDoWndAnimation();

 

// message map functions

public:

         LRESULT OnTimer(UINT nIDEvent);

    LRESULT OnTaskbarCreated(WPARAM wParam, LPARAM lParam);

 

         LRESULT OnSettingChange(UINT uFlags, LPCTSTR lpszSection);

 

};

 

Win32类实现文件SystemTraySDK.cpp

#include "stdafx.h"

#include "SystemTraySDK.h"

#include <assert.h>

 

#define ASSERT assert

 

#define TRAYICON_CLASS _T("TrayIconClass")

 

/*全局变量*/

CSystemTray* CSystemTray::m_pThis = NULL;

const UINT CSystemTray::m_nTimerID    = 4567;

UINT CSystemTray::m_nMaxTooltipLength  = 64;    

const UINT CSystemTray::m_nTaskbarCreatedMsg = ::RegisterWindowMessage(_T("TaskbarCreated"));

HWND  CSystemTray::m_hWndInvisible;

 

/* ************************************

* CSystemTray::CSystemTray()

功能初始化,调用Initialise,暂不创建图标

**************************************/

CSystemTray::CSystemTray()

{

         Initialise();

}

 

/* ************************************

* CSystemTray::CSystemTray(...)

功能初始化,调用Initialise,直接创建图标

**************************************/

CSystemTray::CSystemTray(HINSTANCE hInst,         //应用程序句柄

                            HWND hParent,             // 用于接收图标的notifications

                            UINT uCallbackMessage,     // 发送给父亲窗口的回调用消息

                            LPCTSTR szToolTip,                // tray icon tooltip

                            HICON icon,                    // 图标的句柄

                            UINT uID,                          // 图标的标识符

                            BOOL bHidden,             // 创建后是否隐藏=FALSE

                            LPCTSTR szBalloonTip,                  // 气泡

                            LPCTSTR szBalloonTitle,       // 气泡的标题

                            DWORD dwBalloonIcon,    // 气泡的图标

                            UINT uBalloonTimeout)      // 气泡滞留时间

{

         Initialise();

         Create(hInst, hParent, uCallbackMessage, szToolTip, icon, uID, bHidden,

                   szBalloonTip, szBalloonTitle, dwBalloonIcon, uBalloonTimeout);

}

/* ************************************

* void CSystemTray::Initialise()

功能初始化,设置类成员变量等

**************************************/

void CSystemTray::Initialise()

{

         m_pThis = this;

 

         memset(&m_tnd, 0, sizeof(m_tnd));

         m_bEnabled = FALSE;

         m_bHidden  = TRUE;

         m_bRemoved = TRUE;

 

         m_DefaultMenuItemID    = 0;

         m_DefaultMenuItemByPos = TRUE;

 

         m_bShowIconPending = FALSE;

 

         m_uIDTimer   = 0;

         m_hSavedIcon = NULL;

 

         m_hTargetWnd = NULL;

         m_uCreationFlags = 0;

 

         // 系统版本判断

         OSVERSIONINFO os = { sizeof(os) };

         GetVersionEx(&os);

         m_bWin2K = ( VER_PLATFORM_WIN32_NT == os.dwPlatformId && os.dwMajorVersion >= 5 );

}

/* ************************************

* ATOM CSystemTray::RegisterClass(HINSTANCE hInstance)

功能注册主窗口类

**************************************/

ATOM CSystemTray::RegisterClass(HINSTANCE hInstance)

{

         WNDCLASSEX wcex;

 

         wcex.cbSize = sizeof(WNDCLASSEX);

 

         wcex.style                         = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;

         wcex.lpfnWndProc        = (WNDPROC)WindowProc;

         wcex.cbClsExtra              = 0;

         wcex.cbWndExtra                   = 0;

         wcex.hInstance               = hInstance;

         wcex.hIcon                       = 0;

         wcex.hCursor                   = 0;

         wcex.hbrBackground    = 0;

         wcex.lpszMenuName   = 0;

         wcex.lpszClassName     = TRAYICON_CLASS;

         wcex.hIconSm                 = 0;

 

         return RegisterClassEx(&wcex);

}

/* ************************************

* BOOL CSystemTray::Create(...)

功能创建通知图标窗口

**************************************/

BOOL CSystemTray::Create(HINSTANCE hInst, HWND hParent, UINT uCallbackMessage,

                            LPCTSTR szToolTip, HICON icon, UINT uID,

                            BOOL bHidden /*=FALSE*/,

                            LPCTSTR szBalloonTip,

                            LPCTSTR szBalloonTitle , 

                            DWORD dwBalloonIcon,

                            UINT uBalloonTimeout)

{

         // 判断系统版本 >= Windows 95

         m_bEnabled = (GetVersion() & 0xff) >= 4;

         if (!m_bEnabled)

         {

                   ASSERT(FALSE);

                   return FALSE;

         }

 

         m_nMaxTooltipLength = _countof(m_tnd.szTip);

         // 判断消息

         ASSERT(uCallbackMessage >= WM_APP);

         // 防止溢出

         ASSERT(_tcslen(szToolTip) <= m_nMaxTooltipLength);

 

         m_hInstance = hInst;

         RegisterClass(hInst);

 

         // 创建窗口

         m_hWnd = ::CreateWindow(TRAYICON_CLASS, _T(""), WS_POPUP,

                   CW_USEDEFAULT,CW_USEDEFAULT,

                   CW_USEDEFAULT,CW_USEDEFAULT,

                   NULL, 0,

                   hInst, 0);

 

         // 填充 NOTIFYICONDATA 结构

         m_tnd.cbSize = sizeof(NOTIFYICONDATA);

         m_tnd.hWnd   = (hParent)? hParent : m_hWnd;

         m_tnd.uID    = uID;

         m_tnd.hIcon  = icon;

         m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;

         m_tnd.uCallbackMessage = uCallbackMessage;

 

         wcsncpy(m_tnd.szTip, szToolTip, m_nMaxTooltipLength);

 

         // 判断

         if (m_bWin2K && szBalloonTip)

         {

                   ASSERT(lstrlen(szBalloonTip) < 256);

                   if (szBalloonTitle)

                   {

                            ASSERT(lstrlen(szBalloonTitle) < 64);

                   }

 

                   ASSERT(NIIF_NONE == dwBalloonIcon    || NIIF_INFO == dwBalloonIcon ||

                            NIIF_WARNING == dwBalloonIcon || NIIF_ERROR == dwBalloonIcon);

 

                   ASSERT(uBalloonTimeout >= 10 && uBalloonTimeout <= 30);

 

                   m_tnd.uFlags |= NIF_INFO;                                   // 气泡

 

                   _tcsncpy(m_tnd.szInfo, szBalloonTip, 255);

                   if (szBalloonTitle)

                            _tcsncpy(m_tnd.szInfoTitle, szBalloonTitle, 63);

                   else

                            m_tnd.szInfoTitle[0] = _T('/0');

                   m_tnd.uTimeout    = uBalloonTimeout * 1000; // ms

                   m_tnd.dwInfoFlags = dwBalloonIcon;

         }

 

         m_bHidden = bHidden;

         m_hTargetWnd = m_tnd.hWnd;

 

         if (m_bWin2K && m_bHidden)

         {

                   m_tnd.uFlags = NIF_STATE;

                   m_tnd.dwState = NIS_HIDDEN;

                   m_tnd.dwStateMask = NIS_HIDDEN;

         }

 

         m_uCreationFlags = m_tnd.uFlags;  

 

         BOOL bResult = TRUE;

         if (!m_bHidden || m_bWin2K)

         {

                   // 以NIM_ADD为参数调用Shell_NotifyIcon,增加通知区域图标

                   bResult = Shell_NotifyIcon(NIM_ADD, &m_tnd);

                   m_bShowIconPending = m_bHidden = m_bRemoved = !bResult;

         }

 

         if (m_bWin2K && szBalloonTip)

         {

                   m_tnd.szInfo[0] = _T('/0');

         }

 

         return bResult;

}

 

/* ************************************

* CSystemTray::~CSystemTray()

**************************************/

CSystemTray::~CSystemTray()

{

         RemoveIcon();

         m_IconList.clear();

         if (m_hWnd)

                   ::DestroyWindow(m_hWnd);

}

 

/* ************************************

* void CSystemTray::SetFocus()

功能设置焦点

**************************************/

void CSystemTray::SetFocus()

{

         Shell_NotifyIcon ( NIM_SETFOCUS, &m_tnd );

}

 

/* ************************************

* BOOL CSystemTray::MoveToRight()

* BOOL CSystemTray::AddIcon()

* BOOL CSystemTray::RemoveIcon()

* BOOL CSystemTray::HideIcon()

* BOOL CSystemTray::ShowIcon()

* BOOL CSystemTray::SetIcon(HICON hIcon)

* BOOL CSystemTray::SetIcon(HICON hIcon)

* BOOL CSystemTray::SetIcon(UINT nIDResource)

* BOOL CSystemTray::SetStandardIcon(LPCTSTR lpIconName)

* BOOL CSystemTray::SetStandardIcon(UINT nIDResource)

* HICON CSystemTray::GetIcon()

* BOOL CSystemTray::SetIconList(UINT uFirstIconID, UINT uLastIconID)

* BOOL CSystemTray::SetIconList(HICON* pHIconList, UINT nNumIcons)

功能为通知区域图标ICON相关处理

**************************************/

BOOL CSystemTray::MoveToRight()

{

         RemoveIcon();

         return AddIcon();

}

BOOL CSystemTray::AddIcon()

{

         if (!m_bRemoved)

                   RemoveIcon();

 

         if (m_bEnabled)

         {

                   m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;

                   if (!Shell_NotifyIcon(NIM_ADD, &m_tnd))

                            m_bShowIconPending = TRUE;

                   else

                            m_bRemoved = m_bHidden = FALSE;

         }

         return (m_bRemoved == FALSE);

}

BOOL CSystemTray::RemoveIcon()

{

         m_bShowIconPending = FALSE;

 

         if (!m_bEnabled || m_bRemoved)

                   return TRUE;

 

         m_tnd.uFlags = 0;

         if (Shell_NotifyIcon(NIM_DELETE, &m_tnd))

                   m_bRemoved = m_bHidden = TRUE;

 

         return (m_bRemoved == TRUE);

}

 

BOOL CSystemTray::HideIcon()

{

         if (!m_bEnabled || m_bRemoved || m_bHidden)

                   return TRUE;

         if (m_bWin2K)

         {

                   m_tnd.uFlags = NIF_STATE;

                   m_tnd.dwState = NIS_HIDDEN;

                   m_tnd.dwStateMask = NIS_HIDDEN;

 

                   m_bHidden = Shell_NotifyIcon( NIM_MODIFY, &m_tnd);

         }

         else

                   RemoveIcon();

 

         return (m_bHidden == TRUE);

}

 

BOOL CSystemTray::ShowIcon()

{

         if (m_bRemoved)

                   return AddIcon();

 

         if (!m_bHidden)

                   return TRUE;

         if (m_bWin2K)

         {

                   m_tnd.uFlags = NIF_STATE;

                   m_tnd.dwState = 0;

                   m_tnd.dwStateMask = NIS_HIDDEN;

                   Shell_NotifyIcon ( NIM_MODIFY, &m_tnd );

         }

         else

                   AddIcon();

 

         return (m_bHidden == FALSE);

}

 

BOOL CSystemTray::SetIcon(HICON hIcon)

{

         if (!m_bEnabled)

                   return FALSE;

 

         m_tnd.uFlags = NIF_ICON;

         m_tnd.hIcon = hIcon;

 

         if (m_bHidden)

                   return TRUE;

         else

                   return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);

}

 

BOOL CSystemTray::SetIcon(LPCTSTR lpszIconName)

{

         HICON hIcon = (HICON) ::LoadImage(m_hInstance,

                   lpszIconName,

                   IMAGE_ICON,

                   0, 0,

                   LR_LOADFROMFILE);

 

         if (!hIcon)

                   return FALSE;

         BOOL returnCode = SetIcon(hIcon);

         ::DestroyIcon(hIcon);

         return returnCode;

}

 

BOOL CSystemTray::SetIcon(UINT nIDResource)

{

         HICON hIcon = (HICON) ::LoadImage(m_hInstance,

                   MAKEINTRESOURCE(nIDResource),

                   IMAGE_ICON,

                   0, 0,

                   LR_DEFAULTCOLOR);

 

         BOOL returnCode = SetIcon(hIcon);

         ::DestroyIcon(hIcon);

         return returnCode;

}

 

BOOL CSystemTray::SetStandardIcon(LPCTSTR lpIconName)

{

         HICON hIcon = ::LoadIcon(NULL, lpIconName);

 

         return SetIcon(hIcon);

}

 

BOOL CSystemTray::SetStandardIcon(UINT nIDResource)

{

         HICON hIcon = ::LoadIcon(NULL, MAKEINTRESOURCE(nIDResource));

 

         return SetIcon(hIcon);

}

 

HICON CSystemTray::GetIcon() const

{

         return (m_bEnabled)? m_tnd.hIcon : NULL;

}

 

BOOL CSystemTray::SetIconList(UINT uFirstIconID, UINT uLastIconID)

{

         if (uFirstIconID > uLastIconID)

                   return FALSE;

 

         UINT uIconArraySize = uLastIconID - uFirstIconID + 1;

 

         m_IconList.clear();

         try

         {

                   for (UINT i = uFirstIconID; i <= uLastIconID; i++)

                            m_IconList.push_back(::LoadIcon(m_hInstance, MAKEINTRESOURCE(i)));

         }

         catch (...)

         {

                   m_IconList.clear();

                   return FALSE;

         }

 

         return TRUE;

}

 

BOOL CSystemTray::SetIconList(HICON* pHIconList, UINT nNumIcons)

{

         m_IconList.clear();

 

         try {

                   for (UINT i = 0; i <= nNumIcons; i++)

                            m_IconList.push_back(pHIconList[i]);

         }

         catch (...)

         {

                   m_IconList.clear();

                   return FALSE;

         }

 

         return TRUE;

}

/* ************************************

*BOOL CSystemTray::Animate(UINT nDelayMilliSeconds, int nNumSeconds )

功能使图标动作

**************************************/

BOOL CSystemTray::Animate(UINT nDelayMilliSeconds, int nNumSeconds /*=-1*/)

{

         if (m_IconList.empty())

                   return FALSE;

 

         StopAnimation();

 

         m_nCurrentIcon = 0;

         time(&m_StartTime);

         m_nAnimationPeriod = nNumSeconds;

         m_hSavedIcon = GetIcon();

 

         // 计时器,注意实例中对计时器消息的处理

         m_uIDTimer = ::SetTimer(m_hWnd, m_nTimerID, nDelayMilliSeconds, NULL);

         return (m_uIDTimer != 0);

}

/* ************************************

*BOOL CSystemTray::StepAnimation()

功能使图标动作

**************************************/

BOOL CSystemTray::StepAnimation()

{

         if (!m_IconList.size())

                   return FALSE;

 

         m_nCurrentIcon++;

         if (m_nCurrentIcon >= m_IconList.size())

                   m_nCurrentIcon = 0;

 

         return SetIcon(m_IconList[m_nCurrentIcon]);

}

/* ************************************

*BOOL CSystemTray::StopAnimation()

功能停止图标动作

**************************************/

BOOL CSystemTray::StopAnimation()

{

         BOOL bResult = FALSE;

 

         if (m_uIDTimer)

                   bResult = ::KillTimer(m_hWnd, m_uIDTimer);

         m_uIDTimer = 0;

 

         if (m_hSavedIcon)

                   SetIcon(m_hSavedIcon);

         m_hSavedIcon = NULL;

 

         return bResult;

}

 

/* ************************************

*BOOL CSystemTray::SetTooltipText(LPCTSTR pszTip)

*BOOL CSystemTray::SetTooltipText(UINT nID)

*LPTSTR CSystemTray::GetTooltipText()

功能设置(获取)图标ToolTip

**************************************/

BOOL CSystemTray::SetTooltipText(LPCTSTR pszTip)

{

         ASSERT(_tcslen(pszTip) < m_nMaxTooltipLength);

 

         if (!m_bEnabled)

                   return FALSE;

 

         m_tnd.uFlags = NIF_TIP;

         _tcsncpy(m_tnd.szTip, pszTip, m_nMaxTooltipLength-1);

 

         if (m_bHidden)

                   return TRUE;

         else

                   return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);

}

 

BOOL CSystemTray::SetTooltipText(UINT nID)

{

         TCHAR strBuffer[1024];

         ASSERT(1024 >= m_nMaxTooltipLength);

 

         if (!LoadString(m_hInstance, nID, strBuffer, m_nMaxTooltipLength-1))

                   return FALSE;

 

         return SetTooltipText(strBuffer);

}

 

LPTSTR CSystemTray::GetTooltipText() const

{

         if (!m_bEnabled)

                   return FALSE;

 

         static TCHAR strBuffer[1024];

         ASSERT(1024 >= m_nMaxTooltipLength);

 

         wcsncpy(strBuffer, m_tnd.szTip, m_nMaxTooltipLength-1);

         return strBuffer;

}

 

/* ************************************

* CSystemTray::ShowBalloon

功能显示气泡

**************************************/

BOOL CSystemTray::ShowBalloon(LPCTSTR szText,

                                                                   LPCTSTR szTitle,

                                                                   DWORD   dwIcon/*=NIIF_NONE*/,

                                                                   UINT    uTimeout/*=10*/ )

{

         // Win2k以上

         if (!m_bWin2K)

                   return FALSE;

         // 防止溢出

         ASSERT(lstrlen(szText) < 256);

 

         // 防止Title溢出

         if (szTitle)

         {

                   ASSERT(lstrlen(szTitle) < 64);

         }

         // 判断Flag

         ASSERT(NIIF_NONE == dwIcon    || NIIF_INFO == dwIcon ||

                   NIIF_WARNING == dwIcon || NIIF_ERROR == dwIcon);

 

         // 判断Timeout

         ASSERT(uTimeout >= 10 && uTimeout <= 30);

         // 设置 NOTIFYICONDATA结构

         m_tnd.uFlags = NIF_INFO;                   // 显示气泡信息

         _tcsncpy(m_tnd.szInfo, szText, 256);

         if (szTitle)

                   _tcsncpy(m_tnd.szInfoTitle, szTitle, 64);

         else

                   m_tnd.szInfoTitle[0] = _T('/0');

         m_tnd.dwInfoFlags = dwIcon;

         m_tnd.uTimeout = uTimeout * 1000;   // ms

         // 以NIM_MODIFY 为参数,调用Shell_NotifyIcon

         BOOL bSuccess = Shell_NotifyIcon (NIM_MODIFY, &m_tnd);

 

         // 清零

         m_tnd.szInfo[0] = _T('/0');

         return bSuccess;

}

 

/* ************************************

* BOOL CSystemTray::SetNotificationWnd(HWND hNotifyWnd)

* HWND CSystemTray::GetNotificationWnd()

* BOOL CSystemTray::SetTargetWnd(HWND hTargetWnd)

* BOOL CSystemTray::SetCallbackMessage(UINT uCallbackMessage)

* UINT CSystemTray::GetCallbackMessage()

* BOOL CSystemTray::SetMenuDefaultItem(UINT uItem, BOOL bByPos)

* void CSystemTray::GetMenuDefaultItem(UINT& uItem, BOOL& bByPos)

功能处理与主窗口(接收图标发送的消息的窗口)

消息、菜单等相关的内容

**************************************/

BOOL CSystemTray::SetNotificationWnd(HWND hNotifyWnd)

{

         if (!m_bEnabled)

                   return FALSE;

 

         if (!hNotifyWnd || !::IsWindow(hNotifyWnd))

         {

                   ASSERT(FALSE);

                   return FALSE;

         }

 

         m_tnd.hWnd = hNotifyWnd;

         m_tnd.uFlags = 0;

 

         if (m_bHidden)

                   return TRUE;

         else

                   return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);

}

 

HWND CSystemTray::GetNotificationWnd() const

{

         return m_tnd.hWnd;

}

 

BOOL CSystemTray::SetTargetWnd(HWND hTargetWnd)

{

         m_hTargetWnd = hTargetWnd;

         return TRUE;

}

 

HWND CSystemTray::GetTargetWnd() const

{

         if (m_hTargetWnd)

                   return m_hTargetWnd;

         else

                   return m_tnd.hWnd;

}

 

 

BOOL CSystemTray::SetCallbackMessage(UINT uCallbackMessage)

{

         if (!m_bEnabled)

                   return FALSE;

 

         ASSERT(uCallbackMessage >= WM_APP);

 

         m_tnd.uCallbackMessage = uCallbackMessage;

         m_tnd.uFlags = NIF_MESSAGE;

 

         if (m_bHidden)

                   return TRUE;

         else

                   return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);

}

 

UINT CSystemTray::GetCallbackMessage() const

{

         return m_tnd.uCallbackMessage;

}

 

BOOL CSystemTray::SetMenuDefaultItem(UINT uItem, BOOL bByPos)

{

         if ((m_DefaultMenuItemID == uItem) && (m_DefaultMenuItemByPos == bByPos))

                   return TRUE;

 

         m_DefaultMenuItemID = uItem;

         m_DefaultMenuItemByPos = bByPos;  

 

         HMENU hMenu = ::LoadMenu(m_hInstance, MAKEINTRESOURCE(m_tnd.uID));

         if (!hMenu)

                   return FALSE;

 

         HMENU hSubMenu = ::GetSubMenu(hMenu, 0);

         if (!hSubMenu)

         {

                   ::DestroyMenu(hMenu);

                   return FALSE;

         }

 

         ::SetMenuDefaultItem(hSubMenu, m_DefaultMenuItemID, m_DefaultMenuItemByPos);

 

         ::DestroyMenu(hSubMenu);

         ::DestroyMenu(hMenu);

 

         return TRUE;

}

 

void CSystemTray::GetMenuDefaultItem(UINT& uItem, BOOL& bByPos)

{

         uItem = m_DefaultMenuItemID;

         bByPos = m_DefaultMenuItemByPos;

}

 

/////////////////////////////////////////////////////////////////////////////

/* ************************************

* CSystemTray消息处理相关成员函数

**************************************/

/* ************************************

功能处理计时器,图标动画

**************************************/

LRESULT CSystemTray::OnTimer(UINT nIDEvent)

{

         if (nIDEvent != m_uIDTimer)

         {

                   ASSERT(FALSE);

                   return 0L;

         }

 

         time_t CurrentTime;

         time(&CurrentTime);

 

         time_t period = CurrentTime - m_StartTime;

         if (m_nAnimationPeriod > 0 && m_nAnimationPeriod < period)

         {

                   StopAnimation();

                   return 0L;

         }

 

         StepAnimation();

 

         return 0L;

}

 

/* ************************************

* Pending

**************************************/

LRESULT CSystemTray::OnTaskbarCreated(WPARAM wParam, LPARAM lParam)

{

         InstallIconPending();

         return 0L;

}

/* ************************************

* Pending

**************************************/

LRESULT CSystemTray::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)

{

         if (uFlags == SPI_SETWORKAREA)

                   InstallIconPending();

         return 0L;

}

 

/* ************************************

处理Notification

**************************************/

LRESULT CSystemTray::OnTrayNotification(UINT wParam, LONG lParam)

{

         if (wParam != m_tnd.uID)

                   return 0L;

 

         HWND hTargetWnd = GetTargetWnd();

         if (!hTargetWnd)

                   return 0L;

 

         if (LOWORD(lParam) == WM_RBUTTONUP)

         {    

                   HMENU hMenu = ::LoadMenu(m_hInstance, MAKEINTRESOURCE(m_tnd.uID));

                   if (!hMenu)

                            return 0;

 

                   HMENU hSubMenu = ::GetSubMenu(hMenu, 0);

                   if (!hSubMenu)

                   {

                            ::DestroyMenu(hMenu);       

                            return 0;

                   }

 

                   ::SetMenuDefaultItem(hSubMenu, m_DefaultMenuItemID, m_DefaultMenuItemByPos);

 

                   CustomizeMenu(hSubMenu);

 

                   POINT pos;

                   GetCursorPos(&pos);

 

                   ::SetForegroundWindow(m_tnd.hWnd); 

                   ::TrackPopupMenu(hSubMenu, 0, pos.x, pos.y, 0, hTargetWnd, NULL);

 

                   ::PostMessage(m_tnd.hWnd, WM_NULL, 0, 0);

 

                   DestroyMenu(hMenu);

         }

         else if (LOWORD(lParam) == WM_LBUTTONDBLCLK)

         {

                   ::SetForegroundWindow(m_tnd.hWnd); 

 

                   UINT uItem;

                   if (m_DefaultMenuItemByPos)

                   {

                            HMENU hMenu = ::LoadMenu(m_hInstance, MAKEINTRESOURCE(m_tnd.uID));

                            if (!hMenu)

                                     return 0;

 

                            HMENU hSubMenu = ::GetSubMenu(hMenu, 0);

                            if (!hSubMenu)

                                     return 0;

                            uItem = ::GetMenuItemID(hSubMenu, m_DefaultMenuItemID);

 

                            DestroyMenu(hMenu);

                   }

                   else

                            uItem = m_DefaultMenuItemID;

 

                   ::PostMessage(hTargetWnd, WM_COMMAND, uItem, 0);

         }

 

         return 1;

}

 

/* ************************************

功能Tray图标窗口消息处理函数

**************************************/

LRESULT PASCAL CSystemTray::WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

 

         CSystemTray* pTrayIcon = m_pThis;

         if (pTrayIcon->GetSafeHwnd() != hWnd)

                   return ::DefWindowProc(hWnd, message, wParam, lParam);

 

         // Tray被创建此消息必须处理

         if (message == CSystemTray::m_nTaskbarCreatedMsg)

                   return pTrayIcon->OnTaskbarCreated(wParam, lParam);

 

         // 图标动画计时器

         if (message == WM_TIMER && wParam == pTrayIcon->GetTimerID())

                   return pTrayIcon->OnTimer(wParam);

 

         // 设置改变

         if (message == WM_SETTINGCHANGE && wParam == pTrayIcon->GetTimerID())

                   return pTrayIcon->OnSettingChange(wParam, (LPCTSTR) lParam);

 

         // 是否是需要处理的消息

         if (message == pTrayIcon->GetCallbackMessage())

                   return pTrayIcon->OnTrayNotification(wParam, lParam);

 

         return ::DefWindowProc(hWnd, message, wParam, lParam);

}

 

/* ************************************

* void CSystemTray::InstallIconPending()

**************************************/

void CSystemTray::InstallIconPending()

{

         // 是否pending

         if (!m_bShowIconPending || m_bHidden)

                   return;

 

         // 重置标记

         m_tnd.uFlags = m_uCreationFlags;

 

         // 重新创建ICON

         m_bHidden = !Shell_NotifyIcon(NIM_ADD, &m_tnd);

 

         // 仍然下次再处理

         m_bShowIconPending = !m_bHidden;

 

         ASSERT(m_bHidden == FALSE);

}

/* ************************************

查找Tray窗口

最小化到通知区域,从通知区域恢复时需要调用

**************************************/

BOOL CALLBACK FindTrayWnd(HWND hwnd, LPARAM lParam)

{

         TCHAR szClassName[256];

         GetClassName(hwnd, szClassName, 255);

 

         if (_tcscmp(szClassName, _T("TrayNotifyWnd")) == 0)

         {

                   LPRECT lpRect = (LPRECT) lParam;

                   ::GetWindowRect(hwnd, lpRect);

                   return TRUE;

         }

 

         if (_tcscmp(szClassName, _T("TrayClockWClass")) == 0)

         {

                   LPRECT lpRect = (LPRECT) lParam;

                   RECT rectClock;

                   ::GetWindowRect(hwnd, &rectClock);

 

                   if (rectClock.bottom < lpRect->bottom-5)

                            lpRect->top = rectClock.bottom;

                   else

                            lpRect->right = rectClock.left;

                   return FALSE;

         }

 

         return TRUE;

}

 

/* ************************************

*获得Tray的RECT

**************************************/

void CSystemTray::GetTrayWndRect(LPRECT lprect)

{

#define DEFAULT_RECT_WIDTH 150

#define DEFAULT_RECT_HEIGHT 30

 

         HWND hShellTrayWnd = FindWindow(_T("Shell_TrayWnd"), NULL);

         if (hShellTrayWnd)

         {

                   GetWindowRect(hShellTrayWnd, lprect);

                   EnumChildWindows(hShellTrayWnd, FindTrayWnd, (LPARAM)lprect);

                   return;

         }

 

         APPBARDATA appBarData;

         appBarData.cbSize=sizeof(appBarData);

         if (SHAppBarMessage(ABM_GETTASKBARPOS,&appBarData))

         {

 

                   switch(appBarData.uEdge)

                   {

                   case ABE_LEFT:

                   case ABE_RIGHT:

 

                            lprect->top    = appBarData.rc.bottom-100;

                            lprect->bottom = appBarData.rc.bottom-16;

                            lprect->left   = appBarData.rc.left;

                            lprect->right  = appBarData.rc.right;

                            break;

 

                   case ABE_TOP:

                   case ABE_BOTTOM:

 

                            lprect->top    = appBarData.rc.top;

                            lprect->bottom = appBarData.rc.bottom;

                            lprect->left   = appBarData.rc.right-100;

                            lprect->right  = appBarData.rc.right-16;

                            break;

                   }

                   return;

         }

 

         if (hShellTrayWnd)

         {

                   ::GetWindowRect(hShellTrayWnd, lprect);

                   if (lprect->right - lprect->left > DEFAULT_RECT_WIDTH)

                            lprect->left = lprect->right - DEFAULT_RECT_WIDTH;

                   if (lprect->bottom - lprect->top > DEFAULT_RECT_HEIGHT)

                            lprect->top = lprect->bottom - DEFAULT_RECT_HEIGHT;

 

                   return;

         }

 

         SystemParametersInfo(SPI_GETWORKAREA,0,lprect, 0);

         lprect->left = lprect->right - DEFAULT_RECT_WIDTH;

         lprect->top  = lprect->bottom - DEFAULT_RECT_HEIGHT;

}

 

/* ************************************

*       MinAnimate?

**************************************/

BOOL CSystemTray::GetDoWndAnimation()

{

         ANIMATIONINFO ai;

 

         ai.cbSize=sizeof(ai);

         SystemParametersInfo(SPI_GETANIMATION,sizeof(ai),&ai,0);

 

         return ai.iMinAnimate?TRUE:FALSE;

}

/* ************************************

删除任务档图标

**************************************/

BOOL CSystemTray::RemoveTaskbarIcon(HWND hWnd)

{

         if (!::IsWindow(m_hWndInvisible))

         {

                   m_hWndInvisible = CreateWindowEx(0, _T("Static"), _T(""), WS_POPUP,

                            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

                            NULL, 0, NULL, 0);

 

                   if (!m_hWndInvisible)

                            return FALSE;

         }

 

         SetParent(hWnd, m_hWndInvisible);

 

         return TRUE;

}

/* ************************************

将窗口最小化到通知区域

**************************************/

void CSystemTray::MinimiseToTray(HWND hWnd)

{

 

         if (GetDoWndAnimation())

         {

                   RECT rectFrom, rectTo;

 

                   GetWindowRect(hWnd, &rectFrom);

                   GetTrayWndRect(&rectTo);

 

                   DrawAnimatedRects(hWnd, IDANI_CAPTION, &rectFrom, &rectTo);

         }

 

         RemoveTaskbarIcon(hWnd);

         SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) &~ WS_VISIBLE);

 

}

/* ************************************

从通知区域恢复大小

**************************************/

void CSystemTray::MaximiseFromTray(HWND hWnd)

{

 

         if (GetDoWndAnimation())

         {

                   RECT rectTo;

                   ::GetWindowRect(hWnd, &rectTo);

 

                   RECT rectFrom;

                   GetTrayWndRect(&rectFrom);

 

                   ::SetParent(hWnd, NULL);

                   DrawAnimatedRects(hWnd, IDANI_CAPTION, &rectFrom, &rectTo);

         }

         else

                   ::SetParent(hWnd, NULL);

 

         SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) | WS_VISIBLE);

         RedrawWindow(hWnd, NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN | RDW_FRAME |

                   RDW_INVALIDATE | RDW_ERASE);

 

         // 焦点

         if (::IsWindow(m_hWndInvisible))

                   SetActiveWindow(m_hWndInvisible);

         SetActiveWindow(hWnd);

         SetForegroundWindow(hWnd);

}

原创粉丝点击