分类: C/C++
2008-04-23 21:39:36
系统托盘编程完全指南(二)
编译/
在本文的第一部分,我们讨论并示范了如何在自己的程序中应用系统托盘图标。通过使用自己创建的一个可重用的
C 类——CTrayIcon,我们可以轻松地实现托盘程序。不久以前我用这个类编写了一个程序,开始运行很正常,但是有一次不知什么原因Windows资源管理器死掉了,也就是说非正常关闭,重启资源管理器后,发现托盘程序仍然在运行,但托盘图标显示不出来,在任务栏中看不到托盘图标,只有重新启动机器才能重新显示出托盘图标,让人觉得心里很不舒服,有没有什么办法在这个时候不用重启机器而让Windows自动找回托盘图标并把它添加到任务栏呢?,也就是让它自动恢复托盘图标程序的用户界面,经过一番研究,终于有所收获。
实际上,如果你用的操作系统是Windows 98或者你安装了IE4.0的桌面。那么不论什么时候,只要IE4.0启动了任务栏,那么它就会向所有最顶层父窗口广播一个注册消息:TaskbarCreated。有了这个线索,你就可以重新创建图标。如果你用MFC编程,那么只要定义一个全程变量保存这个注册消息并实现ON_REGISTERED_MESSAGE消息处理例程即可:
const UINT WM_TASKBARCREATED = ::RegisterWindowMessage(_T("TaskbarCreated")); BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_REGISTERED_MESSAGE(WM_TASKBARCREATED, OnTaskBarCreated) END_MESSAGE_MAP(CMainFrame, CFrameWnd) The handler itself should reinstall whatever icons you need. LRESULT CMainFrame::OnTaskBarCreated(WPARAM wp, LPARAM lp) { VERIFY(InstallIcons()); return 0; } BOOL CMainFrame::InstallIcons() { NOTIFYICONDATA nid; // // 准备 nid 参数 // return Shell_NotifyIcon(NIM_ADD, &nid);难道就这么容易吗?当然不是,你必须单独实现InstallIcons函数,而不是直接从OnTaskBarCreated中调用Shell_NotifyIcon,因为一般来说,在应用程序启动的时候你也会调用它。
// 在CMainFrame::OnCreate中 m_trayIcon.SetNotificationWnd(this, WM_MY_TRAY_NOTIFICATION); m_trayIcon.SetIcon(IDI_MYICON);WM_MY_TRAY_NOTIFICATION 是自己的私有消息,只在有事件发生时,托盘图标才发送此消息,如用户单击图标。对于托盘图标来说,你不用对它做什么处理,CTrayIcon全权负责。只是在构造CTrayIcon对象时,你给它一个资源ID就可以了。CTrayIcon用这个ID查找上下文菜单,如果找到的话,它便自动处理右键单击托盘图标事件,这时弹出上下文菜单。如果用户双击图标,CTrayIcon则执行第一个菜单项命令。所以你要做的全部工作只是创建一个菜单资源,将ID传递给构造函数,然后去驱动CTrayIcon就可以了。如果你想要一些非标准的例程,那么只需处理WM_MY_TRAY_NOTIFICATION即可。有关细节请参考源代码。