/*参考别人的做了细微修改*/
类似于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**********************************************
时间: 2024-10-29 21:37:14