最小化程序到托盘区

最小化程序到托盘区

Dec 21, 2013
Coding
MFC, Windows, C++

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消息需要如下四个步骤

声明消息,声明消息处理函数,关联消息和消息处理函数,实现消息处理函数

windows_message

声明消息

在.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的对话框程序默认只有一个关闭按钮,所以首先要为窗口添加最小化(最大化)按钮。

右击窗口,选择“属性”,再切换到“样式”标签页,勾选“最小化框”“(最大化框”)

minimise

(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专栏。有较大改动。