Win32实现系统任务栏的小图标

 

A.第一种方法是通过MFC来实现的,从网上找的,red已经注明。

如果我们在程序最小化时采用在系统任务栏中的小图标,就象金山词霸一样,单击左键可以
实现最大最小化,单击右键有快捷菜单,那么整个程序会显的很简洁。
采用SDK的Shell_NotifyIcon等API可以实现系统任务栏的小图标,但是程序员必须仔细理解
这些API的具体用法,Chris Maunder
开发的系统任务栏类CSystemTray封装了这些API的功能,

使MFC程序员可以方便的实现具有系统任务栏小图标的程序。

---- CsytemTray的功能很多,看一看它的成员函数就可以知道其大致功能了。

  BOOL Enabled() { return m_bEnabled; }
  BOOL Visible() { return !m_bHidden; }
 
  //Create the tray icon
  Create(CWnd* pWnd, 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 lpIconName);
  BOOL  SetIcon(UINT nIDResource);
  BOOL  SetStandardIcon(LPCTSTR lpIconName);
  BOOL  SetStandardIcon(UINT nIDResource);
  HICON GetIcon() const;
  void   HideIcon();
  void   ShowIcon();
  void   RemoveIcon();
  void   MoveToRight();
 
  //Change or retrieve the window to
  send notification messages to
  BOOL  SetNotificationWnd(CWnd* pNotifyWnd);
  CWnd* GetNotificationWnd() const;

 
下面是实现步骤:
(1)首先在Project中加入CsystemTray类的.cpp和.h文件,这样在Workspace的
   ClassView中可以看到CsystemTray类。


(2)然后在CframeWnd的派生类的头文件中
    a.加入WM_ICON_NOTIFY 的消息定义
      #define WM_ICON_NOTIFY WM_USER+1
    b.在CframeWnd的派生类中添加变量
      CSystemTray m_TrayIcon;
    c.在CframeWnd的派生类的CPP文件中添加消息映射
      BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
      ... ...
      ON_MESSAGE(WM_ICON_NOTIFY, OnTrayNotification)
      END_MESSAGE_MAP()


(3)在CframeWnd的派生类中添加成员函数
    LRESULT CMainFrame::OnTrayNotification(WPARAM wParam, LPARAM lParam)
    {
      return m_TrayIcon.OnTrayNotification(wParam, lParam);
    }


(4)定义快捷菜单
    在MENU中添加新菜单IDR_POPUP_MENU,可以如一般的菜单一样从ClassWizard中定义其响应。


(5)在CsystemTray中修改OnTrayNotification函数,
    定义你希望实现的效果,如单击左键可以实现最大最小化,单击右键有快捷菜单等功能。
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;

 

 

  //定义单击右键有快捷菜单
  if (LOWORD(lParam) == WM_RBUTTONUP)
  {
    if (!menu.LoadMenu(m_tnd.uID))
      return 0;
    if (!(pSubMenu = menu.GetSubMenu(0)))
      return 0;

    // Make first menu item the default (bold font)
    ::SetMenuDefaultItem(pSubMenu- >m_hMenu, 0, TRUE);

    //Display and track the popup menu
    CPoint pos;
    GetCursorPos(&pos);

    ::SetForegroundWindow(m_tnd.hWnd);
    ::TrackPopupMenu(pSubMenu->m_hMenu, 0, pos.x,
    pos.y, 0, m_tnd.hWnd, NULL);

    // BUGFIX: See "PRB: Menus for Notification
    Icons Don't Work Correctly"
    ::PostMessage(m_tnd.hWnd, WM_NULL, 0, 0);

    menu.DestroyMenu();
}
//定义双击左键有产生单击快捷菜单第一项功能的响应
  else if (LOWORD(lParam) == WM_LBUTTONDBLCLK)
  {
      if (!menu.LoadMenu(m_tnd.uID)) return 0;
      if (!(pSubMenu = menu.GetSubMenu(0))) return 0;

      // double click received, the default action is to execute first menu item
      ::SetForegroundWindow(m_tnd.hWnd);
      ::SendMessage(m_tnd.hWnd, WM_COMMAND,
      pSubMenu->GetMenuItemID(0), 0);

      menu.DestroyMenu();
  }
  //定义单击左键为最小化或恢复窗口
  else if (LOWORD(lParam) == WM_LBUTTONUP)
  {
      if(AfxGetMainWnd()->IsIconic()!=0)
      {
        EnableWindow(m_tnd.hWnd,TRUE);
        ShowWindow(m_tnd.hWnd,SW_SHOW);
        ShowWindow(m_tnd.hWnd,SW_RESTORE);
      }
      else
      {
        ShowWindow(m_tnd.hWnd,SW_SHOWMINIMIZED);
        EnableWindow(m_tnd.hWnd,FALSE);
        ShowWindow(m_tnd.hWnd,SW_HIDE);
      }
  }
    return 1;
}


(6)在CmainFrame的派生类中添加WM_SIZE的消息响应函数,这可以实现程序最小化时
    只在系统任务栏中有一个小图标,而不会在一般任务栏中有显示
  void CMainFrame::OnSize(UINT nType, int cx, int cy)
  {
    CFrameWnd::OnSize(nType, cx, cy);
    if(nType==SIZE_MINIMIZED)
    {
      EnableWindow(FALSE);
      ShowWindow(SW_HIDE);
    }
  }
  看起来似乎这样实现步骤也不少,但是当我们再开发新的功能时会很方便,程序会更容易
  理解与开发。如我们可以很方便实现动态小图标。
  a.我们只需在CmainFrame的派生类中添加一个定时器
  SetTimer(IDW_TIMER1,500,NULL);
  icon_id=0;
  b.对定时发出的WM_TIME消息进行处理,例如时间到了就换一个图标,图标的变化可以根据
  自己的喜好及实际情况定义,此处有3个图标轮流变化。
  void CMainFrame::OnTimer(UINT nIDEvent)
  {
    // TODO: Add your message handler code here and/or call default
    //change the icon
    //icon_id from 0 to 2 every 0.5s
    if(nIDEvent ==IDW_TIMER1)
    {
      if(icon_id==0)
      {
        hIcon=AfxGetApp()->LoadIcon(IDR_ICON0);
        icon_id++;
      }
      else if(icon_id==1)
      {
        hIcon=AfxGetApp()->LoadIcon(IDR_ICON1);
        icon_id++;
      }
      else if(icon_id=2)
      {
        hIcon=AfxGetApp()->LoadIcon(IDR_ICON2);
        icon_id=0;
      }
      m_TrayIcon.SetIcon(hIcon);
    }
    CFrameWnd::OnTimer(nIDEvent);
}

B.第二种方法是通过消息去处理;

创建的基于对话框,看下面说明:

a.在WM_SIZE 消息里面处理有检测到最小化的动作时,作如下的操作:

主要是从代码中摘取的,看主要的代码就好了:

case WM_SIZE:
  if(wParam == SIZE_MINIMIZED)//if wparam == minimized,then add the icon into the taskbar only;
  {
   if(!g_bAddIcon)
   {  
    if(!AddIconToTaskbar(hDlg))
     MessageBox(0,"Add Icon to task bar ,failed!",0,0);
   }
   ShowWindow(hDlg,SW_HIDE);//hide the window;
  }
  break;

b.在WM_COMMAND消息中要remove掉图标;

 switch (LOWORD(wParam))
{
  case IDCANCEL:
    if (!g_bColor)
    {
         KillTimer(hDlg, 1);
    }
    portio.ShutdownDriver(szDriverName);
    CloseHandle(hLogFile);
    g_bRemove = TRUE;
    AddIconToTaskbar(hDlg);
    DeleteObject(hBrush);
    DeleteObject(hCurrentFont);
    EndDialog(hDlg, FALSE);
    return TRUE;
}

C.关键函数 AddIconTaskBar(HWND hwnd),主要处理如下:

 

BOOL AddIconToTaskbar(HWND hwnd)
{
  NOTIFYICONDATA nid;
  memset(&nid, 0, sizeof(nid));
  nid.cbSize = sizeof(nid);
  strcpy(nid.szTip, "XXX");
  nid.hWnd = hwnd;
  nid.uID = 100;
  nid.uFlags = NIF_ICON | NIF_MESSAGE;
  nid.hIcon = LoadIcon(gst_hInstance, MAKEINTRESOURCE(IDI_TEMP));
  nid.uCallbackMessage = WM_TASKMOUSE;//here to catch the mouse move message

  if (nid.hIcon == NULL)
  {
    MessageBox(0, "Can not add icon ,failed!", 0, 0);
    return FALSE;
  }
  if (!g_bRemove)
  {
    if (Shell_NotifyIcon(NIM_ADD, &nid))//add the icon into the taskbar
    {
      g_bAddIcon = TRUE;
      return TRUE;
    }
    else
      return FALSE;
  }
  else
  {
    Shell_NotifyIcon(NIM_DELETE, &nid);//delete the icon from the taskbar
    return TRUE;
  }
}

 

here, 处理鼠标的动作如下,比较粗糙:

case WM_TASKMOUSE:
  if( lParam == WM_LBUTTONDBLCLK)
  {
           ShowWindow(hDlg,SW_SHOWNORMAL);//double left click to show the window
  }
  break;

转载请注明,谢谢合作!

red 2010/02/10

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值