系統托盤編程完全指南(二)

來源:互聯網
上載者:User

(來源:http://www.vckbase.com/document/viewdoc/?id=495

 

在本文的第一部分

我們討論並示範了如何在自己的程式中應用系統托盤表徵圖。通過使用自己建立的一個可重用的
C++
類——CTrayIcon,我們可以輕鬆地實現托盤程式。不久以前我用這個類編寫了一個程式,開始運行很正常,但是有一次不知什麼原因Windows資源
管理器死掉了,也就是說非正常關閉,重啟資源管理員後,發現托盤程式仍然在運行,但托盤表徵圖顯示不出來,在工作列中看不到托盤表徵圖,只有重新啟動機器才能
重新顯示出托盤表徵圖,讓人覺得心裡很不舒服,有沒有什麼辦法在這個時候不用重啟機器而讓Windows自動找回托盤表徵圖並把它添加到工作列呢?,也就是讓
它自動回復托盤表徵圖程式的使用者介面,經過一番研究,終於有所收穫。

    實際上,如果你用的作業系統是Windows
98或者你安裝了IE4.0的案頭。那麼不論什麼時候,只要IE4.0啟動了工作列,那麼它就會向所有最頂層父視窗廣播一個註冊消
息:TaskbarCreated。有了這個線索,你就可以重新建立表徵圖。如果你用MFC編程,那麼只要定義一個全程變數儲存這個註冊訊息並實現
ON_REGISTERED_MESSAGE訊息處理常式即可:

const UINT WM_TASKBARCREATED = 
::RegisterWindowMessage(_T("TaskbarCreated"));

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_REGISTERED_MESSAGE(WM_TASKBARCREATED,
OnTaskBarCreated)
END_MESSAGE_MAP(CMainFrame, CFrameWnd)
The handler itself should reinstall whatever icons you need.

LRESULT CMainFrame::OnTaskBarCreated(WPARAM wp, LPARAM lp)
{
VERIFY(InstallIcons());
return 0;
}

BOOL CMainFrame::InstallIcons()
{
NOTIFYICONDATA nid;
//
// 準備 nid 參數
//
return Shell_NotifyIcon(NIM_ADD, &nid);

    難道就這麼容易嗎?當然不是,你必須單獨實現InstallIcons函數,而不是直接從OnTaskBarCreated中調用Shell_NotifyIcon,因為一般來說,在應用程式啟動的時候你也會調用它。

   
當我搞清楚TaskbarCreated的奧秘之後,我便回到本文第一部分中建立的那個CTrayIcon類,對它進行了修改和完善,改動不是很大。這個
類管理的是單個的托盤表徵圖(如果你有多個,那麼為每個表徵圖建立一個單獨的執行個體吧)。使用CTrayIcon時,你只要在CMainFrame中建立一個實
例m_trayIcon並象下面這樣安裝它即可:

// 在CMainFrame::OnCreate中
m_trayIcon.SetNotificationWnd(this,
WM_MY_TRAY_NOTIFICATION);
m_trayIcon.SetIcon(IDI_MYICON);

    WM_MY_TRAY_NOTIFICATION
是自己的私人訊息,只在有事件發生時,托盤表徵圖才發送此訊息,如使用者單擊表徵圖。對於托盤表徵圖來說,你不用對它做什麼處理,CTrayIcon全權負責。只
是在構造CTrayIcon對象時,你給它一個資源ID就可以了。CTrayIcon用這個ID尋找操作功能表,如果找到的話,它便自動處理按右鍵托盤
表徵圖事件,這時彈出操作功能表。如果使用者雙擊表徵圖,CTrayIcon則執行第一個功能表項目命令。所以你要做的全部工作只是建立一個菜單資源,將ID傳遞給
建構函式,然後去驅動CTrayIcon就可以了。如果你想要一些非標準的常式,那麼只需處理WM_MY_TRAY_NOTIFICATION即可。有關
細節請參考原始碼。

   
為了實現表徵圖自動重建特性,我使用了以前很多文章中都用到的一個類CSubclassWnd,這個類在我的編程生涯中幾乎無處不在。沒有了它,我幾乎寸步
難行;在我的所有編程訣竅中,它是最有用的一個類。用這個類可以截獲Windows訊息,並將它發送到另外一個視窗訊息處理常式中處理,而不是發送到
Windows自己預設的訊息處理函數。CTrayIcon用它來截獲TaskbarCreated訊息,所以你就不必為此編寫訊息處理器——這個方法非
常酷。CSubclassWnd通過安裝它自己的視窗過程,從而先於MFC一步對訊息進行處理。

   
當CMainFrame調用CTrayIcon::SetNotificationWnd時,CTrayIcon調用GetTopLevelParent
以擷取頂層父視窗,然後安裝CSubclassWnd視窗過程,這相當於一個鉤子,在訊息傳到任何頂層視窗之前,CSubclassWnd的視窗過程先將
它處理掉。這裡必須明白一點:Windows只將TaskbarCreated訊息發送到頂層父視窗。它有點象WM_QUERYNEWPALETTE、
WM_SYSCOLORCHANGE訊息以及其它頂層視窗訊息。現在當Windows發送TaskbarCreated時,控制將首先被傳遞到
CTrayIcon::CTrayHook::WindowProc。

   
CTrayIcon::OnTaskBarCreate是CTrayIcon類中新加的一個虛擬函數,其預設實現是在系統托盤中重新安裝表徵圖。如果你想做
一些其它的事情,可以派生一個新類並改寫此預設行為。實際的WindowProc代碼比我在本文中描述的要稍微複雜一些,因為它還要處理托盤通知以驅動默
認的菜單處理常式,以前,當獲得WM_MY_TRAY_NOTIFICATION訊息時,你必須自己調用OnTrayNotification。新的
CTrayIcon實現請參考本文的原始碼。

   
順便提及一下,你想知道我是如何測試表徵圖自動重建特性的嗎?(如果是你,你用什麼辦法?),很容易。在Windows
98中,按下Ctrl+Alt+Del,彈出工作管理員的任務清單。選擇"資源管理員(Explorer)",然後選擇"結束任務(End
Task)"。此時會顯示關機/重啟對話方塊,此時按下"取消"按鈕(不要按"關機"按鈕)。然後,等待幾秒鐘,你得到訊息顯示"這個任務沒有響應",這時
你要用"結束任務"來回複。接下來Windows的資源管理員便非正常終止!然後它又會自動起來,這時向所有頂層父視窗廣播TaskbarCreated
訊息。如果你的作業系統是Windows
NT/2000/XP,並安裝了IE4.0,如法炮製。當工作列死掉後,從"開始"菜單的"運行"對話方塊中敲入"explorer"啟動器來源管理員。不管
是用什麼作業系統,在殺掉工作列之前,如果TrayTest程式處於運行狀態,那麼當資源管理員自己恢複狀態時,TrayTest程式的托盤表徵圖會自動創
新安裝。不信的話,你用本文第一部分的例子程式和本文提供的範常式序試一下就知道了。你會發現本文的例子程式會處理TaskbarCreated訊息,而
另一個則完全不會。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.