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

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

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

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

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

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

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

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

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

MFC类的头文件SystemTray.h

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

// SystemTray.h : header file

//

// Written by Chris Maunder ([email protected])

// 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 ([email protected])

// 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;

}

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

*获得TrayRECT

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

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

}

你可能感兴趣的:(windows)