MFC之系统托盘实现与应用

来源:互联网 发布:解剖生理学试题软件 编辑:程序博客网 时间:2024/05/20 07:54

系统托盘大家应该都了解,如果程序需要常时间运行,将程序缩小的托盘中移动是个不错的选择。

现在看看系统托盘应该怎么实现:

首先,必须知道一个结构体NOTIFYICONDATA

,这是MFC中包含系统需要的用来传递托盘区域消息的信息结构体,有了它,我们今天的任务就完全可以轻松完成了!


     这时候,我们可以在我们的类中申明一个NOTIFYICONDATA的成员变量为m_nid。

接下来,我们可以给这个结构体变量赋我们想要的值了,记住赋值语句要写在OnInitDialog初始化窗口函数里,不要写在构造函数中,否则将会无效。

m_nid.cbSize = sizeof( NOTIFYICONDATA );

m_nid.hWnd = m_hWnd; 
m_nid.uID = IDR_MAINFRAME; 
m_nid.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
m_nid.uCallbackMessage = WM_SYSTEMTRAY;    //自定义消息
m_nid.hIcon = m_hIcon;                                               
strcpy(m_nid.szTip, "认证系统客户端");

::Shell_NotifyIcon(NIM_ADD, &m_nid);

然后,让我们一句句的解析这段代码,

m_nid.cbSize = sizeof( NOTIFYICONDATA );

cbSize表示结构体的大小,以字节未单位,这里赋值了NOTIFYICONDATA的结构体标准大小就行了,用sizeof函数就能获得其字节大小

m_nid.hWnd = m_hWnd; 

hWnd是你想要赋予托盘的窗口句柄,MFC的窗口类中因为都是继承CDialog类,所以其中会有一个成员变量是m_hWnd保存着当前实例窗口的具体句柄,我们将其赋值给它就行了

m_nid.uID = IDR_MAINFRAME; 

uID指的是应用程序定义的任务栏图标的标识符,简单的时候就是图片图标的ID,这里的ID你可以进入工程下的ResourceView中找到Icon文件夹下的图标,里面的ID号就是我们现在要赋值的具体ID,Shell_NotifyIcon函数调用时,hWnd和UID成员用来标示具体要操作的图标,可以通过多次的调用,来实现不同uID将多个图标关联到一个窗口hWnd上,从而实现托盘图标切换的效果

m_nid.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;

uFlags表明具体哪些其他成员为合法数据,简单的说就是只有在uFlags中提到过的变量,才能发挥其作用,具体uFlags可以由以下一些成员组合:

NIF_ICON     表示hicon成员起作用。

NIF_MESSAGE  表示uCallbackMessage成员起作用

NIF_TIP      表示szTip成员起作用

当然还有许多别的如:NIF_STATE,NIF_INFO,NIF_GUID,这里就具体先介绍上面三个,其他想了解的话可以具体查msdn

m_nid.uCallbackMessage = WM_SYSTEMTRAY; 

uCallbackMessage是应用程序定义的消息标示,当鼠标在托盘鼠标上点击事件的时候,程序的WM_SYSTEMTRAY就会被发出,我们只要在WindowProc函数中就能获得的该消息,从而做出事件响应,如下:

        switch(message)
{
case WM_SYSTEMTRAY:  //自定义消息

           //具体响应消息

        break; 

        }

其中,大家可以看出WM_SYSTEMTRAY不是系统消息,而是自定义的一个消息,用于表示这个特殊的事件发生了,至于怎么定义呢,就是用宏了

#define WM_SYSTEMTRAY WM_USER+1

这里解释下,为什么WM_SYSTEMTRAY要宏定义成WM_USER+1呢,据我了解WM_USER是系统消息中的最后一个,也就是说这样定义就不会和系统的消息冲突成一个同样的值

m_nid.hIcon = m_hIcon;  

增加、修改或删除的图片句柄,用于控制托盘的图标,m_hIcon是自定义的一个窗口图标句柄

HICON m_hIcon;

m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

当然你可以直接将m_nid.hIcon = m_hIcon 改成 m_nid.hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME)

strcpy(m_nid.szTip, "认证系统客户端");

szTip是一个字符串指针,是在鼠标放在图标上的时候,会出现的提示消息。

::Shell_NotifyIcon(NIM_ADD, &m_nid);

最后一个是一个全局函数 BOOL Shell_NotifyIcon(DWORD dwMessage,PNOTIFYICONDATA ipdata);

参数dwMessage表示要执行的操作,可选值为:

NIM_ADD      表示在托盘区域增加图标

NIM_DELETE   表示删除托盘区域的图标

NIM_MODIFY   表示修改托盘区域的图标

NIM_SETFOCUS 表示聚焦到托盘图标上

第二个参数就是我们上面介绍过的NOTIFYICONDATA结构体的指针了。

如果操作成功函数会返回TRUE,否则返回FALSE。


///////////////////////////////////////////////////////////////////////////////////

OK,托盘的实现就是这么简单的啦,但是如果你想具体深入了解,可以查看MSDN里面具体的解释,也可以跟本人沟通

下面介绍下应用,具体的应用情况很多。

我们就来简单的讲一下,怎么实现窗口隐藏后,双击托盘使窗口再出现,和右击托盘出现退出窗口的实现

上面叫到了自定义的消息,在WindowProc函数中,我们可以具体实现

switch(message)
{
case WM_SYSTEMTRAY:  //自定义消息

           if (lParam == WM_LBUTTONDBLCLK)
{  
ShowWindow(SW_SHOWNORMAL);
}

        break; 

        }

上面的代码就实现了,双击托盘实现显示窗口的代码,非常简单,我们就不具体剖析了。

要实现右击托盘显示弹出窗口,我们必须先在资源中创建一个菜单,然后加入以下代码

                case WM_SYSTEMTRAY:  //自定义消息    
if (lParam == WM_RBUTTONDOWN)
{  
//右击弹出托盘菜单
CMenu menu;
menu.LoadMenu(IDR_MENU1);
CMenu *pPopUp=menu.GetSubMenu(0);
CPoint pt; 
GetCursorPos(&pt); 

SetForegroundWindow(); 
pPopUp->TrackPopupMenu(TPM_RIGHTBUTTON,pt.x,pt.y,this); 
PostMessage(WM_NULL,0,0);
}
break;

代码中,刚开始定义了一个CMenu的对象,然后将我们之前创建的菜单ID加载进去,然后获得鼠标当前的位置,在这个位置上将菜单显示出来

。其他的,大家自己发现和探索吧。

原创粉丝点击