系统托盘编程完全指南
2010-07-25 20:46:55 来源:WEB开发网CTrayIcon将此代码解释成NIM_DELETE。你已经看到,所有这些表示行为的编码,标志都被一个使用方便的函数所替代:这都归功于C++!现在,我们来看看如何处理通知消息以及前面提到的所有UI特性。通知消息的处理必须要设置图标之前,但是要在创建窗口之后调用CTrayIcon::SetNotificationWnd,做这件事情的最佳场所是在OnCreate处理例程中,TrayTest就是在这里处理的:
// 注册用于托盘的自定义消息
#define WM_MY_TRAY_NOTIFICATION WM_USER+0
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
……
// 请通知我
m_trayIcon.SetNotificationWnd(this,
WM_MY_TRAY_NOTIFICATION);
m_trayIcon.SetIcon(IDI_MYICON);
return 0;
}
消息一旦注册,接下来你便可以用通常的消息映射方式处理托盘通知消息。
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_MESSAGE(WM_MY_TRAY_NOTIFICATION,
OnTrayNotification)
// (or ON_REGISTERED_MESSAGE)
END_MESSAGE_MAP()
LRESULT
CMainFrame::OnTrayNotification(WPARAM wp, LPARAM lp)
{
……
// 显示消息
……
return m_trayIcon.OnTrayNotification(wp, lp);
}
当消息处理器得到控制,WPARAM的值是在构造CTrayIcon时指定的ID;LPARAM为鼠标事件(如WM_LBUTTONDOWN)。当你得到通知消息后,可以做任何想做的的事情;例子程序TrayTest此时是显示通知信息,细节请参考源代码。完成消息的处理之后,调用CTrayIcon::OnTrayNotification进行缺省处理。此虚拟函数(所以你可以改写)实现我前面提到过的缺省的UI行为。尤其是处理WM_LBUTTONDBLCLK和WM_RBUTTONUP。CTrayIcon寻找与图标ID相同的某个菜单(如IDR_TRAYICON),如果找到,则当用户右键单击图标时CTrayIcon显示这个菜单;当用户数双击图标时,CTrayIcon执行第一个菜单命令。只有两件事情需要进一步交待:
第一件事情是:在显示菜单之前,CTrayIcon让第一个菜单项为默认,所以它以黑体显示。但如何用黑体来显示某个菜单项呢?我在\MSDEV\INCLUDE\*.H搜索了一番,发现了Get/SetMenuDefaultItem。这个函数没有相关的CMenu打包类,所以我必须直接调用它们。
// 让第一个菜单项为默认(黑体):
::SetMenuDefaultItem(pSubMenu->m_hMenu, 0, TRUE);
这里0表示第一个菜单项,TRUE说明用位置表示菜单项的ID。为什么MFC没有打包Get/SetMenuDefaultItem函数呢?微软的家伙们解释那是因为这些函数(其它的还有::Get/SetMenuItemInfo, ::LoadImage等)还没有在最新的Windows版本中实现。一旦在最新的Windows版本中实现了,便会马上添加到MFC中。
第二件事情是上下文菜单的显示:
::SetForegroundWindow(m_nid.hWnd); ::TrackPopupMenu(pSubMenu->m_hMenu, ...);
为了让TrackPopupMenu在托盘的上下文中正确运行,你必须首先调用SetForegroundWindow,否则,当用户按下ESCAPE键或者在菜单之外单击鼠标时,菜单不会消失。为解决这个问题,我花费了数个小时,最后还是在MSDN上找到了解决方法。为了解详情,请参考MSDN的Q135788。最让我哭笑不得的是我花了那么多时间来关注这个问题,最后微软的这帮家伙在MSDN上给你来了一个问题的结论是:“This behavior is by design.....”真是气刹人也。
正如你所看到的,CTrayIcon使得托盘应用的编程变得易如反掌。TrayTest1要做的事情不外乎调用CTrayIcon::OnTrayNotification实现一个通知消息处理器,提供一个与图标ID相同的菜单。就这么简单。
// (TRAYTEST.RC文件)
IDR_TRAYICON MENU DISCARDABLE
BEGIN
POPUP "托盘(&T)"
BEGIN
MENUITEM "打开(&O)", ID_APP_OPEN
MENUITEM "关于 TrayTest(&A)...", ID_APP_ABOUT
MENUITEM SEPARATOR
MENUITEM "退出TrayTest 程序(&S)", ID_APP_SUSPEND
END
END
更多精彩
赞助商链接