NotifyBar.cls :
2
3 Private Type POINTAPIs
4 x As Long
5 y As Long
6 End Type
7
8 Private Type NOTIFYICONDATA
9 cbSize As Long
10 hwnd As Long
11 uID As Long
12 uFlags As Long
13 uCallbackMessage As Long
14 hIcon As Long
15 szTip As String * 128
16 dwState As Long
17 dwStateMask As Long
18 szInfo As String * 256
19 uTimeout As Long
20 szInfoTitle As String * 64
21 dwInfoFlags As Long
22 End Type
23
24 Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, Optional ByVal Length As Long = 4)
25 Private 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
26 Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
27 Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
28 Private Declare Function VirtualProtect Lib "kernel32" (lpAddress As Any, ByVal dwSize As Long, ByVal flNewProtect As Long, lpflOldProtect As Long) As Long
29 Private Declare Function CreateWindowEx Lib "user32" Alias "CreateWindowExA" (ByVal dwExStyle As Long, ByVal lpClassName As String, ByVal lpWindowName As String, ByVal dwStyle As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, lpParam As Any) As Long
30 Private Declare Function GetDesktopWindow Lib "user32" () As Long
31 Private Declare Function Shell_NotifyIcon Lib "shell32" Alias "Shell_NotifyIconA" (ByVal dwMessage As NotifyBarActions, pnid As NOTIFYICONDATA) As Long
32 Private Declare Function DestroyWindow Lib "user32" (ByVal hwnd As Long) As Long
33 Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPIs) As Long
34 Private Declare Function RegisterWindowMessage Lib "user32" Alias "RegisterWindowMessageA" (ByVal lpString As String) As Long
35 Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long
36
37 Enum NotifyClickClass
38 NCL_MouseMove = 0
39 NCL_DoubleClick = 1
40 NCL_LeftButtonClick = 2
41 NCL_RightButtonClick = 3
42 End Enum
43
44 Enum NotifyMessageIcons
45 NIIF_NONE = &H0
46 NIIF_INFO = &H1
47 NIIF_WARNING = &H2
48 NIIF_ERROR = &H3
49 NIIF_GUID = &H4
50 End Enum
51
52 Private Enum NotifyBarActions
53 NIM_ADD = &H0
54 NIM_MODIFY = &H1
55 NIM_DELETE = &H2
56 NIM_SETFOCUS = &H3
57 NIM_SETVERSION = &H4
58 End Enum
59
60 Private Const NOTIFYICON_VERSION = 3 'V5 style taskbar
61 Private Const NOTIFYICON_OLDVERSION = 0 'Win95 style taskbar
62
63 Private Const NIS_HIDDEN = &H1
64 Private Const NIS_SHAREDICON = &H2
65
66 Private Const NIF_STATE = &H8
67 Private Const NIF_MESSAGE = &H1
68 Private Const NIF_ICON = &H2
69 Private Const NIF_TIP = &H4
70 Private Const NIF_INFO = &H10
71
72 Private Const WM_NOTIFYMESSAGE = 11122
73
74 Event NotifyClick(NClickClass As NotifyClickClass, ByVal x As Long, ByVal y As Long)
75
76 Private Type ThisClassSet
77
78 s_wm_TaskBarCreated As Long
79
80 n_HandleOfWindow As Long
81 s_AddressOfWndProc As Long
82
83 n_NotifyData As NOTIFYICONDATA
84
85 n_ClickSign As Boolean
86
87 End Type
88 Dim PG As ThisClassSet
89 Dim LinkProc() As Long
90
91 Private Sub MsgHook(Result As Long, ByVal cHwnd As Long, ByVal Message As Long, ByVal wParam As Long, ByVal lParam As Long)
92
93 '子类化接口过程
94
95 Const WM_MOUSEMOVE = &H200
96 Const WM_LBUTTONDBLCLK = &H203
97 Const WM_LBUTTONDOWN = &H201
98 Const WM_LBUTTONUP = &H202
99 Const WM_RBUTTONDOWN = &H204
100 Const WM_RBUTTONUP = &H205
101
102 Dim Pss As POINTAPIs
103
104 Result = CallWindowProc(PG.s_AddressOfWndProc, cHwnd, Message, wParam, lParam)
105
106 If Message = PG.n_NotifyData.uCallbackMessage Then
107
108 GetCursorPos Pss
109
110 Select Case lParam
111 Case WM_MOUSEMOVE: RaiseEvent NotifyClick(NCL_MouseMove, Pss.x, Pss.y)
112 Case WM_LBUTTONDBLCLK: RaiseEvent NotifyClick(NCL_DoubleClick, Pss.x, Pss.y)
113 Case WM_LBUTTONDOWN, WM_RBUTTONDOWN: PG.n_ClickSign = True
114 Case WM_LBUTTONUP
115 If PG.n_ClickSign Then RaiseEvent NotifyClick(NCL_LeftButtonClick, Pss.x, Pss.y)
116 PG.n_ClickSign = False
117
118 Case WM_RBUTTONUP
119 SetForegroundWindow cHwnd
120 If PG.n_ClickSign Then RaiseEvent NotifyClick(NCL_RightButtonClick, Pss.x, Pss.y)
121 PG.n_ClickSign = False
122
123 End Select
124
125 ElseIf Message = PG.s_wm_TaskBarCreated Then
126
127 If PG.n_NotifyData.cbSize Then
128
129 PG.n_NotifyData.uFlags = NIF_ICON Or NIF_MESSAGE Or NIF_TIP
130 Shell_NotifyIcon NIM_ADD, PG.n_NotifyData
131
132 End If
133 End If
134
135 End Sub
136
137 Private Function GetWndProcAddress(ByVal SinceCount As Long) As Long
138 ' 地址指针 = GetWndProcAddress( SinceCount = 所有公用过程(例: Function,Sub,Property,公共变量) 总和 + 第 N 个 Private function/sub )
139 '// 本例是取 MsgHook 函数地址, SinceCount 取值 12 ,可自行依例验证
140 Dim mePtr As Long
141 Dim jmpAddress As Long
142 mePtr = ObjPtr(Me)
143 CopyMemory jmpAddress, ByVal mePtr, 4
144 CopyMemory jmpAddress, ByVal jmpAddress + (SinceCount - 1) * 4 + &H1C, 4
145
146 ReDim LinkProc(10)
147 LinkProc(0) = &H83EC8B55
148 LinkProc(1) = &HFC8B14EC
149 LinkProc(2) = &H56FC758D
150 LinkProc(3) = &H3308758D
151 LinkProc(4) = &HFC04B1C9
152 LinkProc(5) = &HFF68A5F3
153 LinkProc(6) = &HB8FFFFFF
154 LinkProc(7) = &HFFFFFFFF
155 LinkProc(8) = &H48BD0FF
156 LinkProc(9) = &H10C2C924
157
158 CopyMemory ByVal VarPtr(LinkProc(5)) + 3, mePtr, 4
159 CopyMemory ByVal VarPtr(LinkProc(7)), jmpAddress, 4
160 GetWndProcAddress = VarPtr(LinkProc(0))
161 VirtualProtect ByVal VarPtr(LinkProc(0)), 44, &H40, mePtr
162 End Function
163
164 Private Sub Class_Initialize()
165
166 PG.n_HandleOfWindow = CreateWindowEx(0, "button", vbNullString, &H40010F00, 0, 0, 10, 10, GetDesktopWindow&, ByVal 10&, App.hInstance, ByVal 0&)
167
168 PG.n_NotifyData.uID = 1
169 PG.n_NotifyData.hwnd = PG.n_HandleOfWindow
170 PG.n_NotifyData.uCallbackMessage = WM_NOTIFYMESSAGE
171 PG.s_AddressOfWndProc = SetWindowLong(ByVal PG.n_HandleOfWindow, ByVal -4&, ByVal GetWndProcAddress(12))
172 PG.s_wm_TaskBarCreated = RegisterWindowMessage("TaskbarCreated")
173 End Sub
174
175 Private Sub Class_Terminate()
176
177 Debug.Print "Start !NotifyBar Terminate ...", Timer
178
179 SetWindowLong PG.n_HandleOfWindow, -4&, PG.s_AddressOfWndProc
180 NotifyBoxVisible = False
181 DestroyWindow PG.n_HandleOfWindow
182
183 Debug.Print "NotifyBar Terminate ... end ", Timer
184
185 End Sub
186
187 Public Property Get Icon() As Long
188 '// Notify Icon
189 Icon = PG.n_NotifyData.hIcon
190 End Property
191
192 Public Property Let Icon(ByVal vNewValue As Long)
193
194 With PG.n_NotifyData
195 .uFlags = NIF_ICON Or .uFlags
196 .hIcon = vNewValue
197 End With
198
199 If PG.n_NotifyData.cbSize Then
200 PG.n_NotifyData.uFlags = NIF_ICON
201 Shell_NotifyIcon NIM_MODIFY, PG.n_NotifyData
202 End If
203
204 End Property
205
206 Public Property Get HandleOfNotifybar() As Long
207 '// Notify hWnd
208 HandleOfNotifybar = PG.n_NotifyData.hwnd
209 End Property
210
211 Public Property Let HandleOfNotifybar(ByVal vNewValue As Long)
212
213 PG.n_NotifyData.hwnd = vNewValue
214 If PG.n_NotifyData.cbSize Then _
215 Shell_NotifyIcon NIM_MODIFY, PG.n_NotifyData
216
217 End Property
218
219 Public Property Get CallBackMessage() As Long
220 '// Notify uCallbackMessage
221 CallBackMessage = PG.n_NotifyData.uCallbackMessage
222 End Property
223
224 Public Property Let CallBackMessage(ByVal vNewValue As Long)
225
226 PG.n_NotifyData.uFlags = NIF_MESSAGE Or PG.n_NotifyData.uFlags
227 PG.n_NotifyData.uCallbackMessage = vNewValue
228
229 If PG.n_NotifyData.cbSize Then
230 PG.n_NotifyData.uFlags = NIF_MESSAGE
231 Shell_NotifyIcon NIM_MODIFY, PG.n_NotifyData
232 End If
233
234 End Property
235
236 Public Property Get ToolTipText() As String
237 '// ToolTips
238 ToolTipText = PG.n_NotifyData.szTip
239 End Property
240
241 Public Property Let ToolTipText(ByVal vNewValue As String)
242
243 With PG.n_NotifyData
244 .uFlags = NIF_TIP Or .uFlags
245 .szTip = vNewValue & vbNullChar
246 End With
247
248 If PG.n_NotifyData.cbSize Then
249 PG.n_NotifyData.uFlags = NIF_TIP
250 Shell_NotifyIcon NIM_MODIFY, PG.n_NotifyData
251 End If
252
253 End Property
254
255 Sub NotifyMsgBox(ByVal strMessage As String, Optional ByVal strTitle As String = "Application Notify", Optional ByVal NotifyMessageIcon As NotifyMessageIcons = NIIF_NONE)
256
257 '// Notify MessageBox
258 With PG.n_NotifyData
259 .uFlags = NIF_INFO Or .uFlags
260 .szInfo = strMessage & vbNullChar
261 .szInfoTitle = strTitle & vbNullChar
262 .dwInfoFlags = NotifyMessageIcon
263 End With
264
265 If PG.n_NotifyData.cbSize Then
266 PG.n_NotifyData.uFlags = NIF_INFO
267 Shell_NotifyIcon NIM_MODIFY, PG.n_NotifyData
268 End If
269 End Sub
270
271 Public Property Get NotifyBoxVisible() As Boolean
272 '// Notify visible
273 If PG.n_NotifyData.cbSize Then NotifyBoxVisible = True
274 End Property
275
276 Public Property Let NotifyBoxVisible(ByVal vNewValue As Boolean)
277
278 If vNewValue Then
279 CallBackMessage = PG.n_NotifyData.uCallbackMessage
280 PG.n_NotifyData.cbSize = Len(PG.n_NotifyData)
281 Shell_NotifyIcon NIM_ADD, PG.n_NotifyData
282
283 Else
284 PG.n_NotifyData.uFlags = 0
285 Shell_NotifyIcon NIM_DELETE, PG.n_NotifyData
286 PG.n_NotifyData.cbSize = 0
287 End If
288
289 End Property
一个托盘图标类, 包括:
自实现的窗口实现托盘消息管理
NotifyBar
.Icon(属性) 托盘图标属性,直接赋值图标, 具体可参考实例代码; 动态换图标由调用端联合 Timer 配合 Icon 属性自己实现即可
.HandleOfNotifybar(属性) 托盘图标的消息接受窗口句柄,这个窗口是自动创建的,非必须勿改,且如必须更改则应在显示图标之前调用此属性更改
.CallBackMessage(属性) 自定义托盘消息,非需勿改,有默认值
.ToolTipText(属性) 托盘图标的工具提示
.NotifyMsgBox(方法) 托盘的气泡提示: NotifyMsgBox (气泡通知内容, 气泡通知标题,气泡通知类型[包含4个类型的枚举,分别表示用不同的图标])
.NotifyBoxVisible(属性) 启用/停用 托盘图标,如果需要对 HandleOfNotifybar、CallBackMessage 属性自定义修改,则应该在此属性之前调用
NotifyClick (事件) 托盘图标鼠标事件,提供 MouseMove,LeftButtonClick,RightButtonClick,LBDoubleClick,4个事件
'// 托盘图标事件
Select Case NClickClass
Case NCL_MouseMove: Debug.Print “这是鼠标 MouseMove 事件”
Case NCL_LeftButtonClick: Debug.Print “这是鼠标 左键点击 事件”
Case NCL_RightButtonClick: Debug.Print “这是鼠标 右键单击 事件”
Case NCL_DoubleClick: Debug.Print “这是鼠标 左键双击 事件”
'//Case 右键双击 因应用范围、方式等原因,该事件未提供, 如需要请自行修改 NotifyBar 类 MsgHook 过程的相关代码添加即可
End Select
End Sub
一般情况下,使用时,最后调用 NotifyBoxVisible 属性将托盘图标显示出来即可; 所有属性都支持动态修改;
系统资源管理器崩溃后,托盘图标会按照 NotifyBar 最后一次的记录的属性自动重建托盘图标.
实例工程演示:
Download:
https://files.cnblogs.com/pctgl/%E6%89%98%E7%9B%98%E5%9B%BE%E6%A0%87.rar