要实现在系统通知区绘制图标,必须调用win32 API中的Shell_NotifyIcon函数,该函
数的说明如下:Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias "Shell_NotifyIconA"
(ByVal dwMessage As Long, lpData As NOTIFYICONDATA) As Long。其中,dwMessage 参
数指定要进行的操作类型,它取以下三个值之一:NIM_ADD、NIM_DELETE和
NIM_MODIFY。NIM_ADD参数指出将在系统通知区添加一个图标;NIM_DELETE参数指
出将删除图标;NIM_MODIFY参数指出将修改图标的一些属性,如更改图标,提示文字等。
lpData参数指向一个NOTIFYICONDATA结构,该结构的具体描述如下:
Type NOTIFYICONDATA
cbSize As Long '指定NOTIFYICONDATA结构的长度
hwnd As Long '指向接收回调消息的窗体或控件的句柄
uID As Long '指定系统通知区图标的ID标识值
uFlags As Long '指定将要绘制的图标的属性。它是NIF_ICON、
NIF_MESSAGE和NIF_TIP三个值的组合
uCallbackMessage As Long '指定一条自定义的回调消息
hIcon As Long '指定一个图标的句柄,该句柄指向的图标将显示在
系统通知区上
szTip As String * 64 '指定图标的提示文字,当鼠标停留在图标区域时,将
显示该提示文字
End Type
二、如何接收系统通知区的鼠标消息
在系统通知区上绘制出图标后,当鼠标单击或双击该图标时,必须想办法使程序能接收
到这些消息。这是一个难点。前面说过,如果您有能拦截系统消息的第三方控件,那么您就
可以轻松地实现此目的。如果没有,那该怎么办呢?幸好VB5.0为我们新引入了一个函数
AddressOf()。利用它,我们可以获得变量、函数或过程的内存地址。因此,可以在VB中
实现用自定义的回调函数来截取消息,并处理发送给窗口的消息,实现窗体控件子分类的技
术。这里,应用程序自定义的回调函数说明如下:
Function WindowProc(hwnd, uMsg, wParam, lParam) As Long
该函数中,Hwnd参数标识接收消息的窗口或控件的句柄;uMsg参数指定接收到的消息,这里
它应该是NOTIFYICONDATA结构里自定义的消息,程序中我们将对这条消息进行处理;
wParam参数指定附加的消息信息,该参数的内容依赖于uMsg参数的值;lParam参数指定附加
消息。函数名WindowProc可以取您想到的任何名称。但特别要注意的是,在处理完消息后,
应用程序还必须调用win32 API 中的CallWindowProc()函数,将消息传递给以前的窗口过
程。否则程序将出现"执行非法操作"的程序错误消息。
下面就以一个简单例子来具体说明如何在系统通知区绘制图标。在该例子中,单击
Command1将在系统通知区显示一个图标,并隐藏窗体;单击系统通知区图标,将切换窗体
的显示状态。
1、添加一个公共模块,声明API函数和常量(本文所用的所有API函数和常量均可从
API Viewer中粘贴得到)。在本模块中还定义了一个回调函数SubWndProc(),在该函数中,
将对接收到的系统通知区鼠标消息进行处理。
Option Explicit
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
Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias "Shell_NotifyIconA" _
(ByVal dwMessage As Long, lpData As NOTIFYICONDATA) As Long
Declare Function LoadIcon Lib "user32" Alias "LoadIconA" _
(ByVal hInstance As Long, ByVal lpIconName As String) As Long
Declare Function ExtractIcon Lib "shell32.dll" Alias "ExtractIconA" _
(ByVal hInst As Long, ByVal lpszExeFileName As String, ByVal nIconIndex As Long) As Long
Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" (ByVal lpString1 As String, ByVal
lpString2 As String) As Long
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 GetWindowLong Lib "user32" Alias "GetWindowLongA" ( _
ByVal hwnd As Long, ByVal nIndex 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
Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, lParam As Any) As Long
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 uFlags = NIF_ICON Or NIF_MESSAGE Or NIF_TIP
Public Const WM_USER = &H400
Public Const TRAY_CALLBACK = WM_USER + 100
Public Const GWL_USERDATA = (-21)
Public Const GWL_WNDPROC = (-4)
Public PreWndProc As Long
Public Function SubWndProc(ByVal hwnd As Long, ByVal MSG As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
If MSG = TRAY_CALLBACK Then
SendMessage hwnd, lParam, wParam, 0& '将鼠标消息发送给comTray按钮
End If
SubWndProc = CallWindowProc(PreWndProc, hwnd, MSG, wParam, lParam)
End Function