最小化托盘程序编写过程

原理

1..最小化的原理:首先要将窗口隐藏,然后在任务栏右下角绘制相应的程序图标。

2..恢复的原理:  将窗口显示,再将托盘中的图片删除即可。

实现思路

1 自己添加的按钮 点击后实现最小化

2 截获dlg自身的最小化按钮或者关闭按钮

本文按照 自己添加的按钮先讲 后边说一下第二种情况(思路是一样的)

第一步最小化到托盘 很简单

1..ShowWindow(SW_HIDE); 将主程序窗口隐藏

2..在任务栏绘制图标 用到一个windows提供的函数Shell_NotifyIcon

Shell_NotifyIcon函数 向任务栏的状态栏发送一个消息

函数原型及参数如下

 BOOL Shell_NotifyIcon(DWORD dwMessage,PNOTIFYICONDATA lpdata);

dwMessage为输入参数,传递发送的消息,表明要执行的操作。可选的值如下:

NIM_ADD向托盘区域添加一个图标。此时第二个参数lpdata指向的NOTIFYICONDATA结构体中的hWnd和uID成员用来标示这个图标

NIM_DELETE删除托盘的一个图标。此时第二个参数lpdata指向的NOTIFYICONDATA结构体中的hWnd和uID成员用来标示要被删除的图标NIM_MODIFY修改托盘的一个图标。此时第二个参数lpdata指向的NOTIFYICONDATA结构体中的hWnd和uID成员用来标示要被修改的图标

lpdata为输入参数,是指向NOTIFYICONDATA结构体的指针,结构体内容用来配合第一个参数wMessage进行图标操作。

如果图标操作成功返回TRUE,否则返回FALSE。

绘制图标有这个函数 而第一个参数已经确定为NIM_ADD

下边讲一下第二个参数  NOTIFYICONDATA 结构的一个指针

NOTIFYICONDATA   包含系统需要的用来传递托盘区域消息的信息。

NOTIFYICONDATA 结构(两个版本A W) 下边具体讲解

 

typedef struct _NOTIFYICONDATAA {

        DWORD cbSize;  结构体的大小,以字节为单位。

        HWND hWnd;  窗口的句柄。标示的窗口用来接收与托盘图标相关的消息

        UINT uID;    应用程序定义的任务栏图标的标识符 即 图片ID

        UINT uFlags; 此成员表明具体哪些其他成员为合法数据(即哪些成员起作用)

        UINT uCallbackMessage;应用程序定义的消息标示。当托盘图标区域发生鼠标事件或者使用键盘选择或激活图标时,系统将使用此

                                               标示向由hWnd成员标示的窗口发送消息。

        HICON hIcon;                  增加、修改或删除的图标的句柄。

        CHAR   szTip[64]; 指向一个以\0结束的字符串的指针。字符串的内容为标准工具提示的信息。包含最后的\0字符,szTip最多含

                                      有64个字符。

} NOTIFYICONDATAA, *PNOTIFYICONDATAA;

 

此结构是向托盘发送的消息包含的具体信息,即当点击最小化按钮时候,就对此结构信息进行初始化,并调用Shell_NotifyIcon函数 向任务栏发消息 具体代码

其中nid是NOTIFYICONDATA  nid; 定义在头文件中即可

void CFindFileDlg::OnExit()

{

    ShowWindow(SW_HIDE);

      nid.cbSize=(DWORD)sizeof(NOTIFYICONDATA);常用这种形式

      nid.hWnd=m_hWnd;

      nid.uID=IDR_MAINFRAME;这里使用主程序的默认图标

      //nid.hIcon=AfxGetApp()->LoadIcon(IDR_Edit);   获取图片句柄下边的也可以

      nid.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_Edit));

      strcpy(nid.szTip,"EditFileName!!");  显示信息使用strcpy函数赋值

      nid.uCallbackMessage=WM_NC;自己定义消息当图标弹出的菜单有鼠标消息时响应

      nid.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP;

      Shell_NotifyIcon(NIM_ADD,&nid);  添加此信息到托盘

}

其中有自定义消息WM_NC

自定义消息步骤

1..在stdafx.h头文件中(也可以自己定义头文件)定义宏#define WM_NC  WM_USER+1

2..在自定义消息函数所在的cpp中添加消息映射  ON_MESSAGE(WM_NC,OnShowDlg)

  OnShowDlg函数是自己编写的消息函数(也可以是系统自动完成的)

3..在相应的类头文件中添加消息映射到函数实现体

afx_msg LRESULT OnShowDlg(WPARAM wparam, LPARAM lparam);

afx_msg:afx_msg宏表示声明的是一个消息响应函数这个对编译器来说,相当于什么都没有,对于人来说,我们可以看到这样的符号.   对于类向导来说.这个符号才是有意义的.它是一个消息处理函数的前缀.类向导生成的消息函数,分发函数,事件响应函数都以这个为前缀.如果去掉了,向导将不能识别

好了到这第一步基本完成了 可以实现最小化并且创建一个托盘图标了

接下来就是恢复程序

LRESULT OnShowDlg(WPARAM wparam, LPARAM lparam);

//wParam接收的是图标的ID,而lParam接收的是鼠标的行为

这个消息函数就是当图标弹出的菜单有鼠标消息时响应的函数

在这个函数里我们需要实现的是

1..先判断一下图标的ID是否是我们创建的.

    if(wparam!=IDR_MAINFRAME)             return   1;

2..根据相应的鼠标信息作出相应的动作   代码如下详细讲解

 

LRESULT CFindFileDlg::OnShowDlg(WPARAM wparam, LPARAM lparam)

{

     if(wparam!=IDR_MAINFRAME)  

            return   1;  

     switch(lparam)  

     {  

     case WM_RBUTTONUP:   //右键起来时弹出快捷菜单

            {     

            LPPOINT   lpoint=new   tagPOINT;  

            ::GetCursorPos(lpoint);

           SetForegroundWindow(); //右击后点别地可以清除“右击出来的菜单”

            CMenu   menu;  

            menu.CreatePopupMenu();  //声明创建一个弹出式菜单  

          //增加菜单项“我还要改”,点击则发送消息WM_SHOW给主窗口

         //增加菜单项“从这离开”,点击则发送消息WM_EXIT给主窗口

         //添加消息按照上边步骤即可注意

         //菜单的消息是ON_COMMAND (必须在这里使用之)

         //窗口消息是ON_MESSAGE

           menu.AppendMenu(MF_STRING,WM_SHOW,"我还要改!(&A)");

           menu.AppendMenu(MF_STRING,WM_EXIT,"从这离开!(&X)");  

        //菜单显示的屏幕位置

            menu.TrackPopupMenu(TPM_LEFTALIGN, lpoint->x,lpoint->y+8,this); 

           资源回收

            HMENU hmenu=menu.Detach();  

            menu.DestroyMenu();  

            delete   lpoint;  

            }  

            break;  

     case WM_LBUTTONDBLCLK:     //双击时显示主窗口

            {  

                 this->ShowWindow(SW_SHOW);

                   this->SetForegroundWindow();         //置顶显示

            }  

            break;

     }  

     return 0;

}

其中WM_SHOW对应的消息

void CFindFileDlg::OnShow()

{

   ShowWindow(SW_SHOW);

}

其中WM_EXIT对应的消息

void CFindFileDlg::OnRealExit()

{

      Shell_NotifyIcon(NIM_DELETE, &nid);

      OnOK();

}

 截获dlg自己的最小化或者关闭按钮实现托盘程序思路如下

MFC维护着一个消息队列,每次取出一条消息进行处理。

首先想到的是要截获所有消息,对消息进行分析,如果是最大化,关闭就应该将其截获,然后做出自己的处理。

MFC消息管理提供了函数afx_msg void OnSysCommand(UINT nID,LPARAM lParam );

这样在截获消息后进行判断即可

void CFindFileDlg::OnSysCommand(UINT nID, LPARAM lParam)

{

     if ( ( nID & 0xFFF0 ) == SC_CLOSE )

{

            OnRealExit();   //在这里进行截获实现自己想实现的功能

     }

/*相应的消息参数 改变参数即可

           SC_CLOSE                                   //关闭

      SC_MAXIMIZE (or SC_ZOOM)    //最大化

      SC_MINIMIZE (or SC_ICON)      //最小化

      SC_RESTORE                            //还原

      SC_SIZE                                     //大小

    SC_MOVE                                      //移动

*/

     else

   {

            CDialog::OnSysCommand( nID, lParam );

     }

}

完毕