自己是一个不善管理时间的人,有时为了一两个小程序浪费一天的时间,所以最近为自己做一个类似课程表的软件,就是我先规定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.CppCTray::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)