1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
| LOCAL oForm As TForm
oForm = CREATEOBJECT("TForm")
oForm.Show(1)
* end of main
#DEFINE CRLF CHR(13)+CHR(10)
#DEFINE NIM_ADD 0
#DEFINE NIM_MODIFY 1
#DEFINE NIM_DELETE 2
#DEFINE NIF_MESSAGE 1
#DEFINE NIF_ICON 2
#DEFINE NIF_TIP 4
#DEFINE NIF_INFO 0x10
#DEFINE NIIF_INFO 0x0001
#DEFINE NIIF_WARNING 0x0002
#DEFINE NIIF_USER 0x0004
#DEFINE NIIF_LARGE_ICON 0x0020
#DEFINE NOTIFYICON_VERSION 3
#DEFINE NOTIFYICON_VERSION_4 4
#DEFINE NOTIFYICONDATA_SIZE 88
#DEFINE NOTIFYICONDATA_XP_SIZE NOTIFYICONDATA_SIZE+400
#DEFINE MAX_PATH 260
#DEFINE GWL_WNDPROC -4
#DEFINE IMAGE_ICON 1
#DEFINE LR_LOADFROMFILE 0x0010
#DEFINE LR_DEFAULTSIZE 0x0040
#DEFINE WM_MOUSEMOVE 0x0200
#DEFINE WM_LBUTTONDOWN 0x0201
#DEFINE WM_LBUTTONUP 0x0202
#DEFINE WM_RBUTTONDOWN 0x0204
#DEFINE WM_RBUTTONUP 0x0205
#DEFINE WM_MBUTTONDOWN 0x0207
#DEFINE WM_MBUTTONUP 0x0208
DEFINE CLASS TForm As Form
Width=350
Height=200
BorderStyle=2
MinButton=.F.
MaxButton=.F.
Caption="Systray Icon"
Autocenter=.T.
ADD OBJECT taskbaricon As TaskbarStatus
ADD OBJECT sbar As Tbar WITH Top=398, Left=0, Height=21, Width=685
ADD OBJECT chShowIcon As CheckBox WITH;
Left=15, Top=15, Caption="Show Icon", Autosize=.T.
ADD OBJECT cmdLoadIcon As CommandButton WITH;
Left=120, Top=10, Width=140, Height=27,;
Caption="Load Icon from file"
ADD OBJECT cmdBalloon As CommandButton WITH;
Left=120, Top=70, Width=140, Height=27,;
Caption="Show Balloon", Enabled=.F.
PROCEDURE cmdBalloon.Click
LOCAL cBlnMessage, cBlnCaption, nBlnIconId
cBlnMessage="As of Windows XP Service Pack 2 (SP2), a custom icon " +;
"can be displayed in the notification balloon." +CRLF+CRLF +;
"This allows the calling process to customize " +;
"the notification beyond the previously available options of info, " +;
"warning, and error."
cBlnCaption="Event Notification"
* nBlnIconId=BITOR(NIIF_USER, NIIF_LARGE_ICON)
nBlnIconId=BITOR(NIIF_INFO, NIIF_LARGE_ICON)
ThisForm.taskbaricon.DisplayBalloon(;
cBlnMessage, cBlnCaption, nBlnIconId)
PROCEDURE chShowIcon.Click
LOCAL lShow
lShow=ThisForm.ShowIcon(THIS.Value)
STORE lShow TO ThisForm.cmdBalloon.Enabled
PROCEDURE cmdLoadIcon.Click
ThisForm.LoadIcon
PROCEDURE taskbaricon.OnUdfMessage
PARAMETERS wParam As Integer, lParam As Integer
DODEFAULT()
DO CASE
CASE lParam=WM_MOUSEMOVE
ThisForm.sbar.Panels(1).Text = "Mouse moves: " +;
TRANS(THIS.LastMouseX) + ", " + TRANS(THIS.LastMouseY)
CASE lParam=WM_LBUTTONDOWN
ThisForm.sbar.Panels(2).Text = "Left Button Down"
CASE lParam=WM_LBUTTONUP
ThisForm.sbar.Panels(2).Text = "Left Button Up"
CASE lParam=WM_RBUTTONDOWN
ThisForm.sbar.Panels(2).Text = "Right Button Down"
CASE lParam=WM_RBUTTONUP
ThisForm.sbar.Panels(2).Text = "Right Button Up"
CASE lParam=WM_MBUTTONDOWN
ThisForm.sbar.Panels(2).Text = "Middle Button Down"
CASE lParam=WM_MBUTTONUP
ThisForm.sbar.Panels(2).Text = "Middle Button Up"
ENDCASE
PROCEDURE ShowIcon(nMode)
* shows or hides icon in the systray
WITH THIS.taskbaricon
IF nMode = 0
.DeleteIcon
RETURN .F.
ELSE
.baloon = VERSION()
.InitIcon(.GetDefaultIcon())
RETURN .T.
ENDIF
ENDWITH
PROCEDURE LoadIcon
* loads icon from a file and displays in the systray
LOCAL cPath, cIconFile
cPath = SYS(5) + SYS(2003)
cIconFile = GETFILE("ico", "Load icon file")
SET DEFAULT TO (m.cPath)
IF NOT EMPTY(m.cIconFile)
THIS.taskbaricon.baloon = LOWER(m.cIconFile)
THIS.taskbaricon.InitIcon(m.cIconFile)
THIS.chShowIcon.Value=1
ENDIF
ENDDEFINE
DEFINE CLASS Tbar As OleControl
OleClass="MSComctlLib.SBarCtrl.2"
PROCEDURE Init
THIS.Height=21
THIS.Panels.Add
THIS.Panels(1).Width = 160
THIS.Panels(2).Width = 700
ENDDEFINE
DEFINE CLASS TaskbarStatus As Custom
hWindow=0
AppID=1
MessageID=0x4001
hOrigProc=0
hIcon=0
baloon=""
LastMouseX=0
LastMouseY=0
PROCEDURE Init
THIS.declare
THIS.hWindow = _screen.HWnd
THIS.hOrigProc = GetWindowLong(THIS.hWindow, GWL_WNDPROC)
PROCEDURE Destroy
THIS.DeleteIcon
PROCEDURE DeleteIcon
IF THIS.hIcon <> 0
THIS.SetIcon(NIM_DELETE)
= DestroyIcon(THIS.hIcon)
THIS.hIcon = 0
IF VERSION(5) >= 900 && VFP9+
= UNBINDEVENTS(THIS.hWindow)
ENDIF
ENDIF
PROCEDURE InitIcon(hIcon)
THIS.DeleteIcon
DO CASE
CASE VARTYPE(m.hIcon)="N"
THIS.hIcon = m.hIcon
CASE VARTYPE(m.hIcon)="C"
THIS.hIcon = THIS.LoadIcon(m.hIcon)
OTHERWISE
RETURN
ENDCASE
THIS.SetIcon(NIM_ADD)
PROCEDURE DisplayBalloon(cBlnMessage, cBlnCaption, nBlnIconId)
LOCAL cNotifyIcondDataEx, nFlags, nVersion
nFlags=NIF_INFO
nVersion=NOTIFYICON_VERSION
IF EMPTY(cBlnMessage)
cBlnMessage=THIS.baloon
ENDIF
IF EMPTY(cBlnCaption)
cBlnCaption=""
ENDIF
IF EMPTY(nBlnIconId)
nBlnIconId=0
ENDIF
cNotifyIcondDataEx =;
num2dword(NOTIFYICONDATA_XP_SIZE) +;
num2dword(THIS.hWindow) +;
num2dword(THIS.appid) +;
num2dword(m.nFlags) +;
num2dword(THIS.MessageID) +;
num2dword(THIS.hIcon) +;
PADR(THIS.baloon, 128, Chr(0)) +;
num2dword(0) +;
num2dword(0) +;
PADR(cBlnMessage, 256, CHR(0)) +;
num2dword(nVersion) +;
PADR(m.cBlnCaption, 64, CHR(0)) +;
num2dword(nBlnIconId)
cNotifyIcondDataEx = PADR(cNotifyIcondDataEx,;
NOTIFYICONDATA_XP_SIZE, CHR(0))
Shell_NotifyIcon(NIM_MODIFY, @cNotifyIcondDataEx)
PROCEDURE SetIcon(cAction, nFlags)
LOCAL cNOTIFYICONDATA
IF EMPTY(nFlags)
nFlags=BITOR(NIF_ICON, NIF_MESSAGE, NIF_TIP)
ENDIF
cNOTIFYICONDATA =;
num2dword(NOTIFYICONDATA_SIZE) +;
num2dword(THIS.hWindow) +;
num2dword(THIS.appid) +;
num2dword(m.nFlags) +;
num2dword(THIS.MessageID) +;
num2dword(THIS.hIcon) +;
PADR(THIS.baloon, 64, Chr(0))
cNOTIFYICONDATA=PADR(cNOTIFYICONDATA,;
NOTIFYICONDATA_SIZE, CHR(0))
IF Shell_NotifyIcon(m.cAction, @cNOTIFYICONDATA) <> 0
IF VERSION(5) >= 900 && VFP9+
= BINDEVENT(THIS.hWindow, THIS.MessageID, THIS, "HookedWindowProc")
ENDIF
ENDIF
PROCEDURE GetMousePos(nX, nY)
* retrieves position of the cursor in screen coordinates
LOCAL cBuffer
cBuffer = REPLICATE(Chr(0), 8)
= GetCursorPos(@cBuffer)
nX = buf2dword(SUBSTR(cBuffer, 1,4))
nY = buf2dword(SUBSTR(cBuffer, 5,4))
PROCEDURE LoadIcon(cIconFile)
* loads icon from a file
LOCAL hIcon
TRY
hIcon = LoadImage(0, m.cIconFile, IMAGE_ICON,;
0,0, LR_LOADFROMFILE+LR_DEFAULTSIZE)
CATCH
hIcon=0
ENDTRY
RETURN m.hIcon
PROCEDURE GetDefaultIcon
* loads application icon
LOCAL cBuffer, nBufsize, nIconIndex, hIcon
cBuffer = REPLICATE(CHR(0), MAX_PATH)
nBufsize = GetModuleFileName (0, @cBuffer, MAX_PATH)
cBuffer = LEFT(cBuffer, nBufsize)
nIconIndex = 0 && works as a reference only
hIcon = ExtractAssociatedIcon(0, cBuffer, @nIconIndex)
RETURN m.hIcon
PROCEDURE OnUdfMessage(wParam As Integer, lParam As Integer)
* you will probably want to subclass this
LOCAL nX, nY
STORE 0 TO nX, nY
THIS.GetMousePos(@nX, @nY)
THIS.LastMouseX=m.nX
THIS.LastMouseY=m.nY
PROCEDURE HookedWindowProc(hWindow as Integer,;
nMsgID as Integer, wParam as Integer, lParam as Integer)
* requires VFP9, otherwise ignored
* note that input parameters are predefined and should not be changed
* see WindowProc function for details
LOCAL nReturn
nReturn=0
DO CASE
CASE nMsgID=THIS.MessageID
THIS.OnUdfMessage(wParam, lParam)
OTHERWISE
* pass control to the original window procedure
nReturn = CallWindowProc(THIS.hOrigProc, THIS.hWindow,;
m.nMsgID, m.wParam, m.lParam)
ENDCASE
RETURN nReturn
PROTECTED PROCEDURE declare
DECLARE INTEGER DestroyIcon IN user32 INTEGER hIcon
DECLARE INTEGER SetForegroundWindow IN user32 INTEGER hWindow
DECLARE INTEGER GetCursorPos IN user32 STRING @ lpPoint
DECLARE INTEGER Shell_NotifyIcon IN shell32 INTEGER dwMsg, STRING @lpdata
DECLARE INTEGER GetWindowLong IN user32 INTEGER hWindow, INTEGER nIndex
DECLARE INTEGER ExtractAssociatedIcon IN shell32;
INTEGER hInst, STRING lpIconPath, INTEGER @lpiIcon
DECLARE INTEGER GetModuleFileName IN kernel32;
INTEGER hModule, STRING @lpFilename, INTEGER nSize
DECLARE INTEGER CallWindowProc IN user32;
INTEGER lpPrevWndFunc, INTEGER hWindow, LONG Msg,;
INTEGER wParam, INTEGER lParam
DECLARE INTEGER LoadImage IN user32;
INTEGER hinst, STRING lpszName, INTEGER uType,;
INTEGER cxDesired, INTEGER cyDesired, INTEGER fuLoad
ENDDEFINE
FUNCTION buf2dword(cBuffer)
RETURN Asc(SUBSTR(cBuffer, 1,1)) + ;
BitLShift(Asc(SUBSTR(cBuffer, 2,1)), 8) +;
BitLShift(Asc(SUBSTR(cBuffer, 3,1)), 16) +;
BitLShift(Asc(SUBSTR(cBuffer, 4,1)), 24)
FUNCTION num2dword(nValue)
#DEFINE m0 0x0100
#DEFINE m1 0x010000
#DEFINE m2 0x01000000
IF nValue < 0
nValue = 0x100000000 + nValue
ENDIF
LOCAL b0, b1, b2, b3
b3 = Int(nValue/m2)
b2 = Int((nValue - b3*m2)/m1)
b1 = Int((nValue - b3*m2 - b2*m1)/m0)
b0 = Mod(nValue, m0)
RETURN Chr(b0)+Chr(b1)+Chr(b2)+Chr(b3) |