MFC基于对话框的程序最小化到托盘

一、准备工作

在头文件中做的工作

1.在对话框的头文件中定义一个用户自定义消息。

该消息的用处是,当我们用鼠标点击任务栏上的图标时,图标要发出的消息,消息的接收者就是当前你写定义语句的窗体。

具体方法是:在对话框的头文件中声明消息。如下:

#endif // _MSC_VER > 1000

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

#define WM_SHOWTASK     WM_USER + 100 //定义消息的值

后面没有分号, 建议自定义消息时至少是WM_USER+100,因为很多新控件也要使用WM_USER消息。 
2.在类声明中定义消息处理函数。

还是这个头文件的下面: 

// Generated message map functions

//{{AFX_MSG(CSendInfoSocketDlg)
afx_msg LRESULT OnShowTask(WPARAM wParam, LPARAM lParam);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()

记号afx_msg并没有什么其他用途,它只是用来表明该函数原型说明是针对消息映射函数而言的。

在源文件中做的工作:

1.实现消息映射

在代码文件中还需要有一个消息映射宏,该消息映射宏用于将消息函数和应用框架联系在一起。

BEGIN_MESSAGE_MAP(ON_MESSAGE(WM_SHOWTASK, OnShowTask)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

2.实现消息处理函数(当然可以不实现)。

在Dialog源文件中添加自定义的消息响应代码,左键双击弹出应用程序主窗口,右键单击弹出菜单。

 LRESULT CSendInfoSocketDlg::OnShowTask(WPARAM wParam, LPARAM lParam)

    {

           if(wParam != IDR_MAINFRAME)

                  return 1;

           switch(lParam)

           {

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

                  {                    

                         LPPOINT lpoint = new tagPOINT;

                         ::GetCursorPos(lpoint);                    // 得到鼠标位置

                         CMenu menu;

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

                         menu.AppendMenu(MF_STRING, WM_DESTROY, "关闭");

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

                         HMENU hmenu = menu.Detach();

                         menu.DestroyMenu();

                         delete lpoint;

                  }

                  break;

           case WM_LBUTTONDBLCLK:                                 // 双击左键的处理

                  {

                         this->ShowWindow(SW_SHOWNORMAL);         // 显示主窗口

                  }

                  break;

           }

           return 0;

    }

到这里我们已经完成了定义、接收、处理消息的准备工作,接着就是如何把图标显示在任务栏中的问题了。

二、显示图标 

1.MFC对话框程序有一个默认的IDR_MAINFRAME图标,可以替换成自己喜欢的图标。

具体做法是:将先前的IDR_MAINFRAME的图标删除掉,在资源中的Icon中导入一个自己喜欢的图标,ID命名为IDR_MAINFRAME。

2.在对话框的头文件中定义一个变量NOTIFYICONDATA m_nid。

其原型为: 
typedef struct _NOTIFYICONDATA {  
DWORD cbSize; //为该结构所占的字节数 
HWND hWnd; //为接受该图标所发出的消息的窗口的句柄 
UINT uID; //为被显示图标的ID 
UINT uFlags; //指明其余的几个成员(hIcon、uCallBackMessage和szTip)的值是否有效 
UINT uCallbackMessage; //为一个用户自定义的消息(就是上面定义的那个赋给它) 
HICON hIcon; //为将在任务栏上被显示图标的句柄 
char szTip[64]; //鼠标停留在该图标上时显示的字符串 
}NOTIFYICONDATA 

3.添加消息响应函数OnInitDialog(),并在该函数中添加以下代码,这样程序一启动,就在托盘中显示出了自己应用程序的图标。

显示图标是通过这一步是利用系统API函数Shell_NotifyIcon()将一个图标显示在任务栏的通告区中。

    //---------------------------托盘显示---------------------------------//

    m_nid.cbSize  = (DWORD)sizeof(NOTIFYICONDATA);

    m_nid.hWnd    = this->m_hWnd;

    m_nid.uID     = IDR_MAINFRAME;

    m_nid.uFlags  = NIF_ICON | NIF_MESSAGE | NIF_TIP ;

    m_nid.uCallbackMessage = WM_SHOWTASK;             // 自定义的消息名称

    m_nid.hIcon   = LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));

    strcpy(m_nid.szTip, "服务器程序");                // 信息提示条为"服务器程序",VS2008 UNICODE编码用wcscpy_s()函数

    Shell_NotifyIcon(NIM_ADD, &m_nid);                // 在托盘区添加图标

4.添加关闭窗口时的消息响应函数,将托盘中的应用程序图标删除,让图标随主程序关闭消失。

具体做法是:右击对话框程序的头文件,选择“添加虚函数”菜单项,选择“DestroyWindow”,点击“Add and Edit”。在函数中添加红色部分的代码。

    BOOL CServerDlg::DestroyWindow()

    {

           // TODO: Add your specialized code here and/or call the base class

           // 在托盘区删除图标

           Shell_NotifyIcon(NIM_DELETE, &m_nid);             

           return CDialog::DestroyWindow();

    }

经过以上的步骤,就编写出了一个简单的可以最小化到托盘的程序。该程序在一启动时,在托盘创建应用程序的图标,最小化程序时隐藏主窗口,双击托盘区的图标时,显示主窗口,右键点击托盘区窗口时,弹出菜单进行相应的操作。