Inserire un'icona nella TrayBar e mostrare il Popup-Menu (Tutorial completo)
Nella rubrica dedicata alle DOMANDE abbiamo
parlato di come utilizzare la funzione Shell_NotifyIcon per far apparire un'icona a piacere all'interno
della TrayBar, vicino all'orologio. In questa lezione si andrà leggermente oltre: oltre all'icona si renderà disponibile
un Popup-Menu relativo al progetto a cui l'icona fa riferimento.
Notare che questa lezione propone l'analisi di un codice nel suo complesso: le singole
funzioni verranno (o sono già state) trattate a parte in articoli separati.
Incominciamo a vedere le dichiarazioni generali delle funzioni necessarie allo scopo che vogliamo
raggiungere. Nel modulo quindi aggiungiamo questo blocco di codice:
Declare Function TrackPopupMenuEx& Lib "user32" (ByVal hMenu As Long, ByVal un _
As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal hwnd As Long, lpTPMParams _
As TPMPARAMS)
Declare Function InsertMenu& Lib "user32" Alias "InsertMenuA" (ByVal hMenu As _
Long, ByVal nPosition As Long, ByVal wFlags As Long, ByVal wIDNewItem As Long, _
ByVal lpNewItem As String)
Declare Function CreatePopupMenu& Lib "user32" ()
Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI)
Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias "Shell_NotifyIconA" _
(ByVal dwMessage As Long, lpData As NOTIFYICONDATA) As Long
|
Come vedremo tra poco ognuna di queste funzioni avrà una parte fondamentale
nella creazione del nostro progetto. E del resto se così non fosse, sarebbe del tutto
inutile dichiararle...
Adesso, rimanendo sempre nell'ambito di Module1.bas, aggiungiamo la struttura
NOTIFYICONDATA:
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
|
terminata l'operazione inseriamo qualche FLAG relativo
alla struttur appena vista che ci può interessare:
Public Const NIM_ADD = &H0
Public Const NIM_DELETE = &H2
Public Const NIM_MODIFY = &H1
Public Const NIF_ICON = &H2
Public Const NIF_MESSAGE = &H1
Public Const NIF_TIP = &H4
Public Const TPM_LEFTBUTTON = &H0
Public Const TPM_RIGHTBUTTON = &H2
Public Const TPM_LEFTALIGN = &H0
Public Const TPM_CENTERALIGN = &H4
Public Const TPM_RIGHTALIGN = &H8
Public Const TPM_BOTTOMALIGN = &H20&
Public Const TPM_HORIZONTAL = &H0&
Public Const TPM_NONOTIFY = &H80&
Public Const TPM_RETURNCMD = &H100&
Public Const TPM_TOPALIGN = &H0&
Public Const TPM_VCENTERALIGN = &H10&
Public Const TPM_VERTICAL = &H40&
Public Const WM_MOUSEMOVE = &H200
Public Const WM_LBUTTONDOWN = &H201
Public Const WM_RBUTTONUP = &H205
|
Concludiamo questa parentesi del modulo aggiungendo la struttura RECT TPMPARAMS e POINTAPI:
Type RECT
Top As Long
Left As Long
Bottom As Long
Right As Long
End Type
Type TPMPARAMS
cbSize As Long
rcExclude As RECT
End Type
Type POINTAPI
x As Long
y As Long
End Type
|
Ecco dunque come apparirà Module1.bas alla fine del lavoro:
Declare Function TrackPopupMenuEx& Lib "user32" (ByVal hMenu As Long, ByVal un _
As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal hwnd As Long, lpTPMParams _
As TPMPARAMS)
Declare Function InsertMenu& Lib "user32" Alias "InsertMenuA" (ByVal hMenu As _
Long, ByVal nPosition As Long, ByVal wFlags As Long, ByVal wIDNewItem As Long, _
ByVal lpNewItem As String)
Declare Function CreatePopupMenu& Lib "user32" ()
Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI)
Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias "Shell_NotifyIconA" _
(ByVal dwMessage As Long, lpData As NOTIFYICONDATA) As Long
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
Public Const NIM_ADD = &H0
Public Const NIM_DELETE = &H2
Public Const NIM_MODIFY = &H1
Public Const NIF_ICON = &H2
Public Const NIF_MESSAGE = &H1
Public Const NIF_TIP = &H4
Public Const TPM_LEFTBUTTON = &H0
Public Const TPM_RIGHTBUTTON = &H2
Public Const TPM_LEFTALIGN = &H0
Public Const TPM_CENTERALIGN = &H4
Public Const TPM_RIGHTALIGN = &H8
Public Const TPM_BOTTOMALIGN = &H20&
Public Const TPM_HORIZONTAL = &H0&
Public Const TPM_NONOTIFY = &H80&
Public Const TPM_RETURNCMD = &H100&
Public Const TPM_TOPALIGN = &H0&
Public Const TPM_VCENTERALIGN = &H10&
Public Const TPM_VERTICAL = &H40&
Public Const WM_MOUSEMOVE = &H200
Public Const WM_LBUTTONDOWN = &H201
Public Const WM_RBUTTONUP = &H205
Type RECT
Top As Long
Left As Long
Bottom As Long
Right As Long
End Type
Type TPMPARAMS
cbSize As Long
rcExclude As RECT
End Type
Type POINTAPI
x As Long
y As Long
End Type
|
Adesso passiamo a Form1. Creiamo due pulsanti: premendo Command1 l'icona
apparirà nella TrayBar, premendo invece Command2 l'icona scoparirà ed il menu
eventualmente aperto verrà distrutto:
Private Sub Command1_Click()
'si inserisce l'icona nella tray
Dim NID As NOTIFYICONDATA
'NOTIFYICONDATA è la struttura,
'vedere il modulo
With NID
.hwnd = Me.hwnd
.cbSize = Len(NID)
.uID = vbNull
'le costanti da utilizzare: tip, icona e messaggio mandato al sistema
.uFlags = NIF_TIP Or NIF_ICON Or NIF_MESSAGE
.hIcon = Me.Icon
.uCallbackMessage = WM_MOUSEMOVE
'modificare qui la frase da far apparire
'una volta sovrapposti puntatore e icona
NID.szTip = "Esempio a cura di: Visual Basic Italia"
'viene richiamata l'API alla quale
'si passa il flag che indica di
'aggiungere l'icona e la specifica
'della struttura NOTIFYICONDATA che
'ha acquistato una serie di proprietà
'(lunghezza=luunghezza struttura,
',tipo di icona, finestra nella quale apparire...)
Shell_NotifyIcon NIM_ADD, NID
End With
End Sub
|
Vediamo di gestire adesso l'evento Click di Command2. Tutto sarà invariato
rispetto a quanto visto relativamente a Command1. Verrà solamente passata alla funzione
Shell_NotifyIcon il flag che indica di eliminare l'icona:
Private Sub Command2_Click()
Dim NID As NOTIFYICONDATA
With NID
'id. della finestra nella quale
'deve apparire icona e pop-up
.hwnd = Me.hwnd
.cbSize = Len(NID)
.uID = vbNull
'flags da utilizzare: icona, tips, messaggio
'(ossia quale voce viene selezionata)
.uFlags = NIF_TIP Or NIF_ICON Or NIF_MESSAGE
'indica quale icona far apparire. Per
'semplicità facciamo apparire l'icona
'di form1
.hIcon = Me.Icon
.uCallbackMessage = WM_MOUSEMOVE
'tip che appare quando il puntatore
'è sull'icona
.szTip = "Esempio a cura di: Visual Basic Italia"
End With
'vedi il commento prima di questo blocco di codice
'con riferimento a NIM_DELETE
Shell_NotifyIcon NIM_DELETE, NID
End Sub
|
Ora preoccupiamoci del Popup-Menu. Dove farlo apparire? Quali voci inserire?
Ecco il codice già ampiamente commentato:
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, x _
As Single, y As Single)
Dim msg As Long
msg = x / Screen.TwipsPerPixelX
Select Case msg
'indichiamo il caso in cui si rilasci il pulsante sinistro del
'mouse:non succederà nulla.
Case WM_LBUTTONDOWN
'vogliamo però che anche quando <
'si preme sulla traybar, form1 non perda il focus.
AppActivate Me.Caption
'indichiamo il caso in cui si
'rilasci il pulsante destro del
'mouse: si aprirà il popup-menu
Case WM_RBUTTONUP
Dim pAPI As POINTAPI
Dim PMParams As TPMPARAMS
AppActivate Me.Caption
'determina il punto del piano nel quale l'utente ha cliccato
GetCursorPos pAPI
'richiamando l'api createpopupmenu creiamo un nuovo menu che parte
'dall 'icona. Siccome poi cancelleremo questo menu, lo chiameremo
'temporary popup-menu: tmpPop.
tmpPop% = CreatePopupMenu
'inseriamo poi le voci nel menu temporaneo
InsertMenu tmpPop%, 0, MF_BYPOSITION, 70, "Cancella l'icona"
InsertMenu tmpPop%, 1, MF_BYPOSITION, 71, "Ripristina"
'inseriamo il separatore a cui associamo una stringa nulla
InsertMenu tmpPop%, 2, MF_SEPARATOR, 72, vbNullString
InsertMenu tmpPop%, 3, MF_BYPOSITION, 73, "Esci"
'Adesso dobbiamo pensare alle dimensioni del menu: siccome
'abbiamo poche voci, ci conviene impostare le dimensioni minime per
'un popup menu:20
PMParams.cbSize = 20
'adesso mostriamo il popup menu
tmpReply% = TrackPopupMenuEx(tmpPop%, TPM_LEFTALIGN Or TPM_LEFTBUTTON Or TPM_RETURNCMD, pAPI.x, pAPI.y, Me.hwnd, PMParams)
Select Case tmpReply%
'nel caso in cui si prema la voce1
Case 70
'è si passa all'evento:
Call Command2_Click
'nel caso in cui si prema la voce2
Case 71
'questo mostra come è chiamato il menu dal quale il popup menu
'acquisisce le voci. Notare qual'è la caption di questa finestra
MsgBox "Ripristina"
'form1 non perde il focus.
AppActivate Me.Caption
Case 73
Call Command2_Click
End Select
End Select
End Sub
|
Per concludere diamo un'occhiata al codice necessario per terminare l'applicazione
eliminando l'icona ed il Popup-Menu eventualmente rimasto aperto:
Private Sub Form_Unload(Cancel As Integer)
'dobbiamo ricordarci che anche se l'icona è apparsa nella traybar,
'quando si termina l'applicazione l'icona scompare (NIM_DELETE)
Dim NID As NOTIFYICONDATA
NID.hwnd = Me.hwnd
NID.cbSize = Len(NID)
NID.uID = vbNull
NID.uFlags = NIF_TIP Or NIF_ICON Or NIF_MESSAGE
NID.hIcon = Me.Icon
NID.uCallbackMessage = WM_MOUSEMOVE <
NID.szTip = "Esempio a cura di: Visual Basic Italia"
Shell_NotifyIcon NIM_DELETE, NID
End Sub
|
...e con soli due pulsanti siamo riusciti a creare un'applicazione di tutto rispetto.
Naturalmente integrare questo codice in un'applicazione preesistente e certamente
più complessa non è difficile. Potete inserire il blocco di codice dell'evento Click
di Command1 nell'evento Load di Form1, in modo che l'icona compaia all'apertura
dell'applicazione. Allo stesso modo potrete tenere valido l'evento Unload di Form1
e non considerare l'evento Click di Command2. Oppure potete mantenere i due
pulsanti tali e quali come in questo programma, magari rendendoli invisibili e senza fare
tante modifiche al codice, quando vi servirà l'icona nella TrayBar richiamare l'evento
Click di Command1, ad esempio in questo modo:
Naturalmente per togliere l'icona potrete allo stesso modo fare così:
|