最小化程序到托盘区
Dec 21, 2013
Windows系统右下角显示时间、音量的那块区域叫做系统托盘区(即任务栏的最右侧)。
通常的程序窗口,点击最小化按钮之后,会最小化到任务栏。如果一个程序不需要经常打开界面操作,以后台为主时,可以将它最小化到托盘区,这样就不会占用任务栏的一格,需要时点击托盘区图标打开即可。
最小化到托盘区 #
任意位置执行下面的代码可以将程序最小化到托盘
void CMyDlg::OnBtnToTray()
{
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_SHOWTASK;//自定义的消息名称
nid.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));
strcpy(nid.szTip, "MySoftWare V1.0"); //信息提示条
Shell_NotifyIcon(NIM_ADD, &nid); //在托盘区添加图标
ShowWindow(SW_HIDE); //隐藏主窗口
}
下面解释这段代码
NOTIFYICONDATA 结构体 #
NOTIFYICONDATA: Contains information that the system needs to display notifications in the notification area. Used by Shell_NotifyIcon.
NOTIFYICONDATA 结构体包含了系统在托盘区(通知区)显示通知所需要的信息。它是函数Shell_NotifyIcon的参数。结构体包含的信息和使用方法如代码1所示。
代码1第8行设定一个回调消息WM_SHOWTASK(这是我们自己定义的消息,具体实现方法下面会讲述),当我们点击(左击、右击、双击等等)托盘区时,系统就会发送出WM_SHOWTASK消息。
Shell_NotifyIcon函数 #
BOOL Shell_NotifyIcon(
_In_ DWORD dwMessage,//指示函数要执行的动作
_In_ PNOTIFYICONDATA lpdata//指向NOTIFYICONDATA的指针
);
Shell_NotifyIcon: Sends a message to the taskbar’s status area. 向任务栏的状态区域(托盘区)发送一条消息。
dwMessage可取下面值中的一个:
- NIM_ADD 添加一个图标(ICON)到托盘区
- NIM_MODIFY 修改托盘区的一个图标
- NIM_DELETE 删除托盘区的一个图标
- NIM_SETFOCUM 将焦点返还到托盘区
- NIM_SETVERSION 命令托盘区按照lpdata中指定的Shell版本运行
自定义Windows 消息 #
自定义一个Windows消息需要如下四个步骤
声明消息,声明消息处理函数,关联消息和消息处理函数,实现消息处理函数
声明消息
在.cpp中 添加 #define WM_SHOWTASK (WM_USER + 1)
声明消息处理函数
在.h中添加 afx_msg LRESULT OnShowTask(WPARAM wParam,LPARAM lParam);
关联消息和处理函数
在.cpp的 BEGIN_MESSAGE_MAP 中 添加 ON_MESSAGE(WM_SHOWTASK,OnShowTask)
实现消息处理函数
在 .cpp中 实现函数 LRESULT CMyDlg::OnShowTask(WPARAM wParam,LPARAM lParam)
LRESULT CMyDlg::onShowTask(WPARAM wParam,LPARAM lParam)
//wParam接收的是图标的ID,而lParam接收的是鼠标的行为
{
if(wParam!=IDR_MAINFRAME)
return 1;
switch(lParam)
{
case WM_RBUTTONUP://右键起来时弹出快捷菜单
{
LPPOINT lpoint=new tagPOINT;
::GetCursorPos(lpoint);//得到鼠标位置
CMenu menu;
menu.CreatePopupMenu();//声明一个弹出式菜单
//增加菜单项“关闭”,点击则发送消息WM_DESTROY给主窗口(已隐藏),将程序结束。
menu.AppendMenu(MF_STRING,WM_DESTROY,"关闭");
menu.AppendMenu(MF_STRING,WM_SHOWWINDOW,"打开");
//确定弹出式菜单的位置
menu.TrackPopupMenu(TPM_LEFTALIGN,lpoint->x,lpoint->y,this);
//资源回收
HMENU hmenu=menu.Detach();
menu.DestroyMenu();
delete lpoint;
}
break;
case WM_LBUTTONDBLCLK://双击左键的处理
{
this->ShowWindow(SW_SHOW);//简单的显示主窗口完事儿
}
break;
}
return 0;
}
拦截窗口的最小化消息,实现最小化到托盘区 #
以MFC对话框程序为例,当用户点击窗口右上角的最小化消息时,我们希望拦截此消息,实现程序的最小化到托盘,而不是默认的最小化到任务栏。
方法如下
(1)为窗口添加最小化按钮 #
MFC的对话框程序默认只有一个关闭按钮,所以首先要为窗口添加最小化(最大化)按钮。
右击窗口,选择“属性”,再切换到“样式”标签页,勾选“最小化框”“(最大化框”)
(2)添加窗口的OnSize消息响应 #
右击对话框类名,选择“Add Windows Message Handle…”,在打开的对话左侧选择“WM_SIZE”消息,单击右侧“Add and Edit”进入代码编辑。代码如下
void CMyDlg::OnSize(UINT nType, int cx, int cy)
{
//最小化消息
if(nType == SIZE_MINIMIZED)
{
//最小到托盘区
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_HIDE_TO_TASK; //自定义的消息名称
nid.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));
wcscpy(nid.szTip,L"ScreenCap 1.0"); //信息提示条
Shell_NotifyIcon(NIM_ADD,&nid); //在托盘区添加图标
ShowWindow(SW_HIDE); //隐藏主窗口
}
CDialogEx::OnSize(nType, cx, cy);
}
总结 #
至此,我们实现了程序的最小化,并给出了两种实行方案:一种是直接调用运行代码1,比如这可以是在菜单的消息响应函数中,也可以是在Button的消息响应函数中;一种是拦截窗口的最小化消息,调用代码1,实现窗口最小化到托盘。另外,还穿插讲到了NOTIFYICONDATA 结构体和Shell_NotifyIcon函数。
该文2010-08-01 19:19首发于我的CSDN专栏。有较大改动。