会员: 密码:  免费注册 | 忘记密码 | 会员登录 网页功能: 加入收藏 设为首页 网站搜索  
技术文档 > VC文档 > 窗体界面
在任务栏状态区显示应用程序图标
发表日期:2003-05-28 00:00:00作者: 出处:  

数据结构:

有关的数据由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);

}

返回顶部】 【打印本页】 【关闭窗口

关于我们 / 给我留言 / 版权举报 / 意见建议 / 网站编程QQ群   
Copyright ©2003- 2024 Lihuasoft.net webmaster(at)lihuasoft.net 加载时间 0.00563