关于托盘的一点总结2011-01-07张海明

很多软件例如:KV3000等在关闭之后会在托盘区有一个小的托盘图标,这表示程序并没有真正停止而在后台运行。当我们单击鼠标时可以使它在桌面上出现一个最大化窗口;而如果我们单击程序右上角х,或者单击文件菜单中的退出项时程序仍然在托盘上运行;只有我们右键单击托盘图标在出现的菜单中选择退出才能够真正退出程序等。现在我们通过一个类CSystemTray和修改系统菜单来实现上述功能。我们先来改变系统菜单。1、当我们在程序的标题栏上单击鼠标右键时,只出现如图的几项。而通过MFC生成的还会出现About一项,我们已经把它给去掉了。我们调用函数GetSystemMenu()来取的系统菜单,然后调用DeleteMenu()来去掉不要的系统菜单项,在这里我们去掉了“关闭”下面的分隔线和“about”项代码如下:
CMenu *pSystemMenu=GetSystemMenu(FALSE);
pSystemMenu->DeleteMenu(8,MF_BYPOSITION);
pSystemMenu->DeleteMenu(7,MF_BYPOSITION);
其中的数字7和8表示系统菜单的第7项和第8项,注意分隔线在VC中也算是一项。(这里和前面所讲的修改系统菜单的方法是一样的)。当我们去掉“about”这项后就应该在系统命令中也去掉相应的相应代码。我们找到函数OnSysCommand(UINT nID, LPARAM lParam)去掉其中截获about对话框的代码:
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
它对我们没有任何用处,放在这里只能给我们调试带来麻烦。当然如果你不去掉它程序完全没有一点错误。那么,为什么我们要去掉这两项呢,因为我们准备在托盘中实现相同的功能。1,我们再改变程序的关闭标志“X”的功能,把它改为隐藏而不是完全关闭。我们来截获关闭命令,把它改为隐藏。
if ((nID & 0xFFF0)==SC_CLOSE){
//OnClose();本来这个是关闭的这里也改为隐藏。
AnimateWindow(GetSafeHwnd(),1000,AW_HIDE|AW_BLEND);
KillTimer(0);
ShowWindow(SW_HIDE);//系统菜单的关闭也改为隐藏。
}
在ShowWindow(SW_HIDE)前面的两句是为了实现一种特效,即是慢慢很温和的隐藏,不过只有这两句还是不行的还应该在stdafx.h的前面加上如下两行代码:
#undef WINVER
#define WINVER 0X500
2、我们来建立一个托盘菜单,ID号为IDR_TUOPAN当我们在托盘上点击右键时,会出现一个菜单,在菜单里我们有:关于、显示(隐藏)、换歌、退出四项。我们先在头文件VioletPlayDlg.h中自定义一个消息:
#define WM_USER_TRAY_NOTIFICATION (WM_USER+0x101)
注意它的格式。在文件中定义一个托盘变量CSystemTray m_trayIcon,有了这些后我们就可以先做一个托盘雏形了。在主文件VioletPlayDlg.cpp中来产生一个托盘了。我们用Creat()函数定义如下:
m_trayIcon.Create(this, WM_USER_TRAY_NOTIFICATION, "VioletPlay", m_hIcon, IDR_TUOPAN);
其中第二个参数为我们自定义的功能,即出现托盘图标,第三个参数为当我们把鼠标放在图标上时出现的说明文字,第五个参数为当我们单击右键时出现的菜单,由于我们通过这个函数并不能响应右键,所以在这里并不能出现这个菜单,(下文会讲) 当我们的鼠标离开图标的时候出现的说明文字VioletPlay会自动消失,我们通过一个条件语句来实现。首先我们定义一个BOOL变量BOOL start_minimized我们来判断它的值:
if (start_minimized)
PostMessage(WM_CLOSE);
当我们鼠标移走的时候就发送一个CLOSE命令,关闭窗口。我们在文件VioletPlay.cpp中加上一句代码时程序运行的时候即可以在托盘中显示又可以在桌面上显示:
dlg.start_minimized=GetProfileInt(_T(""),_T("StartMinimized"),FALSE);
我们在这里在显示主程序的对话框之前加上这句代码,起到一个“拦截”作用。这样我们就实现了最初的功能,即在托盘中出现了一个图标,但是这还是远远不够的,我们在来一步步实现其他的功能。