托盘程序需要头文件:
#include <shellapi.h> //托盘程序
1.用户自定义消息
#define WM_SYSTEMTRAY (WM_USER+103) //响应鼠标在托盘图标上的事件
2.在对话框头文件中:
//在托盘区添加图标 最小化到托盘函数
void ToTray(void);
//删除托盘中图标
void DeleteTray();
////////////////////下面的方法是实现菜单响应函数//////////////////////////////////////////////////////////////////////////////
//定义右键托盘图标弹出的菜单ID
typedef enum
{
ID_SHIFT_WORKPATTERN = 10001,
ID_QUIT = 10002
}TRAY_MENU;
//自定义消息WM_SYSTEMTRAY的响应函数,处理鼠标事件,如:右键鼠标弹出菜单
afx_msg LRESULT OnSystemtray(WPARAM wParam, LPARAM lParam);
//在OnCommand中响应菜单消息:
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
3.在对话框原文件中:
BEGIN_MESSAGE_MAP(CSSDlg, CDialog)
ON_MESSAGE(WM_SYSTEMTRAY, &CSSDlg::OnSystemtray)
END_MESSAGE_MAP()
void CSSDlg::ToTray( void )
{
NOTIFYICONDATA nid;
nid.cbSize = (DWORD)sizeof(NOTIFYICONDATA);
nid.hWnd = this->m_hWnd;
nid.uID = IDR_MAINFRAME;
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
nid.uCallbackMessage = WM_SYSTEMTRAY;//自定义的消息名称
nid.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));
//wcscpy_s(nid.szTip, _T("****系统"));//信息提示条
strcpy(nid.szTip, _T("****系统"));//信息提示条
Shell_NotifyIcon(NIM_ADD, &nid);//在托盘区添加图标
ShowWindow(SW_HIDE);//隐藏主窗口
}
void CSSDlg::DeleteTray()
{
NOTIFYICONDATA nid;
nid.cbSize = (DWORD)sizeof(NOTIFYICONDATA);
nid.hWnd = this->m_hWnd;
nid.uID = IDR_MAINFRAME;
nid.uFlags = NIF_ICON;
Shell_NotifyIcon(NIM_DELETE, &nid);//在托盘中删除图标
}
托盘鼠标事件响应函数:
LRESULT CSSDlg::OnSystemtray( WPARAM wParam, LPARAM lParam )
{
//wParam接收的是图标的ID,而lParam接收的是鼠标的行为
// if(wParam!=IDR_MAINFRAME)
// return 1;
switch(lParam)
{
case WM_RBUTTONDOWN://右键起来时弹出快捷菜单
{
LPPOINT lpoint = new tagPOINT;
::GetCursorPos(lpoint);//得到鼠标位置
CMenu menu;
menu.CreatePopupMenu();//声明一个弹出式菜单
//增加菜单项“关闭”,点击则发送消息WM_DESTROY给主窗口(已隐藏),将程序结束。
// menu.AppendMenu(MF_STRING, WM_DESTROY, _T("退出")); //调试的时候发现响应的是OnCancel(),不是OnDestroy
menu.AppendMenu(MF_STRING, ID_QUIT, _T("退出")); //响应OnDestroy()
menu.AppendMenu(MF_STRING, ID_SHIFT_WORKPATTERN, _T("切换工作模式"));
SetForegroundWindow();//设置当失去焦点时菜单自动消失
//确定弹出式菜单的位置
menu.TrackPopupMenu(TPM_LEFTALIGN, lpoint->x, lpoint->y, this);
//资源回收
HMENU hmenu = menu.Detach();
menu.DestroyMenu();
delete lpoint;
}
break;
case WM_LBUTTONDOWN://左键单击的处理
{
ModifyStyleEx(0,WS_EX_TOPMOST); //可以改变窗口的显示风格
ShowWindow(SW_SHOWNORMAL);
break;
}
case WM_LBUTTONDBLCLK://双击左键的处理
{
this->ShowWindow(SW_SHOW);//简单的显示主窗口
this->ShowWindow(SW_RESTORE);
DeleteTray();
//break;
}
break;
default:
break;
}
return 0;
}
实现菜单消息函数:
BOOL CSSDlg::OnCommand( WPARAM wParam, LPARAM lParam )
{
int menuID = LOWORD(wParam);
if ( ID_SHIFT_WORKPATTERN == menuID )
{
do something......
return TRUE;
}
if(ID_QUIT == menuID)
{
DestroyWindow();
return TRUE;
}
return CDialog::OnCommand(wParam,lParam);
}
4. 在关闭时最小化到托盘,而不是关闭:
void CSSDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{ CAboutDlg dlgAbout; }
else if (nID == SC_CLOSE) //SC_MINIMIZE
{
ToTray();
return;
}
CDialog::OnSysCommand(nID, lParam);
}
或者重写close函数:
void CMyPlayerDlg::OnCancel() //点击X 按钮或者按ESC键,最小化到系统托盘
{
// TODO: 在此添加专用代码和/或调用基类
ToTray( );
//CDialogEx::OnCancel();
}
参考:
http://blog.csdn.net/CHIHUN_LOVE/article/details/53944553
利用CMenu类动态添加弹出菜单 - jackyxm - 博客园 http://www.cnblogs.com/yxmx/articles/1628058.html
[罗振辉]MFC中菜单命令路由方式 - CSDN博客 http://blog.csdn.net/xxxluozhen/article/details/3930472