系統(tǒng)托盤編程完全指南一
《系統(tǒng)托盤編程完全指南一》由會員分享,可在線閱讀,更多相關(guān)《系統(tǒng)托盤編程完全指南一(7頁珍藏版)》請在裝配圖網(wǎng)上搜索。
1、文檔供參考,可復(fù)制、編制,期待您的好評與關(guān)注! 系統(tǒng)托盤編程完全指南(一) 編譯/northtibet ??? 自從Windows 95面市以來,系統(tǒng)托盤應(yīng)用作為一種極具吸引力的UI深受廣大用戶的喜愛。使用系統(tǒng)托盤UI的Windows應(yīng)用程序數(shù)不勝數(shù),比如"金山詞霸"、"Winamp"、"RealPlayer"等等。那么如何編寫自己的托盤應(yīng)用呢?本文是系列文章中的第一篇,這些文章將比較系統(tǒng)地描述托盤應(yīng)用的編程。并創(chuàng)建自己的C++類來增強系統(tǒng)托盤應(yīng)用的特性。讀完這些文章,再參照例子,相信讀者能輕松自如地在自己的程序中應(yīng)用系統(tǒng)托盤。 ??? 大家知道,MFC框架沒有提供任何現(xiàn)成的類應(yīng)用
2、于系統(tǒng)托盤UI,那么如何將表示應(yīng)用程序的圖標添加到任務(wù)欄中呢?方法很簡單,只用到一個API函數(shù),它就是Shell_NotifyIcon。這個函數(shù)本身也相當容易理解和使用??纯此脑途椭懒耍? BOOL Shell_NotifyIcon( DWORD dwMessage, PNOTIFYICONDATA pnid ); 第一個參數(shù)dwMessage類型為DWORD,表示要進行的動作,它可以是下面的值之一: NIM_ADD: 添加一個圖標到任務(wù)欄。 NIM_MODIFY: 修改狀態(tài)欄區(qū)域的圖標。
3、 NIM_DELETE: 刪除狀態(tài)欄區(qū)域的圖標。 NIM_SETFOCUS: 將焦點返回到任務(wù)欄通知區(qū)域。當完成用戶界面操作時,任務(wù)欄圖標必須用此消息。例如,如果任務(wù)欄圖標正 顯示上下文菜單,但用戶按下"ESCAPE"鍵取消操作,這時就必須用此消息將焦點返回到任務(wù)欄通知區(qū)域。 NIM_SETVERSION:指示任務(wù)欄按照相應(yīng)的動態(tài)庫版本工作。 第二個參數(shù)pnid是NOTIFYICONDATA結(jié)構(gòu)的地址,其內(nèi)容視dwMessage的值而定。這個結(jié)構(gòu)在SHELLAPI.H文件中定義如下:
4、 typedef struct _NOTIFYICONDATA { DWORD cbSize; // 結(jié)構(gòu)大小(sizeof struct),必須設(shè)置 HWND hWnd; // 發(fā)送通知消息的窗口句柄 UINT uID; // 圖標ID ( 由回調(diào)函數(shù)的WPARAM 指定) UINT uFlags; UINT uCallbackMessage; // 消息被發(fā)送到此窗口過程 HICON hIcon; // 圖標句柄 CHA
5、R szTip[64]; // 提示文本 } NOTIFYICONDATA; uFlags的值: #define NIF_MESSAGE 0x1 // 表示uCallbackMessage 有效 #define NIF_ICON 0x2 // 表示hIcon 有效 #define NIF_TIP 0x4 // 表示szTip 有效 有關(guān)Shell_NotifyIcon函數(shù)的詳細使用細節(jié)請參考MSDN。 ??? NOTIFYICONDATA結(jié)構(gòu)中的 hWnd 是"擁有" 圖標的窗口句柄。uID可以是任何標示托盤圖標的ID(如果
6、有多個圖標),一般使用資源ID。HIcon可以是任何圖標的句柄,包括預(yù)定義的系統(tǒng)圖標,如IDI_HAND、IDI_QUESTION、IDI_EXCLAMATION、或者Windows的徽標IDI_WINLOGO。 ??? 圖標的顯示并不難,關(guān)鍵是事件的處理。 當用戶將鼠標移到圖標上或者在圖標上單擊鼠標時,為了得到通知消息,你可以將自己的消息ID賦給uCallbackMessage,并設(shè)置NIF_MESSAGE標志。當用戶在圖標上移動或單擊鼠標時,Windows將用hWnd指定的窗口句柄調(diào)用你建立的窗口過程;消息ID在uCallbackMessage中指定,uID的值即為wParam,lPar
7、am為鼠標事件,如WM_LBUTTONDOWN等。 ??? 盡管Shell_NotifyIcon函數(shù)簡單實用。但它畢竟是個Win32 API,為此我將它封裝在了一個C++類中,這個類叫做CTrayIcon,有了它,托盤編程會更加輕松自如,因為它隱藏了NOTIFYICONDATA、消息代碼、標志以及所有那些你必須要看MSDN才能搞掂的繁瑣細節(jié)。CTrayIcon的定義以及實現(xiàn)細節(jié)請下載源代碼參考。CTrayIcon為程序員提供了一個更加友好的托盤編程接口,它除了對Shell_NotifyIcon函數(shù)進行打包之外,它還是一個迷你框架呢!之所以這么說,是因為按照Windows系統(tǒng)應(yīng)用軟件界面指南所
8、提倡的原則(這個指南可以在MSDN中找到),這個類增強了托盤圖標的用戶界面行為。以下便是CTrayIcon最終實現(xiàn)的UI特性: 1、 托盤圖標應(yīng)該有信息提示,也就是ToolTips。 2、 單擊右鍵應(yīng)該彈出上下文菜單,這個菜單中應(yīng)包含打開屬性頁的命令或者打開與圖標相關(guān)的其它窗口的命令。 3、 單擊左鍵應(yīng)該顯示進一步的信息或者控制圖標所代表的對象,例如,當左鍵單擊聲音圖標時進行音量控制。如果沒有進一步的信息或控制,則不要有任何動作。 ??? CTrayIcon對上面的特性進行了全面的封裝。為了示范CTrayIcon的工作原理,本文提供一個例子程序TrayTest1,圖一是運行程序
9、后顯示的一個對話框: 圖一 TrayTest1運行后顯示的對話框 當把圖標安裝到系統(tǒng)托盤之后,如果雙擊托盤圖標,程序會彈出一個消息列表窗口,只要你的鼠標在托盤圖標上移動或點擊(無論是左右鍵的單擊或雙擊),產(chǎn)生的消息都會顯示在這個窗口里,如圖二: 圖二 消息顯示窗口 當鼠標光標移到托盤圖標上時,在圖標附近會顯示提示信息,如圖三: 圖三 顯示Tooltip 為了正確使用CTrayIcon,首先你必須在程序的某個地方實例化CTrayIcon,例子程序是在主框架中創(chuàng)建CTrayIcon實例的。 Class MainFrame public
10、CFrameWnd {protected: CTrayIcon m_trayIcon; // my tray icon ……. }; ??? 然后,你必須提供一個ID。這是在圖標生命期內(nèi)的唯一標示,即便以后你修改了要顯示的圖標。這個ID也是鼠標事件發(fā)生時你將獲得的ID。它不一定必須是圖標的資源ID,例子程序中這個ID為IDR_TRAYICON,由框架的構(gòu)造函數(shù)CMainFrame通過成員初始化列表對m_trayIcon進行初始化: CMainFrame::CMainFrame() : m_trayIcon(IDR_TRAYICON)
11、{ …… } 為了添加圖標,必須根據(jù)具體情況調(diào)用下列的 SetIcon 函數(shù)之一: m_trayIcon.SetIcon(IDI_MYICON); //資源 ID m_trayIcon.SetIcon("myicon"); //資源名 m_trayIcon.SetIcon(hicon); //HICON m_trayIcon.SetStandardIcon(IDI_WINLOGO);//系統(tǒng)圖標 ??? 除了SetIcon(UINT uID)之
12、外,這些函數(shù)都有一個LPCSTR類型的可選參數(shù)用于指定提示文本。SetIcon(UINT uID)使用ID與uID相同的串資源作為提示文本。例如,TrayTest1有一行代碼是這樣的: // (在mainframe.cpp文件中) m_trayIcon.SetIcon(IDI_MYICON); 這行代碼也設(shè)置了提示信息,因為TrayTest1有一個串資源,其ID也是IDI_MYICON。這在TRAYTEST.RC文件中可以看到: STRINGTABLE PRELOAD DISCARDABLE BEGIN IDI_MYICON "雙擊圖標激活 TRAYT
13、EST." END ??? 如果你想改變圖標,可以用不同的ID或者HICON再次調(diào)用SetIcon函數(shù)之一。CTrayTest便會用NIM_MODIFY而不是NIM_ADD來改變圖標。相同的函數(shù)甚至可以用于刪除圖標,如: m_trayIcon.SetIcon(0); //刪除圖標 ??? CTrayIcon將此代碼解釋成NIM_DELETE。你已經(jīng)看到,所有這些表示行為的編碼,標志都被一個使用方便的函數(shù)所替代:這都歸功于C++!現(xiàn)在,我們來看看如何處理通知消息以及前面提到的所有UI特性。通知消息的處理必須要設(shè)置圖標之前,但是要在創(chuàng)建窗口之后調(diào)用CTrayIc
14、on::SetNotificationWnd,做這件事情的最佳場所是在OnCreate處理例程中,TrayTest就是在這里處理的: // 注冊用于托盤的自定義消息 #define WM_MY_TRAY_NOTIFICATION WM_USER+0 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { …… // 請通知我 m_trayIcon.SetNotificationWnd(this, WM_MY_TRAY_NOTIFICATION);
15、 m_trayIcon.SetIcon(IDI_MYICON); return 0; } 消息一旦注冊,接下來你便可以用通常的消息映射方式處理托盤通知消息。 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_MESSAGE(WM_MY_TRAY_NOTIFICATION, OnTrayNotification) // (or ON_REGISTERED_MESSAGE) END_MESSAGE_MAP() LRESULT CMai
16、nFrame::OnTrayNotification(WPARAM wp, LPARAM lp) { …… // 顯示消息 …… return m_trayIcon.OnTrayNotification(wp, lp); } ??? 當消息處理器得到控制,WPARAM的值是在構(gòu)造CTrayIcon時指定的ID;LPARAM為鼠標事件(如WM_LBUTTONDOWN)。當你得到通知消息后,可以做任何想做的的事情;例子程序TrayTest此時是顯示通知信息,細節(jié)請參考源代碼。完成消息的處理之后,調(diào)用CTrayIcon:
17、:OnTrayNotification進行缺省處理。此虛擬函數(shù)(所以你可以改寫)實現(xiàn)我前面提到過的缺省的UI行為。尤其是處理WM_LBUTTONDBLCLK和WM_RBUTTONUP。CTrayIcon尋找與圖標ID相同的某個菜單(如IDR_TRAYICON),如果找到,則當用戶右鍵單擊圖標時CTrayIcon顯示這個菜單;當用戶數(shù)雙擊圖標時,CTrayIcon執(zhí)行第一個菜單命令。只有兩件事情需要進一步交待: ??? 第一件事情是:在顯示菜單之前,CTrayIcon讓第一個菜單項為默認,所以它以黑體顯示。但如何用黑體來顯示某個菜單項呢?我在\MSDEV\INCLUDE\*.H搜索了一番,發(fā)現(xiàn)
18、了Get/SetMenuDefaultItem。這個函數(shù)沒有相關(guān)的CMenu打包類,所以我必須直接調(diào)用它們。 // 讓第一個菜單項為默認(黑體): ::SetMenuDefaultItem(pSubMenu->m_hMenu, 0, TRUE); ??? 這里0表示第一個菜單項,TRUE說明用位置表示菜單項的ID。為什么MFC沒有打包Get/SetMenuDefaultItem函數(shù)呢?微軟的家伙們解釋那是因為這些函數(shù)(其它的還有::Get/SetMenuItemInfo, ::LoadImage等)還沒有在最新的Windows版本中實現(xiàn)。一旦在最新的Windows版本中實
19、現(xiàn)了,便會馬上添加到MFC中。 ??? 第二件事情是上下文菜單的顯示: ::SetForegroundWindow(m_nid.hWnd); ::TrackPopupMenu(pSubMenu->m_hMenu, ...); ??? 為了讓TrackPopupMenu在托盤的上下文中正確運行,你必須首先調(diào)用SetForegroundWindow,否則,當用戶按下ESCAPE鍵或者在菜單之外單擊鼠標時,菜單不會消失。為解決這個問題,我花費了數(shù)個小時,最后還是在MSDN上找到了解決方法。為了解詳情,請參考MSDN的Q135788。最讓我哭笑不得的是我花了那么多時間來
20、關(guān)注這個問題,最后微軟的這幫家伙在MSDN上給你來了一個問題的結(jié)論是:“This behavior is by design.....”真是氣剎人也。 ??? 正如你所看到的,CTrayIcon使得托盤應(yīng)用的編程變得易如反掌。TrayTest1要做的事情不外乎調(diào)用CTrayIcon::OnTrayNotification實現(xiàn)一個通知消息處理器,提供一個與圖標ID相同的菜單。就這么簡單。 // (TRAYTEST.RC文件) IDR_TRAYICON MENU DISCARDABLE BEGIN POPUP "托盤(&T)" BEGIN MENU
21、ITEM "打開(&O)", ID_APP_OPEN MENUITEM "關(guān)于 TrayTest(&A)...", ID_APP_ABOUT MENUITEM SEPARATOR MENUITEM "退出TrayTest 程序(&S)", ID_APP_SUSPEND END END 當用戶在托盤圖標上單擊右鍵,CTrayIcon顯示這個菜單,如圖四所示。如果用戶雙擊圖標,CTrayIcon執(zhí)行第一個菜單命令:“打開”,此時激活TrayTest(正常狀
22、態(tài)下是隱藏的)。為了終止TrayTest1,你必須選擇"Suspend TRAYTEST"菜單項。如果你從“文件|退出”退出,或者關(guān)閉TrayTest1主窗口,TrayTest1不會真正關(guān)閉,它只是將自己隱藏起來。這個行為是TrayTest1改寫了CMainframe::OnClose實現(xiàn)的。 圖四 TRAYTEST1 托盤圖標菜單 ??? 最后,我想說明一個很讓人擔(dān)心的問題,每個人在看到這個小圖標后都想盡快的在自己的程序中加入托盤圖標。作為程序員,這完全是可以理解的。當自己的程序中成功添加了托盤圖標,在朋友們中間炫耀一番,那種感覺確實很好。但是要記住:并不是所有的應(yīng)用都需要
23、用托盤圖標,如果不是必須就不要畫蛇添足,否則托盤圖標太多必然造成屏幕垃圾,看看下面圖五吧: 圖五 托盤圖標程序“噩夢版” 看到這么多的托盤圖標對于用戶來說簡直就是噩夢。(待續(xù)) 我按照上面介紹的步驟去作,為什么在我點擊界面右上角的關(guān)閉按鈕,桌面右下角的圖標也一并消失了,整個就是完全退出.但是例子中的不是會仍有圖標顯示在桌面右下角嗎?請指點^_^ ( dahui11 發(fā)表于 2004-7-2 9:52:00) ? 可是就算是注銷掉也編譯ok啊。 但是啟動界面和程序界面同時出現(xiàn),這個問題怎樣解決? ( 艾葭 發(fā)表于 2003-8-11 9:08:00) ?
24、把GetSystemWindowsDirectory改成GetSystemDirectory ( liron 發(fā)表于 2002-12-25 8:21:00) ? 調(diào)試的時候會出錯,提示 D:...\StatLink.cpp(179)?:?error?C2065:?'GetSystemWindowsDirectory'?:?undeclared?identifier??Error?executing?cl.exe. 把GetSystemWindowsDirectory改成GetWindowsDirectory 就ok了。 ( seaboyf 發(fā)表于 2002-12-24 16:51:00) ? 7 / 7
- 溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 6.煤礦安全生產(chǎn)科普知識競賽題含答案
- 2.煤礦爆破工技能鑒定試題含答案
- 3.爆破工培訓(xùn)考試試題含答案
- 2.煤礦安全監(jiān)察人員模擬考試題庫試卷含答案
- 3.金屬非金屬礦山安全管理人員(地下礦山)安全生產(chǎn)模擬考試題庫試卷含答案
- 4.煤礦特種作業(yè)人員井下電鉗工模擬考試題庫試卷含答案
- 1 煤礦安全生產(chǎn)及管理知識測試題庫及答案
- 2 各種煤礦安全考試試題含答案
- 1 煤礦安全檢查考試題
- 1 井下放炮員練習(xí)題含答案
- 2煤礦安全監(jiān)測工種技術(shù)比武題庫含解析
- 1 礦山應(yīng)急救援安全知識競賽試題
- 1 礦井泵工考試練習(xí)題含答案
- 2煤礦爆破工考試復(fù)習(xí)題含答案
- 1 各種煤礦安全考試試題含答案