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

导读:
  二、编程步骤
  1、 启动Visual C++6.0,生成一个单文档的应用程序TrayTest,取消文档视图支持;
  2、 在CMainFrame类中添加自定义消息#define WM_MY_TRAY_NOTIFICATION WM_USER+0,并在该类中为此自定义消息手动添加消息映射ON_MESSAGE(WM_MY_TRAY_NOTIFICATION, OnTrayNotification)和消息响应函数afx_msg LRESULT OnTrayNotification(WPARAM wp, LPARAM lp);
  3、 设计二个图标添加到项目中,其ID标志分别为"IDI_MYICON"、"IDI_MYICON2",作为托盘显示时的图标;
  4、 在CMainFrame类中添加下述变量: CTrayIcon m_trayIcon(用来操作图标的类对象)、CEdit m_wndEdit(编辑框用来显示所跟踪到的鼠标消息)、int m_iWhichIcon(决定当前托盘使用哪个图标)、BOOL m_bShutdown(是否关闭当前拖盘程序标志)、BOOL m_bShowTrayNotifications(是否显示托盘消息标志);
  5、 为程序的IDR_MAINFRAME添加处理菜单项和托盘的上下文菜单IDI_TRAYICON(具体的菜单项的标题和ID标志符参见代码部分),然后使用Class Wizard为各个菜单项添加处理函数;
  6、 添加代码,编译运行程序。
  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 // 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

本文转自
http://tech.163.com/06/0628/09/2KMPTBE40009159Q_2.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值