在任务栏状态区显示应用程序图标   
  数据结构: 
  有关的数据由NOTIFYICONDATA结构描述: 
  typedef   struct   _NOTIFYICONDATA 
  { 
          DWORD   cbSize;   //结构的大小,必须设置 
          HWND   hWnd;   //接受回调消息的窗口的句柄 
          UINT   uID;   //应用程序定义的图标标志 
          UINT   uFlags;   //标志,可以是NIF_ICON、NIF_MESSAGE、NIF_TIP或其组合 
          UINT   uCallbackMessage;//应用程序定义的回调消息标志 
          HICON   hIcon;   //图标句柄 
          char   szTip[64];   //提示字串 
  }   NOTIFYICONDATA,   *PNOTIFYICONDATA; 
  函数说明 
  由Shell_NotifyIcon()函数向系统发送添加、删除、更改图标的消息。 
  WINSHELLAPI   BOOL   WINAPI   Shell_NotifyIcon(DWORD   dwMessage,PNOTIFYICONDATA   pnid); 
  DwMessage为所发送消息的标志: 
          NIM_ADD   添加图标到任务栏通知区; 
          NIM_DELETE   删除任务栏通知区的图标; 
          NIM_MODIFY   更改任务栏通知区的图标、回调消息标志、回调窗口句柄或提示字串; 
  pnid为NOTIFYICONDATA结构的指针。 
  回调信息的获得及处理 
  如果一个任务栏图标有应用程序定义的回调消息,那么当这个图标有鼠标操作时,系统将给hWnd所标志的窗口发送下列的消息: 
  messageID   =   uCallbackMessage 
  wParam   =   uID 
  lParam   =   mouse   event(例如WM_LBUTTONDOWN) 
  通过这种方式,系统通知应用程序用户对图标的操作。如果一个应用程序生成了两个以上的图标,那么你可以根据wParam来判断是哪个图标返回的鼠标操作。通常,标准的Win95任务栏图标有以下鼠标操作响应: 
  当鼠标停留在图标上时,系统应显示提示信息tooltip; 
  当使用鼠标右键单击图标时,应用程序应显示快捷菜单; 
  当使用鼠标左键双击图标时,应用程序应执行快捷菜单的缺省菜单项。 
  在Microsoft   Windows环境中,0x8000到0xBFFF的消息是保留的,应用程序可以定义自定义消息。 
  关于消息处理的详细内容,请参考下一部分。 
  源码及实现 
  在本文中关于任务栏图标的类叫做CTrayIcon,这个类由CCmdTarget(或CObject)类派生,它有如下的成员变量和成员函数: 
  //   TrayIcon.h 
  //   CTrayIcon   command   target 
  class   CTrayIcon   :   public   CCmdTarget 
  { 
  public: 
          NOTIFYICONDATA   m_nid;//NOTIFYICONDATA结构,你的图标要用的啊 
          BOOL   m_IconExist;//标志,看看图标是不是已经存在了 
          CWnd*   m_NotificationWnd;//接受回调消息的窗口,有它就不必经常AfxGetMainWnd了 
  public: 
          CWnd*   GetNotificationWnd()   const;//得到m_NotificationWnd 
          BOOL   SetNotificationWnd(CWnd*   pNotifyWnd);//设置(更改)m_NotificationWnd 
          CTrayIcon();//构造函数 
          virtual   ~CTrayIcon();//析构函数 
          BOOL   CreateIcon(CWnd*   pNotifyWnd,   UINT   uID,   HICON   hIcon, 
                          LPSTR   lpszTip,   UINT   CallBackMessage);//在任务栏上生成图标 
          BOOL   DeleteIcon();//删除任务栏上的图标 
          virtual   LRESULT   OnNotify(WPARAM   WParam,   LPARAM   LParam);//消息响应函数 
          BOOL   SetTipText(UINT   nID);//设置(更改)提示字串 
          BOOL   SetTipText(LPCTSTR   lpszTip);//设置(更改)提示字串 
          BOOL   ChangeIcon(HICON   hIcon);//更改图标 
          BOOL   ChangeIcon(UINT   nID);//更改图标 
          BOOL   ChangeIcon(LPCTSTR   lpszIconName);//更改图标 
          BOOL   ChangeStandardIcon(LPCTSTR   lpszIconName);//更改为标准图标 
          ...... 
  }; 
  下面是成员函数的定义: 
  //   TrayIcon.cpp 
  //   CTrayIcon 
  CTrayIcon::CTrayIcon() 
  {//初始化参数 
          m_IconExist   =   FALSE; 
          m_NotificationWnd   =   NULL; 
          memset(&m_nid,   0,   sizeof(m_nid)); 
          m_nid.cbSize   =   sizeof(m_nid);//这个参数不会改变 
  } 
  CTrayIcon::~CTrayIcon() 
  { 
          if   (m_IconExist) 
                  DeleteIcon();//删除图标 
  } 
  BOOL   CTrayIcon::CreateIcon(CWnd*   pNotifyWnd,   UINT   uID,   HICON   hIcon, 
                  LPSTR   lpszTip,   UINT   CallBackMessage) 
  { 
          //确定接受回调消息的窗口是有效的 
          ASSERT(pNotifyWnd   &&   ::IsWindow(pNotifyWnd->GetSafeHwnd())); 
          ASSERT(CallBackMessage   >=   WM_USER);//确定回调消息不发生冲突 
          ASSERT(_tcslen(lpszTip)   <=   64);//提示字串不能超过64个字符 
          m_NotificationWnd   =   pNotifyWnd;//获得m_NotificationWnd 
          //设置NOTIFYICONDATA结构 
          m_nid.hWnd   =   pNotifyWnd->GetSafeHwnd(); 
          m_nid.uID   =   uID; 
          m_nid.hIcon   =   hIcon; 
          m_nid.uFlags   =   NIF_MESSAGE   |   NIF_ICON   |   NIF_TIP; 
          m_nid.uCallbackMessage   =   CallBackMessage; 
          //设置NOTIFYICONDATA结构的提示字串 
          if   (lpszTip) 
                  lstrcpyn(m_nid.szTip,   lpszTip,   sizeof(m_nid.szTip)); 
          else 
                  m_nid.szTip[0]   =   '\0'; 
          //显示图标 
          m_IconExist   =   Shell_NotifyIcon(NIM_ADD,   &m_nid); 
          return   m_IconExist; 
  } 
  BOOL   CTrayIcon::DeleteIcon() 
  {//删除图标 
          if   (!m_IconExist) 
                  return   FALSE; 
          m_IconExist   =   FALSE; 
          return   Shell_NotifyIcon(NIM_DELETE,   &m_nid); 
  } 
  LRESULT   CTrayIcon::OnNotify(WPARAM   WParam,   LPARAM   LParam) 
  {//处理图标返回的消息 
          if   (WParam   !=   m_nid.uID)//如果不是该图标的消息则迅速返回 
                  return   0L; 
          //准备快捷菜单 
          CMenu   menu; 
          if   (!menu.LoadMenu(IDR_POPUP))//你必须确定资源中有ID为IDR_POPUP的菜单 
                  return   0; 
          CMenu*   pSubMenu   =   menu.GetSubMenu(0);//获得IDR_POPUP的子菜单 
          if   (!pSubMenu) 
                  return   0; 
          if   (LParam   ==   WM_RBUTTONUP) 
          {//右键单击弹出快捷菜单 
                  //设置第一个菜单项为缺省 
                  ::SetMenuDefaultItem(pSubMenu->m_hMenu,   0,   TRUE); 
                  CPoint   pos; 
                  GetCursorPos(&pos); 
                  //显示并跟踪菜单 
                  m_NotificationWnd->SetForegroundWindow(); 
                  pSubMenu->TrackPopupMenu(TPM_RIGHTALIGN|TPM_LEFTBUTTON 
                          |TPM_RIGHTBUTTON,   pos.x,   pos.y,   m_NotificationWnd,   NULL); 
          } 
          else   if   (LParam   ==   WM_LBUTTONDOWN) 
          {//左键单击恢复窗口 
                  m_NotificationWnd->ShowWindow(SW_SHOW);//恢复窗口 
                  m_NotificationWnd->SetForegroundWindow();//放置在前面 
          } 
          else   if   (LParam   ==   WM_LBUTTONDBLCLK) 
          {//左键双击执行缺省菜单项 
                  m_NotificationWnd->SendMessage(WM_COMMAND, 
                          pSubMenu->GetMenuItemID(0),   0); 
          } 
          return   1L; 
  } 
  BOOL   CTrayIcon::SetTipText(LPCTSTR   lpszTip) 
  {//设置提示文字 
          if   (!m_IconExist) 
                  return   FALSE; 
          _tcscpy(m_nid.szTip,   lpszTip); 
          m_nid.uFlags   |=   NIF_TIP; 
          return   Shell_NotifyIcon(NIM_MODIFY,   &m_nid); 
  } 
  BOOL   CTrayIcon::SetTipText(UINT   nID) 
  {//设置提示文字 
          CString   szTip; 
          VERIFY(szTip.LoadString(nID)); 
          return   SetTipText(szTip); 
  } 
  BOOL   CTrayIcon::ChangeIcon(HICON   hIcon) 
  {//更改图标 
          if   (!m_IconExist) 
                  return   FALSE; 
          m_nid.hIcon   =   hIcon; 
          m_nid.uFlags   |=   NIF_ICON; 
          return   Shell_NotifyIcon(NIM_MODIFY,   &m_nid); 
  } 
  BOOL   CTrayIcon::ChangeIcon(UINT   nID) 
  {//更改图标 
          HICON   hIcon   =   AfxGetApp()->LoadIcon(nID); 
          return   ChangeIcon(hIcon); 
  } 
  BOOL   CTrayIcon::ChangeIcon(LPCTSTR   lpszIconName) 
  {//更改图标 
          HICON   hIcon   =   AfxGetApp()->LoadIcon(lpszIconName); 
          return   ChangeIcon(hIcon); 
  } 
  BOOL   CTrayIcon::ChangeStandardIcon(LPCTSTR   lpszIconName) 
  {//更改为标准图标 
          HICON   hIcon   =   AfxGetApp()->LoadStandardIcon(lpszIconName); 
          return   ChangeIcon(hIcon); 
  } 
  BOOL   CTrayIcon::SetNotificationWnd(CWnd   *   pNotifyWnd) 
  {//设置接受回调消息的窗口 
          if   (!m_IconExist) 
                  return   FALSE; 
          //确定窗口是有效的 
          ASSERT(pNotifyWnd   &&   ::IsWindow(pNotifyWnd->GetSafeHwnd())); 
          m_NotificationWnd   =   pNotifyWnd; 
          m_nid.hWnd   =   pNotifyWnd->GetSafeHwnd(); 
          m_nid.uFlags   |=   NIF_MESSAGE; 
          return   Shell_NotifyIcon(NIM_MODIFY,   &m_nid); 
  } 
  CWnd*   CTrayIcon::GetNotificationWnd()   const 
  {//返回接受回调消息的窗口 
          return   m_NotificationWnd; 
  } 
  三点补充: 
  关于使用回调消息的补充说明: 
  首先,在MainFrm.cpp中加入自己的消息代码; 
  //   MainFrm.cpp   :   implementation   of   the   CMainFrame   class 
  // 
  #define   MYWM_ICONNOTIFY   WM_USER   +   10//定义自己的消息代码 
  第二步增加消息映射和函数声明,对于自定义消息不能由ClassWizard添加消息映射,只能手工添加。 
  //   MainFrm.cpp   :   implementation   of   the   CMainFrame   class 
  BEGIN_MESSAGE_MAP(CMainFrame,   CMDIFrameWnd) 
          //{{AFX_MSG_MAP(CMainFrame) 
          //其他的消息映射 
          ...... 
          //}}AFX_MSG_MAP 
          ON_MESSAGE(WM_ICONNOTIFY,OnNotify) 
  END_MESSAGE_MAP() 
  并且在头文件中添加函数声明 
  //   MainFrm.h 
  afx_msg   LRESULT   OnNotify(WPARAM   WParam,   LPARAM   LParam); 
  第三步增加消息处理函数定义 
  LRESULT   CMainFrame::OnNotify(WPARAM   WParam,   LPARAM   LParam) 
  { 
          return   trayicon.OnNotify(WParam,   LParam);//调用CTrayIcon类的处理函数 
  } 
  如何隐藏任务栏上的按钮: 
  可以使用下列两种方法: 
  1.在CreateWindowEx函数中使用WS_EX_TOOLWINDOW窗口式样(相反的如果要确保应用程序在任务栏上生成按钮,可以使用WS_EX_APPWINDOW窗口式样)。   The   problem   with   this   is   that   the   window   decorations   are   as   for   a   small   floating   toolbar,   which   isn't   normally   what's   wanted. 
  2.生成一个空的隐藏的top-level窗口,并使其作为可视窗口的父窗口。 
  3.在应用程序的InitInstance()函数中使用SW_HIDE式样调用ShowWindow()函数。 
  //pMainFrame->ShowWindow(m_nCmdShow); 
  pMainFrame->ShowWindow(SW_HIDE); 
  pMainFrame->UpdateWindow(); 
  如何动画任务栏上的图标: 
  在TrayIcon类中加入下列两个函数: 
  BOOL   CTrayIcon::SetAnimateIcons(HICON*   hIcon,   UINT   Number) 
  {//设置动画图标 
          ASSERT(Number   >=   2);//图标必须为两个以上 
          ASSERT(hIcon);//图标必须不为空 
          m_AnimateIcons   =   new   HICON[Number]; 
          CopyMemory(m_AnimateIcons,   hIcon,   Number   *   sizeof(HICON)); 
          m_AnimateIconsNumber   =   Number; 
          return   TRUE; 
  } 
  BOOL   CTrayIcon::Animate(UINT   Index) 
  {//动画TrayIcon 
          UINT   i   =   Index   %   m_AnimateIconsNumber; 
          return   ChangeIcon(m_AnimateIcons[i]); 
  } 
  在应用程序中添加相应的菜单和函数(请参考下面的例子): 
  void   CMainFrame::OnMenuAnimate() 
  {//动画TrayIcon,设置图标及定时器 
          SetTimer(1,   500,   NULL); 
          HICON   hIcon[3]; 
          hIcon[0]   =   AfxGetApp()->LoadIcon(IDR_MAINFRAME); 
          hIcon[1]   =   AfxGetApp()->LoadIcon(IDR_MYTURNTYPE); 
          hIcon[2]   =   AfxGetApp()->LoadStandardIcon(IDI_HAND); 
          trayicon.SetAnimateIcons(hIcon,   3); 
  } 
  void   CMainFrame::OnTimer(UINT   nIDEvent) 
  {//动画TrayIcon 
          UINT   static   i; 
          i   +=   1; 
          trayicon.Animate(i); 
          CMDIFrameWnd::OnTimer(nIDEvent); 
  }  

 

引用自 : http://topic.csdn.net/t/20010507/03/113715.html



arrow
arrow
    全站熱搜
    創作者介紹
    創作者 gordenhao 的頭像
    gordenhao

    高登

    gordenhao 發表在 痞客邦 留言(0) 人氣()