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
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
| '------------------------------------------------------------------
' Name: modCBMenuHelpers (MODCBMENUHELPERS.BAS)
' Type: Utility API wrapper module.
' Description: Contains commonly-used 'macros' and calls to facilitate
' working with API-created menus. If you want a more object-
' oriented way of doing menus, grab the CPopupMenu class and
' sample(s) from the VBBox
'
' Author: Klaus H. Probst [kprobst@vbbox.com]
' URL: http://www.vbbox.com/
' Copyright: This work is copyrighted © 1999, Klaus H. Probst
' Usage: You may use this code as you see fit, provided that you assume all
' responsibilities for doing so.
' Distribution: If you intend to distribute the file(s) that make up this sample to
' any WWW site, online service, electronic bulletin board system (BBS),
' CD or any other electronic or physical media, you must notify me in
' advance to obtain my express permission.
'
' Notes:
'
' The module makes use of the "new" menu APIs (introduced with Win32). These
' are the ones that take a MENUITEMINFO structure as a parameter, and supercede
' most of the older menu APIs. The declaration for the other ones are included,
' though, but not really used except for RemoveMenu() and DeleteMenu().
' The "new" way to append a submenu to an existing popup menu is to create
' a simple string item and then set it to MF_SUBMENU, which is what the
' mnuSimpleItemToSubmenu() function does. In the old days, you would use
' AppendMenu() or InsertMenu() to do this. It's a bit confusing at first, but
' you get used to it <g>
' The mnuPopMenu() function does not use the RECT exclusion facilities in
' TrackPopupMenuEx(). If you need those, you can add them fairly easily.
' The mnuAddBreak() function has not been tested at all.
'
' Platform:
'
' Any version of 32-bit Windows.
' If you encounter any problems I'd like to hear about it. My e-mail address is above.
'
' Dependencies:
'
' (struct) RECT, POINTAPI
' (API) GetCursorPos
'
'------------------------------------------------------------------------------------------------------
Option Explicit
DefLng A-Z
Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Type POINTAPI
x As Long
y As Long
End Type
Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
'Bepaal wie de 'eigenaar' is van het clipboard
Declare Function GetClipboardOwner Lib "user32" () As Long
'// Used by TrackPopupMenuEx()
Type TPMPARAMS
cbSize As Long
rcExclude As RECT
End Type
'// Used by the "new" menu APIs
Type MENUITEMINFO
cbSize As Long
fMask As Long
fType As Long '// used if MIIM_TYPE
fState As Long '// used if MIIM_STATE
lngID As Long '// used if MIIM_ID
hSubMenu As Long '// used if MIIM_SUBMENU
hbmpChecked As Long '// used if MIIM_CHECKMARKS
hbmpUnchecked As Long '// used if MIIM_CHECKMARKS
dwItemData As Long '// used if MIIM_DATA
dwTypeData As String '// used if MIIM_TYPE
cch As Long '// used if MIIM_TYPE
End Type
'// Menu API declarations
Declare Function DrawMenuBar Lib "user32" (ByVal hwnd As Long) As Long
Declare Function GetSystemMenu Lib "user32" (ByVal hwnd As Long, ByVal bRevert As Long) As Long
Declare Function CreatePopupMenu Lib "user32" () As Long
Declare Function DestroyMenu Lib "user32" (ByVal hMenu As Long) As Long
Declare Function GetSubMenu Lib "user32" (ByVal hMenu As Long, ByVal nPos As Long) As Long
Declare Function GetMenuItemCount Lib "user32" (ByVal hMenu As Long) As Long
Declare Function RemoveMenu Lib "user32" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long) As Long
Declare Function DeleteMenu Lib "user32" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long) As Long
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 Any) As Long
Declare Function TrackPopupMenu Lib "user32" (ByVal hMenu As Long, ByVal wFlags As Long, ByVal x As Long, ByVal y As Long, ByVal nReserved As Long, ByVal hwnd As Long, lprc As Any) As Long
'// "New" menu functions
Declare Function GetMenuItemInfo Lib "user32" Alias "GetMenuItemInfoA" (ByVal hMenu As Long, ByVal dwID As Long, ByVal fbool As Long, lpMenuItemInfo As MENUITEMINFO) As Long
Declare Function SetMenuItemInfo Lib "user32" Alias "SetMenuItemInfoA" (ByVal hMenu As Long, ByVal dwID As Long, ByVal fbool As Long, lpcMenuItemInfo As MENUITEMINFO) As Long
Declare Function InsertMenuItem Lib "user32" Alias "InsertMenuItemA" (ByVal hMenu As Long, ByVal un As Long, ByVal bool As Long, lpcMenuItemInfo As MENUITEMINFO) As Long
Declare Function CheckMenuRadioItem Lib "user32" (ByVal hMenu As Long, ByVal uFirst As Long, ByVal uLast As Long, ByVal uCheck As Long, ByVal uFlags As Long) As Long
'// TrackPopUpMenu() flags
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&
'// Newer flags for the "Ex" version
Public Const TPM_TOPALIGN = &H0&
Public Const TPM_VCENTERALIGN = &H10&
Public Const TPM_BOTTOMALIGN = &H20&
Public Const TPM_HORIZONTAL = &H0& '/* Horz alignment matters more */
Public Const TPM_VERTICAL = &H40& '/* Vert alignment matters more */
Public Const TPM_NONOTIFY = &H80& '/* Don't send any notification msgs */
Public Const TPM_RETURNCMD = &H100&
'// Menu item styles
Public Const MF_STRING = &H0&
Public Const MF_BITMAP = &H4&
Public Const MF_POPUP = &H10&
Public Const MF_SEPARATOR = &H800&
Public Const MF_USECHECKBITMAPS = &H200&
Public Const MF_OWNERDRAW = &H100&
Public Const MF_MENUBARBREAK = &H20&
Public Const MF_MENUBREAK = &H40&
'// Menu item states
Public Const MF_ENABLED = &H0&
Public Const MF_GRAYED = &H1&
Public Const MF_DISABLED = &H2&
Public Const MF_UNCHECKED = &H0&
Public Const MF_CHECKED = &H8&
Public Const MF_UNHILITE = &H0&
Public Const MF_HILITE = &H80&
Public Const MF_DEFAULT = &H1000
Public Const MF_RIGHTJUSTIFY = &H4000&
'// Menu action flags
Public Const MF_INSERT = &H0&
Public Const MF_CHANGE = &H80&
Public Const MF_APPEND = &H100&
Public Const MF_DELETE = &H200&
Public Const MF_REMOVE = &H1000&
Public Const MF_BYCOMMAND = &H0&
Public Const MF_BYPOSITION = &H400&
'// Menu flags
Public Const MF_SYSMENU = &H2000&
Public Const MF_HELP = &H4000&
Public Const MF_MOUSESELECT = &H8000&
'// Values for fMask
Public Const MIIM_STATE = &H1
Public Const MIIM_ID = &H2
Public Const MIIM_SUBMENU = &H4
Public Const MIIM_CHECKMARKS = &H8
Public Const MIIM_TYPE = &H10
Public Const MIIM_DATA = &H20
'// Values for fType
Public Const MFT_STRING = MF_STRING
Public Const MFT_BITMAP = MF_BITMAP
Public Const MFT_MENUBARBREAK = MF_MENUBARBREAK
Public Const MFT_MENUBREAK = MF_MENUBREAK
Public Const MFT_OWNERDRAW = MF_OWNERDRAW
Public Const MFT_RADIOCHECK = &H200&
Public Const MFT_SEPARATOR = MF_SEPARATOR
Public Const MFT_RIGHTORDER = &H2000&
Public Const MFT_RIGHTJUSTIFY = MF_RIGHTJUSTIFY
'// Values for fState
Public Const MFS_GRAYED = &H3&
Public Const MFS_DISABLED = MFS_GRAYED
Public Const MFS_CHECKED = MF_CHECKED
Public Const MFS_HILITE = MF_HILITE
Public Const MFS_ENABLED = MF_ENABLED
Public Const MFS_UNCHECKED = MF_UNCHECKED
Public Const MFS_UNHILITE = MF_UNHILITE
Public Const MFS_DEFAULT = MF_DEFAULT
'
'
'
'
Public Sub mnuCheckRadioGroup(ByVal hMenu As Long, ByVal idItem As Long, ByVal idFirst As Long, ByVal idLast As Long, Optional ByVal uFlags As Long = MF_BYCOMMAND)
Call CheckMenuRadioItem(hMenu, idFirst, idLast, idItem, uFlags)
End Sub
'
'
'
Public Sub mnuHighlightItem(ByVal hMenu As Long, ByVal id As Long)
Dim lpmim As MENUITEMINFO
With lpmim
.cbSize = Len(lpmim)
.fMask = MIIM_STATE
.fState = MFS_HILITE
End With
Call SetMenuItemInfo(hMenu, id, False, lpmim)
End Sub
'
'
'
Public Sub mnuAddBreak(ByVal hMenu As Long, Optional ByRef Position As Long = -1)
Dim lpmim As MENUITEMINFO
Dim lngPos As Long
Dim lngID As Long
If Position < 0 Then
lngPos = GetMenuItemCount(hMenu)
Else
lngPos = Position - 1
End If
With lpmim
.cbSize = Len(lpmim)
.fMask = MIIM_TYPE
.fType = MFT_MENUBREAK Or MFT_MENUBARBREAK
End With
Call InsertMenuItem(hMenu, lngPos, 1, lpmim)
Position = lngPos
End Sub
'
'
'
Public Sub mnuRemoveItemRange(hMenu As Long, ParamArray ItemList() As Variant)
Dim A&
For A& = LBound(ItemList) To UBound(ItemList)
Call DeleteMenu(hMenu, ItemList(A&), MF_BYCOMMAND)
Next A&
End Sub
'
'
'
Public Sub mnuSetItemDefault(ByVal hMenu As Long, ByVal id As Long, ByVal Default As Boolean)
Dim lpmim As MENUITEMINFO
Dim lngState As Long
If Default = True Then
lngState = id
Else
lngState = -1
End If
With lpmim
.cbSize = Len(lpmim)
.fMask = MIIM_STATE
.fState = MFS_DEFAULT
End With
Call SetMenuItemInfo(hMenu, lngState, False, lpmim)
End Sub
'
'
'
Public Sub mnuEnableItem(ByVal hMenu As Long, ByVal id As Long, ByVal Enabled As Boolean)
Dim lpmim As MENUITEMINFO
Dim lngState As Long
If Enabled = True Then
lngState = MFS_ENABLED
Else
lngState = MFS_GRAYED
End If
With lpmim
.cbSize = Len(lpmim)
.fMask = MIIM_STATE
.fState = lngState
End With
Call SetMenuItemInfo(hMenu, id, False, lpmim)
End Sub
'
'
'
Public Sub mnuCheckItem(ByVal hMenu As Long, ByVal id As Long, ByVal Checked As Boolean)
Dim lpmim As MENUITEMINFO
Dim lngState As Long
If Checked = True Then
lngState = MFS_CHECKED
Else
lngState = MFS_UNCHECKED
End If
With lpmim
.cbSize = Len(lpmim)
.fMask = MIIM_STATE
.fState = lngState
End With
Call SetMenuItemInfo(hMenu, id, False, lpmim)
End Sub
'
'
'
Public Sub mnuAddItem(ByVal hMenu As Long, Optional ByVal id As Long = -1, Optional ByRef Position As Long = -1, Optional ByVal Caption As String = "", Optional ByVal RadioCheck As Boolean = False)
Dim lpmim As MENUITEMINFO
Dim lngPos As Long
If Position < 0 Then
lngPos = GetMenuItemCount(hMenu)
Else
lngPos = Position
End If
With lpmim
.cbSize = Len(lpmim)
.fMask = MIIM_TYPE Or MIIM_ID Or MIIM_DATA
If Len(Caption) = 0 Then
.fType = MFT_SEPARATOR
id = 0
Else
.dwTypeData = Caption
.cch = Len(Caption)
.fType = MFT_STRING
If RadioCheck = True Then .fType = MFT_STRING Or MFT_RADIOCHECK
End If
.lngID = id
End With
Call InsertMenuItem(hMenu, lngPos, 1, lpmim)
Position = lngPos
End Sub
'
'
'
Public Sub mnuSetMenuCaption(ByVal hMenu As Long, ByVal id As Long, ByVal Caption As String)
Dim lpmim As MENUITEMINFO
With lpmim
.cbSize = Len(lpmim)
.fMask = MIIM_TYPE
.dwTypeData = Caption
.cch = Len(Caption)
.fType = MFT_STRING
End With
Call SetMenuItemInfo(hMenu, id, False, lpmim)
End Sub
'
'
'
Public Function mnuPopMenu(hMenu As Long, hwnd As Long, Optional flags As Long = 0, Optional x As Long = -1, Optional y As Long = -1) As Long
Dim lppt As POINTAPI
If x < 0 Or y < 0 Then
Call GetCursorPos(lppt)
Else
lppt.x = x
lppt.y = y
End If
mnuPopMenu = TrackPopupMenuEx(hMenu, flags, lppt.x, lppt.y, hwnd, ByVal 0&)
End Function
'
'
'
Public Sub mnuRemoveItem(ByVal hMenu As Long, ByVal id As Long, Optional ByVal Destroy As Boolean = True)
If Destroy = True Then
Call DeleteMenu(hMenu, id, MF_BYCOMMAND)
Else
Call RemoveMenu(hMenu, id, MF_BYCOMMAND)
End If
End Sub
'
'
'
Public Sub mnuSimpleItemToSubMenu(ByVal hMenu As Long, ByVal hSubMenu As Long, ByVal id As Long)
Dim lpmim As MENUITEMINFO
With lpmim
.cbSize = Len(lpmim)
.fMask = MIIM_SUBMENU
.hSubMenu = hSubMenu
End With
Call SetMenuItemInfo(hMenu, id, False, lpmim)
End Sub
'
'
'
Public Function mnuGetSubMenu(ByVal hMenu As Long, ByVal id As Long, Optional ByVal fByPosition As Boolean = True) As Long
Dim lpmim As MENUITEMINFO
With lpmim
.cbSize = Len(lpmim)
.fMask = MIIM_SUBMENU
.lngID = id
End With
Call GetMenuItemInfo(hMenu, id, Abs(fByPosition), lpmim)
mnuGetSubMenu = lpmim.hSubMenu
End Function |