Qt之自定義托盤

    提及Qt,真是個不錯的ui庫,不只僅ui作的好,其餘方面也不差,在平臺擴展方面也是很是的強大。這篇文章我將會分析下qt的托盤,QSystemTrayIcon是qt的托盤類,托盤類的用途是什麼我就不說了,自行百科就好,關鍵問題是咱們要實現自定義的托盤。html

    提及經常使用的客戶端軟件,qq,微信等聊天工具,有這麼幾個托盤事件:windows

一、來消息圖標閃爍api

二、氣泡消息提示微信

三、鼠標左鍵單擊、左鍵雙擊、右鍵單擊、滾動單擊app

    上述這三種事件QSystemTrayIcon類都徹底可以解決,可是托盤的hover事件卻無能爲力,如圖1所示,途圖中是幫助文檔中的一段描述,指明瞭只有在x11系統中,能夠捕獲到系統的tooltip事件,其餘系統都無能爲力,我本身也看了下qt的源碼,果然是這樣的,有興趣的同窗能夠自行在研究下。ide

圖1 幫助文檔函數

    如圖2所示,qq有消息時,鼠標hover在圖盤彈出菜單,那麼qq是怎麼作的呢,既然qq都到作到了,這個功能咱們本身想必確定也能實現。工具

圖2 托盤hover彈框post

    好了,上邊說了這麼多,僅僅是爲了鋪墊我本身實現的托盤,徹底脫離了qt中的托盤類QSystemTrayIcon,不過也不能說徹底脫離,部分代碼仍是從qt源碼中摘出來的。文章的最後我附上我本身用qt實現的自定義托盤和下載別人用mfc自定義實現的自定義托盤。ui

    由於win32我本身也不是特別瞭解,所以我也是大概說下自定義托盤須要瞭解的東西,首先是NOTIFYICONDATA結構,這個結構百科講的特別詳細,看一下就知道怎麼用,而後是Shell_NotifyIcon這個api,這個方法就是對托盤操做的接口。具體參數百科中說的很詳細,不過若是你不想看也無所謂,直接往下看也能夠。對盤託的操做在windows平臺下都是同樣的,關鍵問題是用qt怎麼接受這個圖盤的hover和leave消息。

    關於這個托盤的實現我也是從mfc的示例代碼中獲取的啓發,而後用qt方法實現,接下來我就直接說下用qt實現的步驟:

一、首先咱們須要瞭解下QAbstractNativeEventFilter這個接口類,繼承這個接口類的類能夠把本身註冊到app中,而後就能獲取到整個app

的事件,事件的處理函數爲nativeEventFilter,該類有3個參數,具體能夠參見這篇文字qt捕獲全局windows消息 這個文章中說的不全是對的,不過能抓取到app消息應該是沒問你的,本篇博客的demo也是印證了這個問題。註冊代碼以下:

 1 qApp->installNativeEventFilter(this); 

二、第二步就是建立托盤圖標,建立托盤圖標的時候,windows提供了api,代碼以下:

 1 NOTIFYICONDATA    nid;
 2     QLabel *l = new QLabel;
 3     nid.cbSize = sizeof nid;
 4     nid.hIcon = qt_pixmapToWinHICON(QIcon(":/trayIcon/Resources/childrenWidget.ico").pixmap(16, 16));
 5     nid.hWnd = HWND(l->winId());
 6     nid.uCallbackMessage = WM_TRAYNOTIFY;
 7     nid.uID = 1;
 8     nid.uFlags = NIF_ICON | NIF_MESSAGE;
 9 
10     Shell_NotifyIcon(NIM_ADD, &nid);

    此處代碼中有一個標籤l,建立他是由於建立圖標時須要一個接受鼠標事件的窗口句柄hWnd,若是沒有句柄,那麼托盤也不能建立成功;其餘成員的含義從變量的命名上應該也能理解,我重點說下uFlags這個變量,他其實自己沒有什麼含義,主要是爲了標示NOTIFYICONDATA結構中其餘成員那個是有效的,這個也方便了咱們後續對托盤圖標的修改。好比說修改tooltip、修改圖標等信息。uCallbackMessage是消息id,在咱們後續處理的邏輯中會用到

三、鼠標事件處理

 1 bool trayIcon::nativeEventFilter(const QByteArray & eventType, void * message, long * result)
 2 {
 3     if (eventType == "windows_generic_MSG" || eventType == "windows_dispatcher_MSG")
 4     {
 5         MSG * pMsg = reinterpret_cast<MSG *>(message);
 6         if (pMsg->message == WM_TRAYNOTIFY)
 7         {
 8             switch (pMsg->lParam)
 9             {
10             case WM_MOUSEMOVE:
11                 m_traypos.OnMouseMove();
12                 break;
13             case WM_MOUSEHOVER:
14                 m_Menu->show();
15                 break;
16             case WM_MOUSELEAVE:
17                 m_Menu->hide();
18                 break;
19             case WM_LBUTTONDBLCLK:
20             //    m_Menu->show();
21                 break;
22             case WM_LBUTTONDOWN:
23             //    m_Menu->show();
24                 break;
25             case WM_RBUTTONDOWN:
26             //    m_Menu->show();
27                 break;
28             }
29         }
30     }
31 
32     return false;
33 }

上述代碼主要是針對鼠標事件的一個處理。WM_TRAYNOTIFY消息是咱們開始的時候註冊到圖盤中的消息,當托盤發生鼠標事件的時候咱們只須要關注本身註冊的消息,對於windows托盤稍微有了解的同窗可能也知道,微軟沒有提供給咱們托盤圖標的進入和離開事件,而僅僅提供了鼠標move的事件,不過僅僅有這一個事件咱們就能夠模擬出其餘的事件來。細心的同窗將會注意到 m_traypos.OnMouseMove();這句代碼,其實m_tryapos這個對象是一個move事件處理類,他能夠模擬出鼠標hover和leave事件來。關於這個類的解釋我就不說了,是一個國外的大牛寫的,demo中有源文件。

四、程序退出時銷燬托盤圖標

Shell_NotifyIcon(NIM_DELETE, &m_NotifyIconData);

    經過上述的代碼整理,簡單的托盤就能夠實現了,由於我是本身作的demo,所以不是全部事件的處理了的,高級定製的功能若是有興趣的同窗能夠給我留言,或者私信我能夠,若是是我實現了的,我將願意和你們一塊兒分享。我下邊連接中的這個demo其實比較粗糙,就僅僅的能夠實現鼠標在托盤圖標上的hover和leave請求。

    最後我上兩張效果圖,圖3是mfc示例的鼠標hover截圖,圖4是qt示例的鼠標hover截圖

圖3 mfc示例demo

圖4 qt示例demo

注意:這個demo很是粗糙,不過我已經講明瞭怎麼實現一個本身的托盤,關於須要怎麼實現一個完美的托盤,同窗們能夠參考qt的源碼中qsystemtrayicon_win.cpp文件,該文件就是QSystemTrayIcon類的真正實現。

qt示例連接:http://download.csdn.net/detail/qq_30392343/9608076

mfc示例連接:http://download.csdn.net/detail/qq_30392343/9608078

 

若是您以爲文章不錯,不妨給個 打賞,寫做不易,感謝各位的支持。您的支持是我最大的動力,謝謝!!! 

 

  


很重要--轉載聲明

  1. 本站文章無特別說明,皆爲原創,版權全部,轉載時請用連接的方式,給出原文出處。同時寫上原做者:朝十晚八 or Twowords
  2. 如要轉載,請原文轉載,如在轉載時修改本文,請事先告知,謝絕在轉載時經過修改本文達到有利於轉載者的目的。 

相關文章
相關標籤/搜索