用VB開(kāi)發(fā)托盤(pán)程序
發(fā)表時(shí)間:2023-07-14 來(lái)源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]很多軟件運(yùn)行時(shí)會(huì)在系統(tǒng)托盤(pán)區(qū)(就是桌面右下角顯示時(shí)間的區(qū)域)出現(xiàn)一個(gè)小圖標(biāo),它作為程序運(yùn)行的一個(gè)標(biāo)志,我們可以通過(guò)使用小圖標(biāo)所彈出的菜單來(lái)控制應(yīng)用程序的狀態(tài)。本例就給出了一個(gè)功能比較完整的托盤(pán)程序,...
很多軟件運(yùn)行時(shí)會(huì)在系統(tǒng)托盤(pán)區(qū)(就是桌面右下角顯示時(shí)間的區(qū)域)出現(xiàn)一個(gè)小圖標(biāo),它作為程序運(yùn)行的一個(gè)標(biāo)志,我們可以通過(guò)使用小圖標(biāo)所彈出的菜單來(lái)控制應(yīng)用程序的狀態(tài)。本例就給出了一個(gè)功能比較完整的托盤(pán)程序,我們可以看到怎樣用API函數(shù)Shell_NotifyIcon來(lái)添加、刪除、更改托盤(pán)圖標(biāo);而且例中還演示了為托盤(pán)圖標(biāo)添加右鍵菜單和浮動(dòng)提示的方法。
程序(附后)用到了Shell_NotifyIcon、SendMessage、CallWindowProc、SetWindowLong等API函數(shù),其中Shell_NotifyIcon是主要的函數(shù),它用來(lái)添加、刪除、更改系統(tǒng)托盤(pán)區(qū)(taskbar status area)的圖標(biāo),所以我們先來(lái)看看這個(gè)函數(shù)的聲明和參數(shù):
使用API函數(shù)之前必須先在程序中聲明如下:
Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias "Shell_NotifyIconA" (ByVal dwMessage As Long, lpData As NOTIFYICONDATA) As Long
其中各參數(shù)的意義如下表:
參數(shù): 意義
dwMessage 為消息設(shè)置值,它可以是以下的幾個(gè)常數(shù)值:0、1、2
NIM_ADD = 0 加入圖標(biāo)到系統(tǒng)狀態(tài)欄中
NIM_MODIFY = 1 修改系統(tǒng)狀態(tài)欄中的圖標(biāo)
NIM_DELETE = 2 刪除系統(tǒng)狀態(tài)欄中的圖標(biāo)
LpData 用以傳入NOTIFYICONDATA數(shù)據(jù)結(jié)構(gòu)變量,其結(jié)構(gòu)如下所示:
Type NOTIFYICONDATA
cbSize As Long 需填入NOTIFYICONDATA數(shù)據(jù)結(jié)構(gòu)的長(zhǎng)度
HWnd As Long 設(shè)置成窗口的句柄
Uid As Long 為圖標(biāo)所設(shè)置的ID值
UFlags As Long 設(shè)置uCallbackMessage,hIcon,szTip是否有效
UCallbackMessage As Long 消息編號(hào)
HIcon As Long 顯示在狀態(tài)欄上的圖標(biāo)
SzTip As String * 64 提示信息
End Type
返回值 Long,非零表示成功,零表示失敗
在使用這個(gè)API函數(shù)之前我們應(yīng)該先定義結(jié)構(gòu)類型NOTIFYICONDATA:
Public Type NOTIFYICONDATA
cbSize As Long HWnd As Long
Uid As Long UFlags As Long
UCallbackMessage As Long
HIcon As Long
SzTip As String * 64
End Type
然后定義一個(gè)NOTIFYICONDATA的變量TheData來(lái)記錄設(shè)置托盤(pán)圖標(biāo)的數(shù)據(jù)
Private TheData As NOTIFYICONDATA
這時(shí)我們就可以使用這個(gè)函數(shù)來(lái)設(shè)置系統(tǒng)托盤(pán)圖標(biāo)了,具體方法如下:
1、添加圖標(biāo)
With TheData
.Uid = 0
.HWnd = frm.HWnd 'frm.HWnd是程序主窗體的句柄
.cbSize = Len(TheData)
.HIcon = frm.Icon.Handle 'frm.Icon.Handle指向主窗體的圖標(biāo)
.UFlags = NIF_ICON
.UCallbackMessage = TRAY_CALLBACK
'作用是允許返回消息,在下一節(jié)中會(huì)有詳細(xì)解釋。
.UFlags = .UFlags Or NIF_MESSAGE
.cbSize = Len(TheData)
End With
Shell_NotifyIcon NIM_ADD, TheData
'根據(jù)前面定義NIM_ADD,設(shè)置為“添加模式”,然后添加
2、刪去圖標(biāo)
With TheData
.UFlags = 0
End With
Shell_NotifyIcon NIM_DELETE, TheData
'根據(jù)前面定義NIM_DELETE,設(shè)置為“刪除模式”
3、更改圖標(biāo)
With TheData
.HIcon = pic.Handle
'pic是圖片狂PictureBox,存放圖標(biāo)文件
.UFlags = NIF_ICON
End With
Shell_NotifyIcon NIM_MODIFY, TheData
'根據(jù)前面定義NIM_MODIFY,設(shè)置為“更改模式”
4、為圖標(biāo)添加浮動(dòng)提示信息
With TheData
.SzTip = tip & vbNullChar
'tip是字符串string,存儲(chǔ)提示信息
.UFlags = NIF_TIP
'指明要對(duì)浮動(dòng)提示進(jìn)行設(shè)置
End With
Shell_NotifyIcon NIM_MODIFY, TheData
'根據(jù)前面定義NIM_MODIFY,設(shè)置為“修改模式”
通過(guò)以上幾段代碼我們就能根據(jù)自己需要添加、刪除、更改系統(tǒng)托盤(pán)圖標(biāo),并能添加系統(tǒng)圖標(biāo)上的浮動(dòng)提示信息。但這時(shí)的托盤(pán)圖標(biāo)是孤立的,我們并不能利用它來(lái)控制應(yīng)用程序的行為,怎么辦呢?別急,請(qǐng)往下看……
如果你下載(源程序下載)并運(yùn)行這個(gè)例程序,你會(huì)發(fā)現(xiàn)如果我們?cè)谕斜P(pán)圖標(biāo)上點(diǎn)擊鼠標(biāo)右鍵,則會(huì)彈出一個(gè)右鍵菜單。如果點(diǎn)擊相應(yīng)的菜單項(xiàng),程序主窗體會(huì)隨之變化,這樣就可以控制程序的行為。而如果當(dāng)主窗體處于最小化狀態(tài)時(shí),我們?cè)谕斜P(pán)圖標(biāo)上點(diǎn)擊左鍵,窗體會(huì)恢復(fù)到原來(lái)的大小。其實(shí)實(shí)現(xiàn)上述的功能都要依賴于WINDOWS操作系統(tǒng)的消息機(jī)制,要完全弄懂這個(gè)機(jī)制挺不容易的,但是我們可以按下述文字來(lái)理解它。
把WINDOWS操作系統(tǒng)看作人的大腦,它接收、處理、并發(fā)送各種各樣的信息給我們的各個(gè)器官(當(dāng)然是比喻各個(gè)應(yīng)用程序了),也就是說(shuō)它是消息的中樞。而每個(gè)應(yīng)用程序(甚至每一個(gè)按鈕、標(biāo)簽、窗體等等統(tǒng)稱為窗口)在運(yùn)行時(shí)都會(huì)被分配一個(gè)窗口過(guò)程WINDOWPROC,由這個(gè)窗口過(guò)程來(lái)接收和處理操作系統(tǒng)發(fā)來(lái)的消息(實(shí)際上存在一個(gè)消息隊(duì)列),通常情況下這個(gè)窗口過(guò)程是由操作系統(tǒng)指定的,它會(huì)自動(dòng)的響應(yīng)并處理一些WINDOWS消息(如窗體移動(dòng)、最大化、最小化、錯(cuò)誤信息等)。好,到這我們先停一下,提出一個(gè)疑問(wèn),這些消息能否由我們自己寫(xiě)程序來(lái)處理呢?答案是肯定的,不過(guò)還得借助API函數(shù)的威力了,怎么用?我們還是先看看這些API函數(shù)的定義和參數(shù)吧。
程序中用到了SendMessage、CallWindowProc、SetWindowLong等API函數(shù),其中SendMessage函數(shù)的作用是將一條消息發(fā)給某個(gè)窗口;CallWindowProc函數(shù)用來(lái)發(fā)送消息到一個(gè)窗口過(guò)程;而使用SetWindowLong函數(shù)來(lái)為窗口結(jié)構(gòu)中為指定的窗口設(shè)置屬性。使用API函數(shù)之前必須先在程序中聲明如下:
Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal HWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal HWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal HWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
其中各參數(shù)的意義如下表:
CallWindowProc函數(shù)
參數(shù) 意義
lpPrevWndFunc Long,原來(lái)的窗口過(guò)程地址
HWnd Long,窗口句柄
Msg Long,發(fā)送的消息
wParam Long,消息類型,參考wParam參數(shù)表
lParam Long,依據(jù)wParam參數(shù)的不同而不同
返回值 Long,依據(jù)發(fā)送的消息不同而變化
SetWindowLong函數(shù) :
參數(shù) TD>意義
hwnd Long,欲為其取得信息的窗口的句柄
nIndex Long,請(qǐng)參考GetWindowLong函數(shù)的nIndex參數(shù)的說(shuō)明
dwNewLong Long,由nIndex指定的窗口信息的新值
返回值 Long,指定數(shù)據(jù)的前一個(gè)值
SendMessage函數(shù) :
參數(shù) 意義
hwnd Long,要接收消息的那個(gè)窗口的句柄
wMsg Long,消息的標(biāo)識(shí)符
wParam Long,具體取決于消息
lParam Any,具體取決于消息
返回值 Long,由具體的消息決定
我們要自己寫(xiě)程序來(lái)處理消息,必須先更改窗口的屬性,從原來(lái)由默認(rèn)的窗口過(guò)程來(lái)處理消息變成由我們自己寫(xiě)的消息處理過(guò)程來(lái)處理消息。方法是使用SetWindowLong函數(shù)來(lái)取得默認(rèn)窗口過(guò)程的地址,然后轉(zhuǎn)向?yàn)槲覀冏约簩?xiě)的窗口過(guò)程的地址,具體的實(shí)現(xiàn)方法如下代碼:
'GWL_WNDPROC獲得該窗口的窗口過(guò)程的地址,AddressOf是取址函數(shù),NewWindowProc是我們寫(xiě)的過(guò)程
OldWindowProc = SetWindowLong(frm.HWnd, GWL_WNDPROC, AddressOf
NewWindowProc)
然后在NewWindowProc函數(shù)中寫(xiě)入如下代碼,需要注意的是下面代碼中紅色的TRAY_CALLBACK是由托盤(pán)區(qū)圖標(biāo)傳來(lái)的消息,要讓托盤(pán)圖標(biāo)傳回消息,必須在添加托盤(pán)圖標(biāo)時(shí)指定:
Public Function NewWindowProc(ByVal HWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'如果用戶點(diǎn)擊了托盤(pán)中的圖標(biāo),則進(jìn)行判斷是點(diǎn)擊了左鍵還是右鍵
If Msg = TRAY_CALLBACK Then
'如果點(diǎn)擊了左鍵
If lParam = WM_LBUTTONUP Then
'而這時(shí)窗體的狀態(tài)是最小化時(shí)
If TheForm.WindowState = vbMinimized Then _
'恢復(fù)到最小化前的窗體狀態(tài)
TheForm.WindowState = TheForm.LastState
TheForm.SetFocus
Exit Function
End If
End If
'如果點(diǎn)擊了右鍵
If lParam = WM_RBUTTONUP Then
'則彈出右鍵菜單
TheForm.PopupMenu TheMenu
Exit Function
End If
End If
'如果是其他類型的消息則傳遞給原有默認(rèn)的窗口函數(shù)
NewWindowProc = CallWindowProc(OldWindowProc, HWnd, Msg, wParam, lParam)
End Function
這樣我們就取得并處理了來(lái)自托盤(pán)圖標(biāo)的消息,現(xiàn)在的問(wèn)題是在鼠標(biāo)右鍵菜單彈出后,怎么控制程序主窗體的狀態(tài),這時(shí)我們需要用到SendMessage函數(shù)來(lái)向主窗體發(fā)送最大化、最小化、關(guān)閉、移動(dòng)等消息,具體的代碼實(shí)現(xiàn)如下,其中HWnd是主窗體的句柄,WM_SYSCOMMAND表示發(fā)送的是系統(tǒng)控制類的消息,SC_MOVE、SC_SIZE、SC_RESTORE便是要發(fā)送的消息了:
'托盤(pán)圖標(biāo)右鍵菜單上的“移動(dòng)”項(xiàng)被點(diǎn)擊時(shí)
Private Sub mnuTrayMove_Click()
SendMessage HWnd, WM_SYSCOMMAND, SC_MOVE, 0&
End Sub
'托盤(pán)圖標(biāo)右鍵菜單上的“恢復(fù)”項(xiàng)被點(diǎn)擊時(shí)
Private Sub mnuTrayRestore_Click()
SendMessage HWnd, WM_SYSCOMMAND, SC_RESTORE, 0&
End Sub
'托盤(pán)圖標(biāo)右鍵菜單上的“退出”項(xiàng)被點(diǎn)擊時(shí)
Private Sub mnuTraySize_Click()
SendMessage HWnd, WM_SYSCOMMAND, SC_SIZE, 0&
End Sub
最后要提醒你,在程序退出時(shí)一定要把窗口過(guò)程的地址恢復(fù)為默認(rèn)值,同時(shí)把托盤(pán)圖標(biāo)移去哦。
為了學(xué)習(xí)方便,以下提供了源代碼:
'---------------------------------------------
' 使用系統(tǒng)托盤(pán)程序演示
'---------------------------------------------
'程序說(shuō)明:
' 這是一個(gè)比較完整的使用系統(tǒng)托盤(pán)的程序?qū)嵗,包?br>'了:添加托盤(pán)圖標(biāo),刪除托盤(pán)圖標(biāo),動(dòng)態(tài)改變托盤(pán)圖標(biāo),
'為托盤(pán)圖標(biāo)添加浮動(dòng)提示信息,實(shí)現(xiàn)托盤(pán)圖標(biāo)的鼠標(biāo)右鍵
'菜單等內(nèi)容。
'-------名稱-------------------作用------------
' Form1 主窗體
' mnuFile,mnuFileExit 文件菜單,菜單項(xiàng)
' mnuTray,mnuTrayClose... 托盤(pán)區(qū)右鍵菜單,菜單項(xiàng)
'---------------------------------------------
Option Explicit
'LastState變量的作用是標(biāo)示主窗體原有狀態(tài)
Public LastState As Integer
'【VB聲明】
' Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
'【說(shuō)明】
' 調(diào)用一個(gè)窗口的窗口函數(shù),將一條消息發(fā)給那個(gè)窗口。除非消息處理完畢,否則該函數(shù)不會(huì)返回。SendMessageBynum,
' SendMessageByString是該函數(shù)的“類型安全”聲明形式
'【返回值】
' Long,由具體的消息決定
'【參數(shù)表】
' hwnd ----------- Long,要接收消息的那個(gè)窗口的句柄
' wMsg ----------- Long,消息的標(biāo)識(shí)符
' wParam --------- Long,具體取決于消息
' lParam --------- Any,具體取決于消息
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal HWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
'表示發(fā)送的是系統(tǒng)命令
Private Const WM_SYSCOMMAND = &H112
Private Const SC_MOVE = &HF010&
Private Const SC_RESTORE = &HF120&
Private Const SC_SIZE = &HF000&
'當(dāng)主窗體加載時(shí)
Private Sub Form_Load()
'窗體的WindowState屬性,返回或設(shè)置一個(gè)值,該值用來(lái)指定在運(yùn)行時(shí)窗體窗口的可視狀態(tài)
'vbNormal 0 (缺省值)正常 。
'VbMinimized 1 最小化(最小化為一個(gè)圖標(biāo))
'VbMaximized 2 最大化(擴(kuò)大到最大尺寸)
If WindowState = vbMinimized Then
LastState = vbNormal
Else
LastState = WindowState
End If
'將圖標(biāo)添加到托盤(pán)的函數(shù),參見(jiàn)模塊中的解釋
'注意了這是從主程序到模塊的入口,本例中并沒(méi)有直接調(diào)用Shell_NotifyIcon函數(shù)
AddToTray Me, mnuTray
SetTrayTip "托盤(pán)圖標(biāo)演示,點(diǎn)擊右鍵彈出菜單"
End Sub
'在主窗體Form1大小改變時(shí),相應(yīng)改變右鍵菜單mnuTray的菜單項(xiàng)的可用屬性Enabled
Private Sub Form_Resize()
Select Case WindowState
'如果窗體最小化了,把菜單項(xiàng)“最大化”“恢復(fù)”設(shè)為可用,
'而把“最小化”“移動(dòng)”“大小”三項(xiàng)設(shè)為不可用.
'如果這時(shí)在托盤(pán)圖標(biāo)上點(diǎn)擊鼠標(biāo)右鍵,會(huì)發(fā)現(xiàn)不可用項(xiàng)變?yōu)榛疑?br>Case vbMinimized
mnuTrayMaximize.Enabled = True
mnuTrayMinimize.Enabled = False
mnuTrayMove.Enabled = False
mnuTrayRestore.Enabled = True
mnuTraySize.Enabled = False
'窗體最大化時(shí)
Case vbMaximized
mnuTrayMaximize.Enabled = False
mnuTrayMinimize.Enabled = True
mnuTrayMove.Enabled = False
mnuTrayRestore.Enabled = True
mnuTraySize.Enabled = False
'一般狀態(tài)下
Case vbNormal
mnuTrayMaximize.Enabled = True
mnuTrayMinimize.Enabled = True
mnuTrayMove.Enabled = True
mnuTrayRestore.Enabled = False
mnuTraySize.Enabled = True
End Select
If WindowState <> vbMinimized Then LastState = WindowState
End Sub
'保證在程序退出時(shí)刪除托盤(pán)圖標(biāo)
Private Sub Form_Unload(Cancel As Integer)
RemoveFromTray
End Sub
'“文件”菜單的“退出”項(xiàng)被點(diǎn)擊時(shí)
Private Sub mnuFileExit_Click()
Unload Me
End Sub
'托盤(pán)圖標(biāo)右鍵菜單上的“退出”項(xiàng)被點(diǎn)擊時(shí)
Private Sub mnuTrayClose_Click()
Unload Me
End Sub
'托盤(pán)圖標(biāo)右鍵菜單上的“最大化”項(xiàng)被點(diǎn)擊時(shí)
Private Sub mnuTrayMaximize_Click()
WindowState = vbMaximized
End Sub
'托盤(pán)圖標(biāo)右鍵菜單上的“最小化”項(xiàng)被點(diǎn)擊時(shí)
Private Sub mnuTrayMinimize_Click()
WindowState = vbMinimized
End Sub
'托盤(pán)圖標(biāo)右鍵菜單上的“移動(dòng)”項(xiàng)被點(diǎn)擊時(shí)
Private Sub mnuTrayMove_Click()
SendMessage HWnd, WM_SYSCOMMAND, _
SC_MOVE, 0&
End Sub
'托盤(pán)圖標(biāo)右鍵菜單上的“恢復(fù)”項(xiàng)被點(diǎn)擊時(shí)
Private Sub mnuTrayRestore_Click()
SendMessage HWnd, WM_SYSCOMMAND, _
SC_RESTORE, 0&
End Sub
'托盤(pán)圖標(biāo)右鍵菜單上的“退出”項(xiàng)被點(diǎn)擊時(shí)
Private Sub mnuTraySize_Click()
SendMessage HWnd, WM_SYSCOMMAND, _
SC_SIZE, 0&
End Sub
'-----------------------------------------
'以下為模塊中的代碼:
'-----------------------------------------
Option Explicit
Public OldWindowProc As Long
Public TheForm As Form
Public TheMenu As Menu
'【VB聲明】
'Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal HWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'【說(shuō)明】
' 此函數(shù)發(fā)送消息到一個(gè)窗口過(guò)程
'【返回值】
' Long,依據(jù)發(fā)送的消息不同而變化
'【參數(shù)表】
' lpPrevWndFunc----- Long,原來(lái)的窗口過(guò)程地址
' HWnd-------------- Long,窗口句柄
' Msg -------------- Long,發(fā)送的消息
' wParam ----------- Long,消息類型,參考wParam參數(shù)表
' lParam ----------- Long,依據(jù)wParam參數(shù)的不同而不同
Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal HWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'【VB聲明】
' Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
'【說(shuō)明】
' 在窗口結(jié)構(gòu)中為指定的窗口設(shè)置信息
'【返回值】
' Long,指定數(shù)據(jù)的前一個(gè)值
'【參數(shù)表】
' hwnd ----------- Long,欲為其取得信息的窗口的句柄
' nIndex --------- Long,請(qǐng)參考GetWindowLong函數(shù)的nIndex參數(shù)的說(shuō)明
' dwNewLong ------ Long,由nIndex指定的窗口信息的新值
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal HWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
'【VB聲明】
'Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias "Shell_NotifyIconA" (ByVal dwMessage As Long, lpData As NOTIFYICONDATA) As Long
'【說(shuō)明】
'【參數(shù)表】
'參數(shù)dwMessage ---- 為消息設(shè)置值,它可以是以下的幾個(gè)常數(shù)值:0、1、2
'NIM_ADD = 0 加入圖標(biāo)到系統(tǒng)狀態(tài)欄中
'NIM_MODIFY = 1 修改系統(tǒng)狀態(tài)欄中的圖標(biāo)
'NIM_DELETE = 2 刪除系統(tǒng)狀態(tài)欄中的圖標(biāo)
'參數(shù)LpData ---- 用以傳入NOTIFYICONDATA數(shù)據(jù)結(jié)構(gòu)變量,我們也需要在"模塊"中定義其結(jié)構(gòu)如下:
'Type NOTIFYICONDATA
' cbSize As Long 需填入NOTIFYICONDATA數(shù)據(jù)結(jié)構(gòu)的長(zhǎng)度
' HWnd As Long 設(shè)置成窗口的句柄
' Uid As Long 為圖標(biāo)所設(shè)置的ID值
' UFlags As Long 用來(lái)設(shè)置以下三個(gè)參數(shù)uCallbackMessage、hIcon、szTip是否有效
' UCallbackMessage As Long 消息編號(hào)
' HIcon As Long 顯示在狀態(tài)欄上的圖標(biāo)
' SzTip As String * 64 提示信息
'End Type
'---- 其中參數(shù)uCallbackMessage、hIcon、szTip也應(yīng)在模塊中聲明為以下的常量:
'Public Const NIF_MESSAGE = 1
'Public Const NIF_ICON = 2
'Public Const NIF_TIP = 4
Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias "Shell_NotifyIconA" (ByVal dwMessage As Long, lpData As NOTIFYICONDATA) As Long
Public Const WM_USER = &H400
Public Const WM_LBUTTONUP = &H202
Public Const WM_MBUTTONUP = &H208
Public Const WM_RBUTTONUP = &H205
Public Const TRAY_CALLBACK = (WM_USER + 1001&)
Public Const GWL_WNDPROC = (-4)
Public Const GWL_USERDATA = (-21)
Public Const NIF_ICON = &H2
Public Const NIF_TIP = &H4
Public Const NIM_ADD = &H0
Public Const NIF_MESSAGE = &H1
Public Const NIM_MODIFY = &H1
Public Const NIM_DELETE = &H2
'記錄 設(shè)置托盤(pán)圖標(biāo)的數(shù)據(jù) 的數(shù)據(jù)類型NOTIFYICONDATA
Public Type NOTIFYICONDATA
cbSize As Long
HWnd As Long
Uid As Long
UFlags As Long
UCallbackMessage As Long
HIcon As Long
SzTip As String * 64
End Type
'TheData變量記錄設(shè)置托盤(pán)圖標(biāo)的數(shù)據(jù)
Private TheData As NOTIFYICONDATA
' *********************************************
' 新的窗口過(guò)程--主程序中采用SetWindowLong函數(shù)改變了窗口函數(shù)的地址,消息轉(zhuǎn)向由NewWindowProc處理
' *********************************************
Public Function NewWindowProc(ByVal HWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'如果用戶點(diǎn)擊了托盤(pán)中的圖標(biāo),則進(jìn)行判斷是點(diǎn)擊了左鍵還是右鍵
If Msg = TRAY_CALLBACK Then
'如果點(diǎn)擊了左鍵
If lParam = WM_LBUTTONUP Then
'而這時(shí)窗體的狀態(tài)是最小化時(shí)
If TheForm.WindowState = vbMinimized Then _
'恢復(fù)到最小化前的窗體狀態(tài)
TheForm.WindowState = TheForm.LastState
TheForm.SetFocus
Exit Function
End If
End If
'如果點(diǎn)擊了右鍵
If lParam = WM_RBUTTONUP Then
'則彈出右鍵菜單
TheForm.PopupMenu TheMenu
Exit Function
End If
End If
'如果是其他類型的消息則傳遞給原有默認(rèn)的窗口函數(shù)
NewWindowProc = CallWindowProc(OldWindowProc, HWnd, Msg, wParam, lParam)
End Function
' *********************************************
' 把主窗體的圖標(biāo)(Form1.icon屬性可改變)添加到托盤(pán)中
' *********************************************
Public Sub AddToTray(frm As Form, mnu As Menu)
'保存當(dāng)前窗體和菜單信息
Set TheForm = frm
Set TheMenu = mnu
'GWL_WNDPROC獲得該窗口的窗口函數(shù)的地址
OldWindowProc = SetWindowLong(frm.HWnd, GWL_WNDPROC, AddressOf NewWindowProc)
'知識(shí)點(diǎn)滴:HWnd屬性
'返回窗體或控件的句柄。語(yǔ)法: object.HWnd
'說(shuō)明:Microsoft Windows 運(yùn)行環(huán)境,通過(guò)給應(yīng)用程序中的每個(gè)窗體和控件
'分配一個(gè)句柄(或 hWnd)來(lái)標(biāo)識(shí)它們。hWnd 屬性用于Windows API調(diào)用。
'將主窗體圖標(biāo)添加在托盤(pán)中
With TheData
.Uid = 0 '忘了嗎?參考一下前面內(nèi)容,Uid圖標(biāo)的序號(hào),做動(dòng)畫(huà)圖標(biāo)有用
.HWnd = frm.HWnd
.cbSize = Len(TheData)
.HIcon = frm.Icon.Handle
.UFlags = NIF_ICON '指明要對(duì)圖標(biāo)進(jìn)行設(shè)置
.UCallbackMessage = TRAY_CALLBACK
.UFlags = .UFlags Or NIF_MESSAGE '指明要設(shè)置圖標(biāo)或返回信息給主窗體,此句不能省去
.cbSize = Len(TheData) '為什么呢?我們需要在添加圖標(biāo)的同時(shí),讓其返回信息
End With '給主窗體,Or的意思是同時(shí)進(jìn)行設(shè)置和返回消息
Shell_NotifyIcon NIM_ADD, TheData '根據(jù)前面定義NIM_ADD,設(shè)置為“添加模式”
End Sub
' *********************************************
' 刪除系統(tǒng)托盤(pán)中的圖標(biāo)
' *********************************************
Public Sub RemoveFromTray()
'刪除托盤(pán)中的圖標(biāo)
With TheData
.UFlags = 0
End With
Shell_NotifyIcon NIM_DELETE, TheData '根據(jù)前面定義NIM_DELETE,設(shè)置為“刪除模式”
'恢復(fù)原有的設(shè)置
SetWindowLong TheForm.HWnd, GWL_WNDPROC, OldWindowProc
End Sub
' *********************************************
' 為托盤(pán)中的圖標(biāo)加上浮動(dòng)提示(也就是鼠標(biāo)移上去時(shí)出現(xiàn)的提示字條)
' *********************************************
Public Sub SetTrayTip(tip As String)
With TheData
.SzTip = tip & vbNullChar
.UFlags = NIF_TIP '指明要對(duì)浮動(dòng)提示進(jìn)行設(shè)置
End With
Shell_NotifyIcon NIM_MODIFY, TheData '根據(jù)前面定義NIM_MODIFY,設(shè)置為“修改模式”
End Sub
' *********************************************
' 設(shè)置托盤(pán)的圖標(biāo)(在本例中沒(méi)有用到,如果要?jiǎng)討B(tài)改變托盤(pán)內(nèi)顯示的圖標(biāo),它非常有用)
' 例如:1、顯示動(dòng)畫(huà)圖標(biāo)(方法你一定猜到了,對(duì)!使用Timer控件,不斷調(diào)用此過(guò)程,注意把動(dòng)畫(huà)放在pic數(shù)組中)
' 2、程序處于不同狀態(tài)時(shí),顯示不同的圖標(biāo),方法是類似的
' 有興趣的話試一試吧。
' *********************************************
Public Sub SetTrayIcon(pic As Picture)
'判斷一下pic中存放的是不是圖標(biāo)
If pic.Type <> vbPicTypeIcon Then Exit Sub
'更換圖標(biāo)為pic中存放的圖標(biāo)
With TheData
.HIcon = pic.Handle
.UFlags = NIF_ICON
End With
Shell_NotifyIcon NIM_MODIFY, TheData
End Sub