首页 > 代码库 > MFC实现NotifyIcon托盘应用程序

MFC实现NotifyIcon托盘应用程序

/*参考别人的做了细微修改*/

类似于QQ的托盘程序编写

1.首先我们新建一个MFC程序,在对话框Dlg类中添加一个NOTIFYICONDATA类型对象

NOTIFYICONDATA m_nid;  
2.在stdafx.h头文件中定义一个自定义消息
#define WM_SYSTEMTRAY WM_USER+1001  
3.在Dlg类中中定义一个线程函数
static DWORD WINAPI NotifyIconProc(LPVOID lpParameter);//呵呵,有人会问了这里的线程函数为什么是静态的呢??大家先思考一下!
4.在Dlg的OnInitDialog()代码中输入以下代码:
HICON m_hicon = ::LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));//加载一个托盘图标  
	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;                        //指定托盘图标  
	wcscpy_s(m_nid.szTip, _T("我的托盘"));           //添加气泡提示  
	::Shell_NotifyIcon(NIM_ADD, &m_nid);          //在托盘区添加图标   
	HANDLE hNotifyTherad = CreateThread(NULL, 0, NotifyIconProc, (LPVOID)&m_nid, 0, NULL);//创建一个线程来更新托盘图标  
	CloseHandle(hNotifyTherad);
5.在线程里面处理托盘图标切换
DWORD WINAPI CMFCApplication1Dlg::NotifyIconProc(LPVOID lpParameter)
{
	NOTIFYICONDATA *pnotifyicon = (NOTIFYICONDATA*)lpParameter;//把传递进来的指针转换  

	/////先在工程里面调入几个图标  
	HICON m_hstateicon_1 = ::LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));//加载4个图标  
	HICON m_hstateicon_2 = ::LoadIcon(AfxGetInstanceHandle(), NULL);//空图标
	HICON m_hstateicon_3 = ::LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));
	HICON m_hstateicon_4 = ::LoadIcon(AfxGetInstanceHandle(), NULL);
	////////////////////////////////////不断的切换托盘图标////////////////////////////////////////////////  
	while (true)

	{
		pnotifyicon->uFlags = NIF_ICON;
		pnotifyicon->hIcon = m_hstateicon_1;
		::Shell_NotifyIcon(NIM_MODIFY, pnotifyicon);

		Sleep(400);//400ms切换一次  

		pnotifyicon->uFlags = NIF_ICON;
		pnotifyicon->hIcon = m_hstateicon_2;
		::Shell_NotifyIcon(NIM_MODIFY, pnotifyicon);

		Sleep(400);//400ms切换一次  

		pnotifyicon->uFlags = NIF_ICON;
		pnotifyicon->hIcon = m_hstateicon_3;
		::Shell_NotifyIcon(NIM_MODIFY, pnotifyicon);

		Sleep(400);//400ms切换一次  

		pnotifyicon->uFlags = NIF_ICON;
		pnotifyicon->hIcon = m_hstateicon_4;
		::Shell_NotifyIcon(NIM_MODIFY, pnotifyicon);

		Sleep(400);//400ms切换一次  
	}
	return 0;
}
6.处理自定义消息和实现托盘菜单(托盘的产生一般是在最小化的时候,有的程序一启动也产生托盘图标,看程序的需要)

首先我们重写一下WindowProc函数,然后在WindowProc函数里面处理我们的托盘消息:

LRESULT CMFCApplication1Dlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	// TODO:  在此添加专用代码和/或调用基类
	switch (message)
	{
	case WM_SYSCOMMAND:
		if (wParam == SC_MINIMIZE)
		{
			CMFCApplication1Dlg *dlg = (CMFCApplication1Dlg*)AfxGetApp()->GetMainWnd();//获取窗口CWnd指针  
			HWND hwnd = dlg->m_hWnd;//获取h_hWnd指针  
			::ShowWindow(hwnd, 0);//隐藏界面  
			return TRUE;
		}
		if (wParam == SC_RESTORE)
		{
		}
		break;

	case WM_CLOSE:
		Shell_NotifyIcon(NIM_DELETE, &m_nid);//关闭软件时卸载托盘图标  
		break;
	case WM_SYSTEMTRAY:
	{
		if (wParam != IDR_MAINFRAME)
		    return 1;
	    switch (lParam)
		{
	    	case WM_RBUTTONUP://右键起来时弹出快捷菜单,这里只有一个"关闭"   
		    {
				CMenu menu;
				LPPOINT lpoint = new tagPOINT;
				::GetCursorPos(lpoint);     // 得到鼠标位置
				menu.CreatePopupMenu(); // 声明一个弹出式菜单
				SetForegroundWindow();//如果点击弹出菜单的时候,菜单失去焦点让菜单自动关闭
				menu.AppendMenu(MF_STRING, WM_DESTROY, _T("退出"));// 增加菜单项"关闭",点击则发送消息WM_DESTROY 给主窗口(已隐藏),将程序结束
				//此类型的菜单需要自定义消息,做消息映射和相关的消息响应函数
				menu.TrackPopupMenu(TPM_LEFTALIGN, lpoint->x, lpoint->y, this);// 确定弹出式菜单的位置
							
				HMENU hmenu = menu.Detach();
				menu.DestroyMenu();// 资源回收
				delete lpoint;// 资源回收

				Shell_NotifyIcon(NIM_DELETE, &m_nid);//关闭软件时卸载托盘图标 
				break;
		    }
		    case WM_LBUTTONDBLCLK://双击左键的处理   
		    {
				this->ShowWindow(SW_SHOW);//简单的显示主窗口完事儿  
				break;
		    }
	    	case WM_LBUTTONDOWN://单击左键的处理
		    {
			    this->ShowWindow(SW_SHOW);//简单的显示主窗口完事儿 
			    break;
			}
		}
	}
		break;
	}
	return CDialogEx::WindowProc(message, wParam, lParam);
}


*****************************************欢迎提出BUG**********************************************

MFC实现NotifyIcon托盘应用程序