自己是一个不善管理时间的人,有时为了一两个小程序浪费一天的时间,所以最近为自己做一个类似课程表的软件,就是我先规定XX点到XX点要干什么,把一天的计划输入进去,到时间分界点时,我的软件会自动提醒我该时间段到了,该进入下一个工作阶段。规化一下整个系统后决定系统启动后以托盘图标的形式工作,用防QQ右下角弹出信息+声音的方式来提醒自己。最近对设计模式和重构细心研究了一下,所以把能完成一系列工作的东东都封成类,而不是像以前直接在MFC的对话框里写代码。于是写下此类,简单易懂易操作。只是我也在测试(其实我测我的C++程序主要是测内存)。
废话多了,别见怪,进入正题。老习惯,先放代码再解释 第一步,建立系统托盘类 Tray.h #include "stdafx.h" #pragma once #include "PopDlg.h" class CTray { public: CTray(void); ~CTray(void); private: NOTIFYICONDATA m_NotifyIconData; //定义标识托盘是否可用 bool m_bIsEnable; //弹出对话框变量(就是用MFC添加一个对话框,然后用该对话框生成的一个类CPopDlg) CPopDlg m_popDlg; public: /* 函数名:创建托盘 参数: nMenuId: 托盘菜单ID pWnd:程序窗口指针 uCallbackMessage:托盘消息ID szTip:鼠标经过托盘时显示的文字 icon:托盘图标 */ void CreateTray(UINT nMenuId, CWnd* pWnd, UINT uCallbackMessage, LPCTSTR szTip, HICON icon); //处理托盘图标事件 LRESULT OnShowTask(WPARAM wParam, LONG lParam); //删除托盘 void DelTray(); }; Tray.Cpp CTray::CTray(void) { } CTray::~CTray(void) { DelTray(); } void CTray::CreateTray(UINT nMenuId, CWnd* pWnd, UINT uCallbackMessage, LPCTSTR szTip, HICON icon) { //创建弹出对话框 m_popDlg.Create(ID_DLG_POP,pWnd); //定义托盘 m_NotifyIconData.cbSize = (DWORD)sizeof(NOTIFYICONDATA); m_NotifyIconData.hWnd = pWnd->GetSafeHwnd(); m_NotifyIconData.uID = nMenuId; m_NotifyIconData.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP; m_NotifyIconData.uCallbackMessage = uCallbackMessage; m_NotifyIconData.hIcon = icon; strcpy(m_NotifyIconData.szTip,szTip); Shell_NotifyIcon(NIM_ADD, &m_NotifyIconData); m_bIsEnable = true; } //删除托盘 void CTray::DelTray() { if(m_bIsEnable) { Shell_NotifyIcon(NIM_DELETE,&m_NotifyIconData); m_popDlg.DestroyWindow(); m_bIsEnable = false; } } //处理菜单 LRESULT CTray::OnShowTask(WPARAM wParam, LONG lParam) { static int i = 0; if(wParam != m_NotifyIconData.uID) return 1; else { if(LOWORD(lParam) == WM_LBUTTONDOWN) { //点击图标左键,弹出对话框 int x= GetSystemMetrics(SM_CXSCREEN); int y= GetSystemMetrics(SM_CYSCREEN); ::SetWindowPos( m_popDlg.m_hWnd ,NULL,x-349,y-234,349,207,SWP_NOACTIVATE ); ::AnimateWindow( m_popDlg.m_hWnd ,1000,AW_VER_NEGATIVE|AW_SLIDE); } if (LOWORD(lParam) == WM_RBUTTONUP) { //右键弹出菜单 CMenu menu, *pSubMenu; //加载菜单 if(!menu.LoadMenu(m_NotifyIconData.uID)) { return 1; } //加载菜单中的第一项 if(!(pSubMenu = menu.GetSubMenu(0))) { return 1; } CPoint pos; ::GetCursorPos(&pos); ::SetForegroundWindow(m_NotifyIconData.hWnd); //设置菜单的显示位置 ::TrackPopupMenu(pSubMenu->m_hMenu,0,pos.x,pos.y,0,m_NotifyIconData.hWnd,NULL); menu.DestroyMenu(); } } return 0; } 第二步,让托盘接管系统消息,操作如下。 在主程序对话框头文件中定义一个消息。 定义一个消息ID #define WM_SHOW_TASK WM_USER+100 类中添加一个消息声明 afx_msg LRESULT OnShowNotify(WPARAM wParam, LPARAM lParam); 在 对话框源文件中添加映射及处理 BEGIN_MESSAGE_MAP(CAngleMemoryDlg, CDialog) ON_MESSAGE(WM_SHOW_TASK,OnShowNotify) END_MESSAGE_MAP() //响应托盘菜单 LRESULT CAngleMemoryDlg::OnShowNotify(WPARAM wParam, LPARAM lParam) { return m_tray.OnShowTask(wParam, lParam); } 第三步,测试代码 在主程序对话框的头文件中定义CTray m_tray, 在对话框中加一个按钮,消息中代码加入: m_tray.CreateTray(ID_MENU_SYS,this, WM_SHOW_TASK,"娃子的计划",this->m_hIcon); this->ShowWindow(SW_HIDE); 到此系统托盘和弹出对话框就做好了。可以先测试一下。 |
(转自http://hi.baidu.com/anglecloudy/blog/item/218c963def1adae63c6d9769.html)