一个托盘程序演示 -闹钟 Alert
From:?http://www.vckbase.com/document/viewdoc/?id=996
下載源代碼
關(guān)鍵字:托盤 Tray
想必大家都看見過那些在系統(tǒng)托盤(Tray)中的程序吧,本文就演示了如何創(chuàng)建一個這樣的托盤程序Alert。Alert是一個運行在系統(tǒng)托盤中的小鬧鐘,它在設(shè)定的時間后觸發(fā),運行屏幕保護(hù)程序并播放一首歌曲。這個程序是很久以前寫的了,而我現(xiàn)在沒有安裝VC++了,所以本文的截圖都是朋友Leoyin幫我做出來后傳給我的(好麻煩,呵呵),在此也對他表示感謝!
建立一個托盤程序的關(guān)鍵在于Windows API-Shell_NotifyIcon()的使用,這個API的聲明包含在ShellAPI.H文件中。請在StdAfx.h中使用“#include <ShellAPI.H>”將其引入工程,別象我當(dāng)時那么傻-在工程管理器里引入了該文件,導(dǎo)致現(xiàn)在你們在類視圖中看見了許多不希望看到的東西。我現(xiàn)在也沒有VC++ IDE來修改它了,就這樣吧。
首先,給大家介紹一下相關(guān)的函數(shù)和結(jié)構(gòu):Shell_NotifyIcon()的原型和說明(最新版)如下:
dwMessage :[輸入?yún)?shù)] 說明要執(zhí)行的動作。動作的可選值如下:
- NIM_ADD 增加一個圖標(biāo)到托盤區(qū)
- NIM_DELETE 從托盤區(qū)刪除一個圖標(biāo)
- NIM_MODIFY 修改圖標(biāo)
- NIM_SETFOCUS 將焦點(Focus)返回托盤區(qū)。這個消息通常在托盤區(qū)圖標(biāo)完成了用戶界面下的操作后發(fā)出。比如一個托盤圖標(biāo)顯示了一個快捷菜單,然后用戶按下ESC鍵了操作,這時使用NIM_SETFOCUS將焦點繼續(xù)保留在托盤區(qū)。該項僅在系統(tǒng)外殼與常用控制DLL( Shlwapi.dll與Comctl32.dll)5.0以上版本才可用。
- NIM_SETVERSION 指定使用特定版本的系統(tǒng)外殼與常用控制DLL。缺省值為0,表示使用Win95方式。該項僅在系統(tǒng)外殼與常用控制DLL 5.0以上版本才可用。
返回值: 成功時函數(shù)返回TRUE,否則FALSE。
NOTIFYICONDATA ?結(jié)構(gòu)的說明(最新版)如下:
typedef struct _NOTIFYICONDATA {DWORD cbSize;HWND hWnd;UINT uID;UINT uFlags;UINT uCallbackMessage;HICON hIcon;TCHAR szTip[64];DWORD dwState;DWORD dwStateMask;TCHAR szInfo[256];union {UINT uTimeout;UINT uVersion;};TCHAR szInfoTitle[64];DWORD dwInfoFlags;GUID guidItem; } NOTIFYICONDATA, *PNOTIFYICONDATA;
| cbSize | 以字節(jié)計的結(jié)構(gòu)大小,以適應(yīng)不同版本。 |
| hWnd | 接收Windows消息的窗口句柄。 |
| uID | 托盤圖標(biāo)的ID。 |
| uFlags | 指示結(jié)構(gòu)中的哪些成員包含有效數(shù)據(jù),可選值:NIF_ICON, NIF_MESSAGE,NIF_TIP,NIF_STATE,NIF_INFO,NIF_GUID。 |
| uCallbackMessage | 回調(diào)消息ID,由用戶自定義。與一個自定義的消息處理函數(shù)關(guān)聯(lián)。 |
| hIcon | 托盤圖標(biāo)的句柄。 |
| szTip | 托盤圖標(biāo)的提示字符串。 |
| 注意:以下數(shù)據(jù)成員僅限系統(tǒng)外殼與常用控制DLL?5.0及以上版本才有效! | |
| dwState | 圖標(biāo)的狀態(tài):NIS_HIDDEN-隱藏,或NIS_SHAREDICON-可視。 |
| dwStateMask | 圖標(biāo)狀態(tài)掩碼,用以設(shè)置dwState |
| szInfo | 氣球型提示(Balloon ToolTip)的字符串。 |
| uTimeout | 以毫秒計的提示顯示時間 |
| uVersion | 確定所依賴的版本。0-Win95,NOTIFYICON_VERSION-Win2000 |
| szInfoTitle | 氣球型提示的標(biāo)題 |
| dwInfoFlags | 設(shè)置氣球型提示所用的圖標(biāo)(類似MessageBox中所使用的圖標(biāo)):
|
| guidItem | 6.0版本保留 |
接下來,讓我們開始實現(xiàn)這個Alert吧。Alert是一個基于對話框的Win32應(yīng)用程序,利用AppWizard 創(chuàng)建它吧。然后設(shè)計一下這個對話框如圖:
?
在AlertDlg.H中加入: #include < mmsystem.h > //這個頭文件是干什么的記不得了,呵呵#define WM_NOTIFYICON WM_USER+5 //自定義消息的ID #define IDI_ICON 0x0005 //圖標(biāo)ID #define IDT_APPLY WM_USER+6 //我要使用的定時器Timer的自定義消息ID
然后為類CAlertDlg添加數(shù)據(jù)成員m_Interval和自定義成員函數(shù)的聲明(怎么添加不用我教了吧?)。最后形成CAlertDlg類的聲明(已去掉了一些注釋)如下:
class CAlertDlg : public CDialog { public:~CAlertDlg();CAlertDlg(CWnd* pParent = NULL);enum { IDD = IDD_ALERT_DIALOG };int m_Interval; //定時間隔,以分鐘為單位protected:virtual void DoDataExchange(CDataExchange* pDX);protected:void ShowMessage(void); //自定義的定時觸發(fā)時運行的函數(shù)HICON m_hIcon; //圖標(biāo)句柄virtual BOOL OnInitDialog();afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();afx_msg void OnClickApply(); //"應(yīng)用"按鈕的點擊消息處理函數(shù)virtual void OnCancel(); //"退出"按鈕的點擊消息處理函數(shù)afx_msg void OnTimer(UINT nIDEvent); //定時器消息處理函數(shù)afx_msg void OnClickHide(); //"隱藏"按鈕的點擊消息處理函數(shù)//自定義WM_NOTIFYICON消息的處理函數(shù)afx_msg void OnNotifyIcon(WPARAM wParam, LPARAM lParam); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); //系統(tǒng)消息處理函數(shù)afx_msg BOOL OnQueryEndSession(); //Windows關(guān)閉消息處理函數(shù)DECLARE_MESSAGE_MAP() };
以下是AlertDlg.CPP中相應(yīng)函數(shù)的實現(xiàn)(還是設(shè)置點錨點吧):
BOOL CAlertDlg::OnInitDialog() {SetIcon(m_hIcon, TRUE);SetIcon(m_hIcon, FALSE);// 初始化時間間隔CSpinButtonCtrl * pSpin;pSpin = (CSpinButtonCtrl *) GetDlgItem(IDC_SPIN);pSpin->SetRange(5,150);m_Interval = 30;CDialog::OnInitDialog();// 設(shè)置定時器,每秒一次心跳SetTimer(1, 1000, NULL);// 將圖標(biāo)放入系統(tǒng)托盤NOTIFYICONDATA nd;nd.cbSize = sizeof (NOTIFYICONDATA);nd.hWnd = m_hWnd;nd.uID = IDI_ICON;nd.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP;nd.uCallbackMessage= WM_NOTIFYICON;nd.hIcon = m_hIcon;strcpy(nd.szTip, "我的鬧鐘");Shell_NotifyIcon(NIM_ADD, &nd);return TRUE; }void CAlertDlg::OnClickApply() {// 重置時間間隔UpdateData();OnTimer(IDT_APPLY); }void CAlertDlg::OnCancel() {// 釋放定時器KillTimer(1);// 將圖標(biāo)從系統(tǒng)托盤中刪除NOTIFYICONDATA nd;nd.cbSize = sizeof (NOTIFYICONDATA);nd.hWnd = m_hWnd;Shell_NotifyIcon(NIM_DELETE, &nd);CDialog::OnCancel(); }void CAlertDlg::OnTimer(UINT nIDEvent) {static CString strTemp;static int Count = 0;COleDateTime dtTime;// 刷新顯示的時間//常在論壇里遇到人問怎么獲得當(dāng)前時間,這相知道了吧?dtTime = COleDateTime::GetCurrentTime(); strTemp.Format("現(xiàn)在時間 %02i:%02i:%02i ",dtTime.GetHour(),dtTime.GetMinute(),dtTime.GetSecond());GetDlgItem(IDC_CURTIME)->SetWindowText(strTemp);// 刷新剩余時間值if (nIDEvent == IDT_APPLY) Count = 0; //若用戶重新定義了時間間隔,則重新開始計時Count++;int RestTime;RestTime = m_Interval - Count/60;if (RestTime <= 0) {Count = 0;ShowMessage();}strTemp.Format("離下次提醒還差 %i 分鐘", RestTime);GetDlgItem(IDC_RESTTIME)->SetWindowText(strTemp); CDialog::OnTimer(nIDEvent); }//這個ShowMessasge()函數(shù),你們需要自己修改一下,我的代碼太死板了 void CAlertDlg::ShowMessage() {//調(diào)用C:\InfoCD\WinaMP\下的WinaMP3播放Music.m3u清單::WinExec("C:\\INFOCD\\WINAMP\\WINAMP.EXE music.m3u",SW_HIDE);MessageBox("您該休息一會兒了......", "休息", MB_SYSTEMMODAL|MB_OK|MB_ICONEXCLAMATION|MB_ICONWARNING);//運行C:\Windows\System下的太空屏保ShellExecute(m_hWnd,"open","C:\\WINDOWS\\SYSTEM\\太空.scr", NULL,NULL,SW_SHOWNORMAL); }afx_msg void CAlertDlg::OnNotifyIcon(WPARAM wParam, LPARAM lParam) {// 響應(yīng)在托盤圖標(biāo)上的單擊//wParam中是響應(yīng)消息的圖標(biāo)ID,lParam中則是Windows的消息if ((wParam == IDI_ICON)&&(lParam == WM_LBUTTONDOWN))ShowWindow(SW_SHOWNORMAL); }void CAlertDlg::OnSysCommand(UINT nID, LPARAM lParam) {// 屏蔽最大化(MFC Bug?),將最小化重定向至隱藏窗口if (nID == SC_MAXIMIZE)return;if (nID == SC_MINIMIZE)ShowWindow(SW_HIDE);elseCWnd::OnSysCommand(nID, lParam); }BOOL CAlertDlg::OnQueryEndSession() {// 在用戶退出Windows時自動退出應(yīng)用程序CAlertDlg::OnCancel();return TRUE; }void CAlertDlg::OnClickHide() {OnSysCommand(SC_MINIMIZE, 0x0000);return; }
好了,通過閱讀上面這些源代碼,我想大家對托盤程序的創(chuàng)建有了一定的認(rèn)識了吧,這也是本文的根本目的。 只是這個程序有個Bug:在程序退出后圖標(biāo)仍在托盤區(qū)顯示,要把鼠標(biāo)在圖標(biāo)上面過一下才會消失。這個Bug記得有人提出過解決辦法,好象是要釋放圖標(biāo)句柄什么的。可惜我記不得了,這個程序也沒有再修改。?
衷心希望大家給我回復(fù),謝謝!
參考文章:
1、MSDN中的相關(guān)鏈接: The Taskbar , TrayNot Sample ,
2、VCKBase里也有不少優(yōu)秀文章(比如NorthTibet編譯的“ 系統(tǒng)托盤編程完全指南 ”)。
在硬盤版的MSDN還會有相應(yīng)的專題文章,自己搜搜吧。
總結(jié)
以上是生活随笔為你收集整理的一个托盘程序演示 -闹钟 Alert的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微软2014编程之美初赛第一场——题目3
- 下一篇: PS1参数详解