AutoCAD 3DMAX C语言 Pro/E UG JAVA编程 PHP编程 Maya动画 Matlab应用 Android
Photoshop Word Excel flash VB编程 VC编程 Coreldraw SolidWorks A Designer Unity3D
 首页 > VC编程

利用Visual C++实现系统托盘程序

51自学网 2015-08-30 http://www.wanshiok.com

  三、程序代码

////////////////////////////////////////////////CTrayIcon类的头文件;
#ifndef _TRAYICON_H
#define _TRAYICON_H
class CTrayIcon : public CCmdTarget {
 protected:
  DECLARE_DYNAMIC(CTrayIcon)
  NOTIFYICONDATA m_nid; // struct for Shell_NotifyIcon args
 public:
  CTrayIcon(UINT uID);
  ~CTrayIcon();
  // Call this to receive tray notifications
  void SetNotificationWnd(CWnd* pNotifyWnd, UINT uCbMsg);
  BOOL SetIcon(UINT uID); // main variant you want to use
  BOOL SetIcon(HICON hicon, LPCSTR lpTip);
  BOOL SetIcon(LPCTSTR lpResName, LPCSTR lpTip)
  { return SetIcon(lpResName ?
   AfxGetApp()->LoadIcon(lpResName) : NULL, lpTip); }
  BOOL SetStandardIcon(LPCTSTR lpszIconName, LPCSTR lpTip)
  { return SetIcon(::LoadIcon(NULL, lpszIconName), lpTip); }
  virtual LRESULT OnTrayNotification(WPARAM uID, LPARAM lEvent);
};
#endif
///////////////////////////////////////////////////CTrayIcon类的.CPP文件
#include "stdafx.h"
#include "trayicon.h"
#include <afxpriv.h> // for AfxLoadString
IMPLEMENT_DYNAMIC(CTrayIcon, CCmdTarget)
CTrayIcon::CTrayIcon(UINT uID)
{
 memset(&m_nid, 0 , sizeof(m_nid)); // Initialize NOTIFYICONDATA
 m_nid.cbSize = sizeof(m_nid);
 m_nid.uID = uID; // never changes after construction
 AfxLoadString(uID, m_nid.szTip, sizeof(m_nid.szTip));
 // Use resource string as tip if there is one
}

CTrayIcon::~CTrayIcon()
{
 SetIcon(0); // remove icon from system tray
}

void CTrayIcon::SetNotificationWnd(CWnd* pNotifyWnd, UINT uCbMsg)
{
 // Set notification window. It must created already.
 ASSERT(pNotifyWnd==NULL || ::IsWindow(pNotifyWnd->GetSafeHwnd()));
 m_nid.hWnd = pNotifyWnd->GetSafeHwnd();
 ASSERT(uCbMsg==0 || uCbMsg>=WM_USER);
 m_nid.uCallbackMessage = uCbMsg;
}

BOOL CTrayIcon::SetIcon(UINT uID)
{
 // Sets both the icon and tooltip from resource ID ,To remove the icon, call SetIcon(0)
 HICON hicon=NULL;
 if (uID) {
  AfxLoadString(uID, m_nid.szTip, sizeof(m_nid.szTip));
  hicon = AfxGetApp()->LoadIcon(uID);
 }
 return SetIcon(hicon, NULL);
}

BOOL CTrayIcon::SetIcon(HICON hicon, LPCSTR lpTip)
{
 // Common SetIcon for all overloads.
 UINT msg;
 m_nid.uFlags = 0;
 if (hicon) {
  // Set the icon
  msg = m_nid.hIcon ? NIM_MODIFY : NIM_ADD;
  m_nid.hIcon = hicon; // Add or replace icon in system tray
  m_nid.uFlags |= NIF_ICON;
 } else {
  if (m_nid.hIcon==NULL) // remove icon from tray
   return TRUE; // already deleted
  msg = NIM_DELETE;
 }
 if (lpTip) // Use the tip, if any
  strncpy(m_nid.szTip, lpTip, sizeof(m_nid.szTip));
 if (m_nid.szTip[0])
  m_nid.uFlags |= NIF_TIP;
 if (m_nid.uCallbackMessage && m_nid.hWnd) // Use callback if any
  m_nid.uFlags |= NIF_MESSAGE;
  BOOL bRet = Shell_NotifyIcon(msg, &m_nid); // Do it
 if (msg==NIM_DELETE || !bRet)
  m_nid.hIcon = NULL; // failed
 return bRet;
}

LRESULT CTrayIcon::OnTrayNotification(WPARAM wID, LPARAM lEvent)
{
 if (wID!=m_nid.uID || (lEvent!=WM_RBUTTONUP && lEvent!=WM_LBUTTONDBLCLK))
  return 0;
 CMenu menu;//装载上下文菜单;
 if (!menu.LoadMenu(m_nid.uID))
  return 0;
 CMenu* pSubMenu = menu.GetSubMenu(0);
 if (!pSubMenu)
  return 0;
 if (lEvent==WM_RBUTTONUP) {//设置第一个菜单项为默认菜单项目
  ::SetMenuDefaultItem(pSubMenu->m_hMenu, 0, TRUE);
  //将当前菜单作为上下文菜单;
  CPoint mouse;
  GetCursorPos(&mouse);
  ::SetForegroundWindow(m_nid.hWnd);
  ::TrackPopupMenu(pSubMenu->m_hMenu, 0, mouse.x, mouse.y, 0,m_nid.hWnd, NULL);
 } else // double click: execute first menu item
  ::SendMessage(m_nid.hWnd, WM_COMMAND, pSubMenu->GetMenuItemID(0), 0);
 return 1;
}

///////////////////////////////// MainFrm.h : interface of the CMainFrame class
#if !defined(AFX_MAINFRM_H__9ED70A69_C975_4F20_9D4E_B2877E3575D0__INCLUDED_)
#define AFX_MAINFRM_H__9ED70A69_C975_4F20_9D4E_B2877E3575D0__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "trayicon.h"
class CMainFrame : public CFrameWnd
{
 public:
  CMainFrame();
 protected:
  DECLARE_DYNAMIC(CMainFrame)
  // Attributes
 public:
  // Overrides
  // ClassWizard generated virtual function overrides
  //{{AFX_VIRTUAL(CMainFrame)
  //}}AFX_VIRTUAL
  // Implementation
 public:
  virtual ~CMainFrame();
  #ifdef _DEBUG
   virtual void AssertValid() const;
   virtual void Dump(CDumpContext& dc) const;
  #endif
 protected: // control bar embedded members
  CStatusBar m_wndStatusBar;
  CTrayIcon m_trayIcon; // my tray icon
  CEdit m_wndEdit; // to display tray notifications
  int m_iWhichIcon; // which HICON to use
  BOOL m_bShutdown; // OK to terminate TRAYTEST
  BOOL m_bShowTrayNotifications; // display info in main window
  // Generated message map functions
 protected:
  //{{AFX_MSG(CMainFrame)
   afx_msg LRESULT OnTrayNotification(WPARAM wp, LPARAM lp);
   afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
   afx_msg void OnToggleIcon();
   afx_msg void OnViewClear();
   afx_msg void OnViewNotifications();
   afx_msg void OnUpdateViewClear(CCmdUI* pCmdUI);
   afx_msg void OnUpdateViewNotifications(CCmdUI* pCmdUI);
   afx_msg void OnClose();
   afx_msg void OnAppOpen();
   afx_msg void OnAppSuspend();
   // NOTE - the ClassWizard will add and remove member functions here.
   // DO NOT EDIT what you see in these blocks of generated code!
  //}}AFX_MSG
 DECLARE_MESSAGE_MAP()
};

///////////////////////////////////////////////CMainFrm.cpp
#include "stdafx.h"
#include "TrayTest.h"
#include "MainFrm.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMainFrame
// Message ID used for tray notifications
#define WM_MY_TRAY_NOTIFICATION WM_USER+0

IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
 // NOTE - the ClassWizard will add and remove mapping macros here.
 // DO NOT EDIT what you see in these blocks of generated code !
 ON_MESSAGE(WM_MY_TRAY_NOTIFICATION, OnTrayNotification)
 ON_WM_CREATE()
 ON_COMMAND(ID_VIEW_CLEAR, OnViewClear)
 ON_COMMAND(ID_TOGGLE_ICON, OnToggleIcon)
 ON_COMMAND(ID_VIEW_NOTIFICATIONS, OnViewNotifications)
 ON_UPDATE_COMMAND_UI(ID_VIEW_CLEAR, OnUpdateViewClear)
 ON_UPDATE_COMMAND_UI(ID_VIEW_NOTIFICATIONS, OnUpdateViewNotifications)
 ON_WM_CLOSE()
 ON_COMMAND(ID_APP_OPEN, OnAppOpen)
 ON_COMMAND(ID_APP_SUSPEND, OnAppSuspend)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

static UINT indicators[] =
{
 ID_SEPARATOR, // status line indicator
 ID_INDICATOR_CAPS,
 ID_INDICATOR_NUM,
 ID_INDICATOR_SCRL,
};

/////////////////////////////////////////////////////////////////////////////
// CMainFrame construction/destruction

CMainFrame::CMainFrame() : m_trayIcon(IDR_TRAYICON)
{
 // TODO: add member initialization code here
 m_bShowTrayNotifications = TRUE;//zxn
 m_bShutdown = FALSE;//zxn
}

CMainFrame::~CMainFrame()
{}

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
 if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
  return -1;

 if (!m_wndStatusBar.Create(this) ||!m_wndStatusBar.SetIndicators(indicators,
   sizeof(indicators)/sizeof(UINT)))
 {
  TRACE0("Failed to create status bar/n");
  return -1; // fail to create
 }

 // Create child edit control for displaying messages
 CRect rc;
 if (!m_wndEdit.Create(
  WS_VISIBLE|WS_CHILD|WS_VSCROLL|ES_MULTILINE|ES_READONLY, rc, this,
   AFX_IDW_PANE_FIRST))
  return -1;
  // Set up tray icon
 m_trayIcon.SetNotificationWnd(this, WM_MY_TRAY_NOTIFICATION);
 m_iWhichIcon = 1;
 m_trayIcon.SetIcon(IDI_MYICON);
 return 0;
}

//////////////////
// Close window. Unless we are shutting down, just hide it.
void CMainFrame::OnClose()
{
 if (m_bShutdown)
  CFrameWnd::OnClose();
 else
  ShowWindow(SW_HIDE);
}
//////////////////// Handle notification from tray icon: display a message.
LRESULT CMainFrame::OnTrayNotification(WPARAM uID, LPARAM lEvent)
{
 if (m_bShowTrayNotifications) {
  static LPCSTR MouseMessages[] = { "WM_MOUSEMOVE",
    "WM_LBUTTONDOWN", "WM_LBUTTONUP", "WM_LBUTTONDBLCLK",
    "WM_RBUTTONDOWN", "WM_RBUTTONUP", "WM_RBUTTONDBLCLK",
    "WM_MBUTTONDOWN","WM_MBUTTONUP","WM_MBUTTONDBLCLK" };
  CString s;
  s.Format("托盘通知消息: ID=%d, lEvent=0x%04x %s/r/n",
   uID, lEvent, WM_MOUSEFIRST<=lEvent && lEvent<=WM_MOUSELAST ?
   MouseMessages[lEvent-WM_MOUSEFIRST] : "(未知消息)");

  m_wndEdit.SetSel(-1, -1); // end of edit text
  m_wndEdit.ReplaceSel(s); // append string..
  m_wndEdit.SendMessage(EM_SCROLLCARET); // ..and make visible
 }
 // let tray icon do default stuff
 return m_trayIcon.OnTrayNotification(uID, lEvent);
}

////////////////////////////////////////////////////////////////
// Command handlers below.
//
void CMainFrame::OnViewClear()
{
 m_wndEdit.SetWindowText("");
}

void CMainFrame::OnUpdateViewClear(CCmdUI* pCmdUI)
{
 pCmdUI->Enable(m_wndEdit.GetLineCount() > 1 || m_wndEdit.LineLength() > 0);
}

void CMainFrame::OnToggleIcon()
{
 m_iWhichIcon=!m_iWhichIcon;
 m_trayIcon.SetIcon(m_iWhichIcon ? IDI_MYICON : IDI_MYICON2);
}

void CMainFrame::OnViewNotifications()
{
 m_bShowTrayNotifications = !m_bShowTrayNotifications;
}

void CMainFrame::OnUpdateViewNotifications(CCmdUI* pCmdUI)
{
 pCmdUI->SetCheck(m_bShowTrayNotifications);
}

void CMainFrame::OnAppOpen()
{
 ShowWindow(SW_NORMAL);
 SetForegroundWindow();
}

void CMainFrame::OnAppSuspend()
{
 m_bShutdown = TRUE; // really exit
 SendMessage(WM_CLOSE);
}

/////////////////////////////////////////////////////////////////////////////
// CMainFrame diagnostics

#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
 CFrameWnd::AssertValid();
}

void CMainFrame::Dump(CDumpContext& dc) const
{
 CFrameWnd::Dump(dc);
}

#endif //_DEBUG
///////////////////////////////////////////////////////////////
BOOL CMyApp::InitInstance()
{
 //在应用程序初始化函数中将程序的主框架隐藏起来;
 #ifdef _AFXDLL
  Enable3dControls(); // Call this when using MFC in a shared DLL
 #else
  Enable3dControlsStatic(); // Call this when linking to MFC statically
 #endif
 SetRegistryKey(_T("Local AppWizard-Generated Applications"));
 CMainFrame* pFrame = new CMainFrame;
 m_pMainWnd = pFrame;
 pFrame->LoadFrame(IDR_MAINFRAME,
 WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, NULL);
 pFrame->ShowWindow(SW_HIDE);
 pFrame->UpdateWindow();
 return TRUE;
}

  四、小结

  托盘程序的信息提示通常是将鼠标光标移到托盘图标上之后,Windows会发送消息给托盘程序,从而显示提示信息--Tooltip。但在Windows XP中我们还看到有些系统托盘程序是自动显示ToolTips信息的,也就是说不用将鼠标光标移到托盘图标上便可显示ToolTips,此类新式的信息提示一般称为气球提示,它是由你的程序来控制显示。气球提示为托盘程序提供了一种非打扰式的方法通知用户发生了某件事情。但是如何让气球提示显示出来呢?其实所有的托盘图标行为都是通过一个单纯的API函数Shell_NotifyIcon来操作的。你可以利用这个函数的参数NOTIFYICONDATA结构,这个结构来告诉Windows你想要做什么。下面是这个结构的定义的最新版本(For IE5.0+),其中已经加入了新的成员:

typedef struct _NOTIFYICONDATA {
 DWORD cbSize;
 HWND hWnd;
 UINT uID;
 UINT uFlags;
 UINT uCallbackMessage;
 HICON hIcon;
 #if (_WIN32_IE < 0x0500)
  WCHAR szTip[64];
 #else
  WCHAR szTip[128];
 #endif
 #if (_WIN32_IE >= 0x0500)
  DWORD dwState;
  DWORD dwStateMask;
  WCHAR szInfo[256];
  union {
   UINT uTimeout;
   UINT uVersion;
  } DUMMYUNIONNAME;
  WCHAR szInfoTitle[64];
  DWORD dwInfoFlags;
 #endif
} NOTIFYICONDATA, *PNOTIFYICONDATA;

  在NOTIFYICONDATA.uFlags中的标志之一是NIF_TIP,用它来设置传统的信息提示,即鼠标要移动到图标上。新的标志NIF_INFO(由于_WIN32_IE >= 0x0500条件定义,因此在编译时,请注意包含最新版本的头文件shellapi.h,并保证链接最新版本的库文件shell32.lib,分发程序时用最新版本的运行时动态链接库shell32.dll)便是为显示气球提示所用的。也就是说,要显示气球提示,那么在调用Shell_NotifyIcon函数时必须用NIF_INFO标志。提示文本填入szInfo域,标题文本填入szInfoTitle。你甚至可以在NOTIFYICONDATA.uTimeout中设置一个超时时间,当经过指定的毫秒数之后,气球提示自动隐藏。

 
 
说明
:本教程来源互联网或网友上传或出版商,仅为学习研究或媒体推广,wanshiok.com不保证资料的完整性。

上一篇:VC中实现带有背景位图的树型控件  下一篇:Winsock开发网络通信程序的经典入门