View difference between Paste ID: 8NX0UisU and MKVkTjWz
SHOW: | | - or go back to the newest paste.
1
' SystemMenu Manager
2
'
3-
' // By Elektor H@cker
3+
' // By Elektro H@cker
4
5
#Region " SystemMenu Manager "
6
7
Public Class SystemMenuManager
8
    Inherits NativeWindow
9
    Implements IDisposable
10
11
    ' ----------------------------
12
    ' MSDN documentation Reference
13
    ' ----------------------------
14
    ' Menu Functions: http://msdn.microsoft.com/en-us/library/windows/desktop/ff468865%28v=vs.85%29.aspx
15
    ' MenuItemInfo  : http://msdn.microsoft.com/en-us/library/windows/desktop/ms647578%28v=vs.85%29.aspx
16
    ' MenuInfo      : http://msdn.microsoft.com/en-us/library/windows/desktop/ms647575%28v=vs.85%29.aspx
17
18
#Region " Variables "
19
20
    ''' <summary>
21
    ''' The form for which the system menu will be managed.
22
    ''' </summary>
23
    Private WithEvents form As Form = Nothing
24
25
    ''' <summary>
26
    ''' The handle of the form's system menu.
27
    ''' </summary>
28
    Private MenuHandle As IntPtr = IntPtr.Zero
29
30
    ''' <summary>
31
    ''' Stores a MenuInfo structure.
32
    ''' </summary>
33
    Private mi As New MenuInfo
34
35
    ''' <summary>
36
    ''' Stores a menuiteminfo structure.
37
    ''' </summary>
38
    Private mii As New MenuItemInfo
39
40
    ''' <summary>
41
    ''' Stores a menu item Text.
42
    ''' </summary>
43
    Private ItemText As New System.Text.StringBuilder With {.Capacity = 260}
44
45
    ''' <summary>
46
    ''' Brush used to paint the menu background.
47
    ''' </summary>
48
    Private MenuBrush As IntPtr = IntPtr.Zero
49
50
    ''' <summary>
51
    ''' Stores the ItemClickedEventArgs members.
52
    ''' </summary>
53
    Private ItemClickedArgs As New ItemClickedEventArgs
54
55
    ''' <summary>
56
    ''' The State of the Close item.
57
    ''' </summary>
58
    Private CloseItem_State As ItemState = ItemState.Enabled
59
60
    ''' <summary>
61
    ''' Stores the current state of each MenuItem.
62
    ''' </summary>
63
    Private ItemStates As New Dictionary(Of Item, ItemState) From
64
        {
65
          {Item.Close, Nothing},
66
          {Item.Move, Nothing},
67
          {Item.Maximize, Nothing},
68
          {Item.Minimize, Nothing},
69
          {Item.Restore, Nothing},
70
          {Item.Size, Nothing}
71
        }
72
73
    ''' <summary>
74
    ''' Stores the Bitmap image of each MenuItem.
75
    ''' </summary>
76
    Private ItemBitmaps As New Dictionary(Of Item, Bitmap) From
77
        {
78
          {Item.Close, Nothing},
79
          {Item.Move, Nothing},
80
          {Item.Maximize, Nothing},
81
          {Item.Minimize, Nothing},
82
          {Item.Restore, Nothing},
83
          {Item.Size, Nothing}
84
        }
85
86
    ''' <summary>
87
    ''' Stores the current state of each MenuItem specified by position.
88
    ''' </summary>
89
    Private PositionItemStates As New Dictionary(Of Integer, ItemState)
90
91
    ''' <summary>
92
    ''' Stores the Bitmap image of each MenuItem specified by position.
93
    ''' </summary>
94
    Private PositionItemBitmaps As New Dictionary(Of Integer, Bitmap)
95
96
#End Region ' Variables
97
98
#Region " Events "
99
100
    ''' <summary>
101
    ''' Event raised when a menu item is clicked.
102
    ''' </summary>
103
    Public Event ItemClicked As EventHandler(Of ItemClickedEventArgs)
104
    Public Class ItemClickedEventArgs : Inherits EventArgs
105
        ''' <summary>
106
        ''' Item Identifier.
107
        ''' </summary>
108
        Public Property ID As Integer
109
        ''' <summary>
110
        ''' Item Text.
111
        ''' </summary>
112
        Public Property Text As String
113
        ''' <summary>
114
        ''' Item State.
115
        ''' </summary>
116
        Public Property State As ItemState
117
        ''' <summary>
118
        ''' Item Type.
119
        ''' </summary>
120
        Public Property Type As ItemType
121
    End Class
122
123
#End Region ' Events
124
125
#Region " Enumerations "
126
127
    ''' <summary>
128
    ''' The menu Position ttype.
129
    ''' </summary>
130
    Public Enum ItemPosition As Integer
131
132
        ''' <summary>
133
        ''' The menu item is specified by command.
134
        ''' </summary>
135
        ByCommand = &H0
136
137
        ''' <summary>
138
        ''' The menu item is specified by position.
139
        ''' </summary>
140
        ByPosition = &H410
141
142
    End Enum
143
144
    ''' <summary>
145
    ''' The Menu Items.
146
    ''' </summary>
147
    Public Enum Item As Integer
148
149
        ''' <summary>
150
        ''' Closes the window.
151
        ''' </summary>
152
        Close = &HF060
153
154
        ''' <summary>
155
        ''' Moves the window.
156
        ''' </summary>
157
        Move = &HF010
158
159
        ''' <summary>
160
        ''' Maximizes the window.
161
        ''' </summary>
162
        Maximize = &HF030
163
164
        ''' <summary>
165
        ''' Minimizes the window.
166
        ''' </summary>
167
        Minimize = &HF020
168
169
        ''' <summary>
170
        ''' Restores the window to its normal position and size.
171
        ''' </summary>
172
        Restore = &HF120
173
174
        ''' <summary>
175
        ''' Sizes the window.
176
        ''' </summary>
177
        Size = &HF000
178
179
    End Enum
180
181
    ''' <summary>
182
    ''' The states that a menu item can have.
183
    ''' </summary>
184
    Public Enum ItemState As Integer
185
186
        ''' <summary>
187
        ''' The menu item is present and can be selected.
188
        ''' </summary>
189
        ''' <remarks>
190
        ''' This is the default state.
191
        ''' </remarks>
192
        Enabled = &H0
193
194
        ''' <summary>
195
        ''' The menu item is present but greyed-out and cannot be selected.
196
        ''' </summary>
197
        Grayed = &H1
198
199
        ''' <summary>
200
        ''' The menu item is present but can not be selected.
201
        ''' </summary>
202
        Disabled = &H2
203
204
        ''' <summary>
205
        ''' The menu item is not present.
206
        ''' </summary>
207
        Removed = -1
208
209
    End Enum
210
211
    ''' <summary>
212
    ''' Predefined menu item positions.
213
    ''' </summary>
214
    Public Enum DefaultPositions As Short
215
216
        ''' <summary>
217
        ''' Top position.
218
        ''' </summary>
219
        First = 0
220
221
        ''' <summary>
222
        ''' Second position.
223
        ''' </summary>
224
        Second = 1
225
226
        ''' <summary>
227
        ''' Third position.
228
        ''' </summary>
229
        Third = 2
230
231
        ''' <summary>
232
        ''' Middle position.
233
        ''' </summary>
234
        Middle = 3
235
236
        ''' <summary>
237
        ''' Penultimate position.
238
        ''' </summary>
239
        Penultimate = 4
240
241
        ''' <summary>
242
        ''' Bottom position.
243
        ''' </summary>
244
        Last = 5
245
246
    End Enum
247
248
    ''' <summary>
249
    ''' Mask type of the MenuItemInfo structure.
250
    ''' </summary>
251
    Public Enum ItemMask As Integer
252
253
        ''' <summary>
254
        ''' Retrieves or sets the "hbmpItem" member.
255
        ''' </summary>
256
        BITMAP = &H80
257
258
        ''' <summary>
259
        ''' Retrieves or sets the "hbmpChecked" and "hbmpUnchecked" members.
260
        ''' </summary>
261
        CHECKMARKS = &H8
262
263
        ''' <summary>
264
        ''' Retrieves or sets the "dwItemData" member.
265
        ''' </summary>
266
        DATA = &H20
267
268
        ''' <summary>
269
        ''' Retrieves or sets the "fType" member.
270
        ''' </summary>
271
        FTYPE = &H100
272
273
        ''' <summary>
274
        ''' Retrieves or sets the "wID" member.
275
        ''' </summary>
276
        ID = &H2
277
278
        ''' <summary>
279
        ''' Retrieves or sets the "fState" member.
280
        ''' </summary>
281
        STATE = &H1
282
283
        ''' <summary>
284
        ''' Retrieves or sets the "dwTypeData" member.
285
        ''' </summary>
286
        TEXT = &H40
287
288
        ''' <summary>
289
        ''' Retrieves or sets the "hSubMenu" member.
290
        ''' </summary>
291
        SUBMENU = &H4
292
293
        ''' <summary>
294
        ''' Retrieves or sets the "fType" and "dwTypeData" members.
295
        ''' "ItemMask.TYPE" is replaced by "ItemMask.BITMAP", "ItemMask.FTYPE", and "ItemMask.TEXT".
296
        ''' </summary>
297
        TYPE = &H10
298
299
    End Enum
300
301
    ''' <summary>
302
    ''' Item Type of the MenuItemInfo structure.
303
    ''' </summary>
304
    Public Enum ItemType As Long
305
306
        ''' <summary>
307
        ''' Displays the menu item using a bitmap. 
308
        ''' The low-order word of the dwTypeData member is the bitmap handle, and the cch member is ignored.
309
        ''' "ItemType.BITMAP" is replaced by "ItemMask.BITMAP" and "hbmpItem".
310
        ''' </summary>
311
        BITMAP = &H4L
312
313
        ''' <summary>
314
        ''' Displays selected menu items using a radio-button mark instead of a check mark if the hbmpChecked member is NULL.
315
        ''' </summary>
316
        RADIOCHECK = &H200L
317
318
        ''' <summary>
319
        ''' Specifies that the menu item is a separator.
320
        ''' A menu item separator appears as a horizontal dividing line. 
321
        ''' The dwTypeData and cch members are ignored. 
322
        ''' This value is valid only in a drop-down menu, submenu, or shortcut menu.
323
        ''' </summary>
324
        SEPARATOR = &H800L
325
326
        ''' <summary>
327
        ''' Displays the menu item using a text string.
328
        ''' The dwTypeData member is the pointer to a null-terminated string,
329
        ''' and the cch member is the length of the string.
330
        ''' "ItemType.TEXT" is replaced by "ItemMask.TEXT".
331
        ''' </summary>
332
        TEXT = &H0L
333
334
        ''' <summary>
335
        ''' Right-justifies the menu item and any subsequent items. 
336
        ''' This value is valid only if the menu item is in a menu bar.
337
        ''' </summary>
338
        RIGHTJUSTIFY = &H4000L
339
340
        ''' <summary>
341
        ''' Specifies that menus cascade right-to-left (the default is left-to-right).
342
        ''' This is used to support right-to-left languages, such as Arabic and Hebrew.
343
        ''' </summary>
344
        RIGHTORDER = &H2000L
345
346
        ''' <summary>
347
        ''' Places the menu item on a new line (for a menu bar),
348
        ''' or in a new column (for a drop-down menu, submenu, or shortcut menu).
349
        ''' For a drop-down menu, submenu, or shortcut menu, a vertical line separates the new column from the old.
350
        ''' </summary>
351
        MENUBARBREAK = &H20L
352
353
        ''' <summary>
354
        ''' Places the menu item on a new line (for a menu bar),
355
        ''' or in a new column (for a drop-down menu, submenu, or shortcut menu).
356
        ''' For a drop-down menu, submenu, or shortcut menu, the columns are not separated by a vertical line.
357
        ''' </summary>
358
        MENUBREAK = &H40L
359
360
        ''' <summary>
361
        ''' Assigns responsibility for drawing the menu item to the window that owns the menu.
362
        ''' The window receives a "WM_MEASUREITEM" message before the menu is displayed for the first time,
363
        ''' and a "WM_DRAWITEM" message whenever the appearance of the menu item must be updated.
364
        ''' If this value is specified, the dwTypeData member contains an application-defined value.
365
        ''' </summary>
366
        OWNERDRAW = &H100L
367
368
    End Enum
369
370
    ''' <summary>
371
    ''' Mask type of the MenuInfo structure.
372
    ''' Indicates the members to be retrieved or set (except for "MenuMask.APPLYTOSUBMENUS").
373
    ''' This member can be one or more of the following values. 
374
    ''' </summary>
375
    Public Enum MenuMask As Integer
376
377
        ''' <summary>
378
        ''' Settings apply to the menu and all of its submenus. 
379
        ''' "SetMenuInfo" API function uses this flag and "GetMenuInfo" API function ignores this flag.
380
        ''' </summary>
381
        APPLYTOSUBMENUS = &H80000000
382
383
        ''' <summary>
384
        ''' Retrieves or sets the hbrBack member.
385
        ''' </summary>
386
        BACKGROUND = &H2
387
388
        ''' <summary>
389
        ''' Retrieves or sets the dwContextHelpID member.
390
        ''' </summary>
391
        HELPID = &H4
392
393
        ''' <summary>
394
        ''' Retrieves or sets the cyMax member.
395
        ''' </summary>
396
        MAXHEIGHT = &H1
397
398
        ''' <summary>
399
        ''' Retrieves or sets the dwMenuData member.
400
        ''' </summary>
401
        MENUDATA = &H8
402
403
        ''' <summary>
404
        ''' Retrieves or sets the dwStyle member.
405
        ''' </summary>
406
        STYLE = &H10
407
408
    End Enum
409
410
    ''' <summary>
411
    ''' The menu style.
412
    ''' This member can be one or more of the following values.
413
    ''' </summary>
414
    Public Enum MenuStyle As Integer
415
416
        ''' <summary>
417
        ''' Menu automatically ends when mouse is outside the menu for approximately 10 seconds..
418
        ''' </summary>
419
        AUTODISMIS = &H10000000
420
421
        ''' <summary>
422
        ''' The same space is reserved for the check mark and the bitmap. 
423
        ''' If the check mark is drawn, the bitmap is not. 
424
        ''' All checkmarks and bitmaps are aligned. 
425
        ''' Used for menus where some items use checkmarks and some use bitmaps.
426
        ''' </summary>
427
        CHECKORBMP = &H4000000
428
429
        ''' <summary>
430
        ''' Menu items are OLE drop targets or drag sources.
431
        ''' Menu owner receives "WM_MENUDRAG" and "WM_MENUGETOBJECT" messages.
432
        ''' </summary>
433
        DRAGDROP = &H20000000
434
435
        ''' <summary>
436
        ''' Menu is modeless; that is,
437
        ''' there is no menu modal message loop while the menu is active.
438
        ''' </summary>
439
        MODELESS = &H40000000
440
441
        ''' <summary>
442
        ''' No space is reserved to the left of an item for a check mark.
443
        ''' The item can still be selected, but the check mark will not appear next to the item.
444
        ''' </summary>
445
        NOCHECK = &H80000000
446
447
        ''' <summary>
448
        ''' Menu owner receives a "WM_MENUCOMMAND" message,
449
        ''' instead of a "WM_COMMAND" message, when the user makes a selection.
450
        ''' "MenuStyle.NOTIFYBYPOS" is a menu header style and has no effect when applied to individual sub menus.
451
        ''' </summary>
452
        NOTIFYBYPOS = &H8000000
453
454
    End Enum
455
456
#End Region ' Enumerations
457
458
#Region " APIs "
459
460
    '''' <summary>
461
    '''' Creates an empty menu.
462
    '''' </summary>
463
    ' <Runtime.InteropServices.
464
    ' DllImport("user32.dll")>
465
    ' Private Shared Function CreateMenu() As IntPtr
466
    ' End Function
467
468
    '''' <summary>
469
    '''' Assigns a new menu to the specified window.
470
    '''' </summary>
471
    '<DllImport("user32.dll")> _
472
    'Public Shared Function SetMenu(
473
    '       ByVal hWnd As IntPtr,
474
    '       ByVal hMenu As IntPtr
475
    ') As Boolean
476
    'End Function
477
478
    ''' <summary>
479
    ''' Gets the handle of the form's system menu.
480
    ''' </summary>
481
    ''' <param name="hWnd">
482
    ''' The handle of the form for which to get the system menu.
483
    ''' </param>
484
    ''' <param name="bRevert">
485
    ''' Indicates whether the menu should be reset to its original state.
486
    ''' </param>
487
    ''' <returns>
488
    ''' The handle of the system menu of the specified form.
489
    ''' </returns>
490
    <Runtime.InteropServices.
491
    DllImport("user32.dll")>
492
    Private Shared Function GetSystemMenu(
493
            ByVal hWnd As IntPtr,
494
            ByVal bRevert As Integer
495
    ) As IntPtr
496
    End Function
497
498
    ''' <summary>
499
    ''' Sets the state of the specified menu item.
500
    ''' </summary>
501
    ''' <returns>
502
    ''' The previous state of the menu item if it exists, -1 otherwise.
503
    ''' </returns>
504
    <Runtime.InteropServices.
505
    DllImport("user32.dll")>
506
    Private Shared Function EnableMenuItem(
507
            ByVal hMenu As IntPtr,
508
            ByVal wIDEnableItem As UInteger,
509
            ByVal wEnable As UInteger
510
    ) As IntPtr
511
    End Function
512
513
    ''' <summary>
514
    ''' Determines the number of items in the specified menu.
515
    ''' </summary>
516
    <Runtime.InteropServices.
517
    DllImport("user32.dll")>
518
    Private Shared Function GetMenuItemCount(
519
            ByVal hMenu As IntPtr
520
    ) As Integer
521
    End Function
522
523
    ''' <summary>
524
    ''' Associates the specified bitmap with a menu item. 
525
    ''' Whether the menu item is selected or clear, 
526
    ''' the system displays the appropriate bitmap next to the menu item.
527
    ''' </summary>
528
    <Runtime.InteropServices.
529
    DllImport("user32.dll")>
530
    Private Shared Function SetMenuItemBitmaps(
531
            ByVal hMenu As IntPtr,
532
            ByVal uPosition As UInteger,
533
            ByVal uFlags As UInteger,
534
            ByVal hBitmapUnchecked As IntPtr,
535
            ByVal hBitmapChecked As IntPtr
536
    ) As Boolean
537
    End Function
538
539
    ''' <summary>
540
    ''' Destroys the specified menu and frees any memory that the menu occupies.
541
    ''' </summary>
542
    <Runtime.InteropServices.
543
    DllImport("user32.dll")>
544
    Private Shared Function DestroyMenu(
545
            ByVal hMenu As IntPtr
546
    ) As Boolean
547
    End Function
548
549
    ''' <summary>
550
    ''' Determines whether a handle is a menu handle. 
551
    ''' </summary>
552
    <Runtime.InteropServices.
553
    DllImport("user32.dll")>
554
    Private Shared Function IsMenu(
555
            ByVal hMenu As IntPtr
556
    ) As Boolean
557
    End Function
558
559
    ''' <summary>
560
    ''' Insert a menu item into an existing menu.
561
    ''' </summary>
562
    <Runtime.InteropServices.
563
    DllImport("user32.dll",
564
    SetLastError:=True,
565
    CharSet:=Runtime.InteropServices.CharSet.Auto)>
566
    Friend Shared Function InsertMenuItem(
567
           ByVal hMenu As IntPtr, ByVal uItem As Integer,
568
           ByVal fByPosition As Boolean,
569
           ByRef lpmii As MenuItemInfo
570
    ) As Boolean
571
    End Function
572
573
    ''' <summary>
574
    ''' Deletes the specified menu item.
575
    ''' </summary>
576
    ''' <returns>
577
    ''' Non-zero if the function succeeds,
578
    ''' zero otherwise.
579
    ''' </returns>
580
    <Runtime.InteropServices.
581
    DllImport("user32.dll")>
582
    Private Shared Function DeleteMenu(
583
            ByVal hMenu As IntPtr,
584
            ByVal uPosition As UInteger,
585
            ByVal uFlags As UInteger
586
    ) As Boolean
587
    End Function
588
589
    ''' <summary>
590
    ''' Ends the calling thread's active menu
591
    ''' </summary>
592
    <Runtime.InteropServices.
593
    DllImport("user32.dll")>
594
    Private Shared Function EndMenu() As Boolean
595
    End Function
596
597
    ''' <summary>
598
    ''' Gets the ID of a menu item.
599
    ''' </summary>
600
    <Runtime.InteropServices.
601
    DllImport("user32.dll")>
602
    Public Shared Function GetMenuItemID(
603
            ByVal hMenu As IntPtr,
604
            ByVal nPos As Integer
605
    ) As Integer
606
    End Function
607
608
    ''' <summary>
609
    ''' Gets the text of a menu item.
610
    ''' </summary>
611
    <Runtime.InteropServices.
612
    DllImport("user32.dll")>
613
    Private Shared Function GetMenuString(
614
            ByVal hMenu As IntPtr,
615
            ByVal uIDItem As UInteger,
616
            <Runtime.InteropServices.Out,
617
            Runtime.InteropServices.MarshalAs(
618
            Runtime.InteropServices.UnmanagedType.LPStr)>
619
            ByVal lpString As System.Text.StringBuilder,
620
            ByVal nMaxCount As Integer,
621
            ByVal uFlag As UInteger
622
    ) As Integer
623
    End Function
624
625
    ''' <summary>
626
    ''' Gets the State of a menu item.
627
    ''' </summary>
628
    <Runtime.InteropServices.
629
    DllImport("user32.dll")>
630
    Private Shared Function GetMenuState(
631
            ByVal hMenu As IntPtr,
632
            ByVal uId As UInteger,
633
            ByVal uFlags As UInteger
634
    ) As UInteger
635
    End Function
636
637
    ''' <summary>
638
    ''' Gets the handle of the form's system menu.
639
    ''' </summary>
640
    ''' <param name="hMenu">
641
    ''' The handle to the menu that contains the menu item.
642
    ''' </param>
643
    ''' <param name="uItem">
644
    ''' The identifier or position of the menu item to get information about.
645
    ''' The meaning of this parameter depends on the value of fByPosition.
646
    ''' </param>
647
    ''' <param name="fByPosition">
648
    ''' The meaning of uItem.
649
    ''' If this parameter is FALSE, uItem is a menu item identifier,
650
    ''' If this parameter is TRUE, it is a menu item position.
651
    ''' </param>
652
    ''' <param name="lpmii">
653
    ''' A pointer to a MenuItemInfo structure that specifies the information to retrieve.
654
    ''' Note that you must set the cbSize member to sizeof(MENUITEMINFO) before calling this function.
655
    ''' </param>
656
    <Runtime.InteropServices.
657
    DllImport("user32.dll",
658
    CharSet:=Runtime.InteropServices.CharSet.Auto)> _
659
    Private Shared Function GetMenuItemInfo(
660
            ByVal hMenu As IntPtr,
661
            ByVal uItem As UInteger,
662
            ByVal fByPosition As Boolean,
663
            ByRef lpmii As MenuItemInfo
664
    ) As Boolean
665
    End Function
666
667
    ''' <summary>
668
    ''' Sets information for a specified menu..
669
    ''' </summary>
670
    ''' <param name="hMenu">
671
    ''' The handle to the menu that contains the menu item.
672
    ''' </param>
673
    ''' <param name="lpcmi">
674
    ''' A pointer to a MENUINFO structure that specifies the information to retrieve.
675
    ''' </param>
676
    <Runtime.InteropServices.
677
    DllImport("user32.dll")>
678
    Private Shared Function SetMenuInfo(
679
            ByVal hmenu As IntPtr,
680
            <Runtime.InteropServices.[In]>
681
            ByRef lpcmi As MenuInfo
682
    ) As Boolean
683
    End Function
684
685
    ''' <summary>
686
    ''' Creates a logical brush that has the specified solid color.
687
    ''' A solid brush is a bitmap that the system uses to paint the interiors of filled shapes.
688
    ''' After an application creates a brush by calling CreateSolidBrush,
689
    ''' it can select that brush into any device context by calling the "SelectObject" API function.
690
    ''' When you no longer need the brush, call the "DeleteObject" API function to delete it.
691
    ''' </summary>
692
    <Runtime.InteropServices.
693
    DllImport("gdi32.dll")>
694
    Private Shared Function CreateSolidBrush(
695
            ByVal crColor As UInteger
696
    ) As IntPtr
697
    End Function
698
699
    ''' <summary>
700
    ''' Selects an object into a specified device context.
701
    ''' The new object replaces the previous object of the same type. 
702
    ''' </summary>
703
    <Runtime.InteropServices.
704
    DllImport("gdi32.dll")>
705
    Public Shared Function SelectObject(
706
           ByVal hdc As IntPtr,
707
           ByVal hObject As IntPtr
708
    ) As IntPtr
709
    End Function
710
711
    ''' <summary>
712
    ''' Deletes a logical pen, brush, font, bitmap, region, or palette,
713
    ''' freeing all system resources associated with the object.
714
    ''' After the object is deleted, the specified handle is no longer valid.
715
    ''' </summary>
716
    <Runtime.InteropServices.
717
    DllImport("gdi32.dll")>
718
    Private Shared Function DeleteObject(
719
            ByVal hObject As IntPtr
720
    ) As <Runtime.InteropServices.MarshalAs(
721
          Runtime.InteropServices.UnmanagedType.Bool)> Boolean
722
    End Function
723
724
    ''' <summary>
725
    ''' Changes information about a menu item.
726
    ''' </summary>
727
    ''' <param name="hMenu ">
728
    ''' A handle to the menu that contains the menu item.
729
    ''' </param>
730
    ''' <param name="uItem">
731
    ''' The identifier or position of the menu item to change.
732
    ''' The meaning of this parameter depends on the value of fByPosition. 
733
    ''' </param>
734
    ''' <param name="fByPosition">
735
    ''' The meaning of "uItem".
736
    ''' If this parameter is set to "FALSE", "uItem" is a menu item identifier.
737
    ''' Otherwise, it is a menu item position.
738
    ''' </param>
739
    ''' <param name="lpmii">
740
    ''' A pointer to a MenuItemInfo structure that contains information about the menu item,
741
    ''' and specifies which menu item attributes to change.
742
    ''' </param>
743
    <Runtime.InteropServices.
744
    DllImport("user32.dll",
745
    SetLastError:=True,
746
    CharSet:=Runtime.InteropServices.CharSet.Auto)>
747
    Private Shared Function SetMenuItemInfo(
748
            ByVal hMenu As IntPtr,
749
            ByVal uItem As UInteger,
750
            ByVal fByPosition As Boolean,
751
            <Runtime.InteropServices.[In]>
752
            ByRef lpmii As MenuItemInfo
753
    ) As Boolean
754
    End Function
755
756
#End Region ' APIs
757
758
#Region " Structures "
759
760
    ''' <summary>
761
    ''' MenuItemInfo Structure,
762
    ''' Contains information about a menu,
763
    ''' Is used to set menu information.
764
    ''' </summary>
765
    <Runtime.InteropServices.
766
    StructLayout(Runtime.InteropServices.LayoutKind.Sequential,
767
    CharSet:=Runtime.InteropServices.CharSet.Auto)>
768
    Public Structure MenuInfo
769
770
        ''' <summary>
771
        ''' The size of the structure, in bytes.
772
        ''' The caller must set this member to sizeof(MenuInfo). 
773
        ''' </summary>
774
        Public cbSize As UInteger
775
776
        ''' <summary>
777
        ''' Indicates the members to be retrieved or set (except for "MenuMask.APPLYTOSUBMENUS").
778
        ''' This member can be one or more of the "MenuMask" Enum values.
779
        ''' </summary>
780
        Public fMask As UInteger
781
782
        ''' <summary>
783
        ''' The menu style.
784
        ''' This member can be one or more of the following values. 
785
        ''' </summary>
786
        Public dwStyle As UInteger
787
788
        ''' <summary>
789
        ''' The maximum height of the menu in pixels. 
790
        ''' When the menu items exceed the space available, scroll bars are automatically used. 
791
        ''' The default (0) is the screen height. 
792
        ''' </summary>
793
        Public cyMax As UInteger
794
795
        ''' <summary>
796
        ''' A handle to the brush to be used for the menu's background.
797
        ''' </summary>
798
        Public hbrBack As IntPtr
799
800
        ''' <summary>
801
        ''' The context help identifier.
802
        ''' This is the same value used in the "GetMenuContextHelpId" and "SetMenuContextHelpId" API functions. 
803
        ''' </summary>
804
        Public dwContextHelpID As UInteger
805
806
        ''' <summary>
807
        ''' An application-defined value.
808
        ''' </summary>
809
        Public dwMenuData As UIntPtr
810
811
    End Structure
812
813
    ''' <summary>
814
    ''' MenuItemInfo Structure,
815
    ''' Contains information about a menu item,
816
    ''' Is used to set a menu item info,
817
    ''' to add a new item or to get an existing item.
818
    ''' </summary>
819
    <Runtime.InteropServices.
820
    StructLayout(Runtime.InteropServices.LayoutKind.Sequential,
821
    CharSet:=Runtime.InteropServices.CharSet.Auto)>
822
    Public Structure MenuItemInfo
823
824
        ''' <summary>
825
        ''' The size of the structure, in bytes.
826
        ''' The caller must set this member to sizeof(MenuItemInfo). 
827
        ''' </summary>
828
        Public cbSize As Integer
829
830
        ''' <summary>
831
        ''' Indicates the members to be retrieved or set.
832
        ''' This member can be one or more of the "ItemMask" Enum values.
833
        ''' </summary>
834
        Public fMask As Integer
835
836
        ''' <summary>
837
        ''' The menu item type. 
838
        ''' This member can be one or more of the "ItemType" Enum values.
839
        ''' The "ItemType.BITMAP", "ItemType.SEPARATOR", and "ItemType.MFT_STRING" values cannot be combined with one another.
840
        ''' Set "fMask" member to "ItemMask.TYPE" to use "fType" member.
841
        ''' "fType" is used only if "fMask" has a value of "ItemMask.TYPE". 
842
        ''' </summary>
843
        Public fType As Integer
844
845
        ''' <summary>
846
        ''' The menu item state.
847
        ''' This member can be one or more of the "ItemState" Enum values.
848
        ''' Set fMask to "ItemMask.STATE" to use "fState". 
849
        ''' </summary>
850
        Public fState As Integer
851
852
        ''' <summary>
853
        ''' An application-defined value that identifies the menu item.
854
        ''' Set "fMask" to "ItemMask.ID" to use "wID".
855
        ''' </summary>
856
        Public wID As Integer
857
858
        ''' <summary>
859
        ''' A handle to the drop-down menu or submenu associated with the menu item.
860
        ''' If the menu item is not an item that opens a drop-down menu or submenu, this member is NULL.
861
        ''' Set "fMask" to "ItemMask.SUBMENU" to use "hSubMenu".
862
        ''' </summary>
863
        Public hSubMenu As IntPtr
864
865
        ''' <summary>
866
        ''' A handle to the bitmap to display next to the item if it is selected.
867
        ''' If this member is NULL, a default bitmap is used.
868
        ''' If the "ItemType.RADIOCHECK" type value is specified, the default bitmap is a bullet,
869
        ''' Otherwise it is a check mark.
870
        ''' Set "fMask" to "ItemMask.CHECKMARKS" to use "hbmpChecked".
871
        ''' </summary>
872
        Public hbmpChecked As IntPtr
873
874
        ''' <summary>
875
        ''' A handle to the bitmap to display next to the item if it is not selected.
876
        ''' If this member is NULL, no bitmap is used.
877
        ''' Set "fMask" to "ItemMask.CHECKMARKS" to use "hbmpUnchecked". 
878
        ''' </summary>
879
        Public hbmpUnchecked As IntPtr
880
881
        ''' <summary>
882
        ''' An application-defined value associated with the menu item.
883
        ''' Set "fMask" to "ItemMask.DATA" to use "dwItemData".
884
        ''' </summary>
885
        Public dwItemData As IntPtr
886
887
        ''' <summary>
888
        ''' The contents of the menu item.
889
        ''' The meaning of this member depends on the value of fType,
890
        ''' and is used only if the "ItemMask.TYPE" flag is set in the "fMask" member.
891
        ''' </summary>
892
        Public dwTypeData As String
893
894
        ''' <summary>
895
        ''' The length of the menu item text, in characters,
896
        ''' when information is received about a menu item of the "ItemType.TEXT" type.
897
        ''' However, "cch" is used only if the "ItemMask.TYPE" flag is set in the "fMask" member and is zero otherwise.
898
        ''' Also, "cch" is ignored when the content of a menu item is set by calling "SetMenuItemInfo" API function.
899
        ''' The "cch" member is used when the "ItemMask.TEXT" flag is set in the "fMask" member. 
900
        ''' </summary>
901
        Public cch As Integer
902
903
        ''' <summary>
904
        ''' A handle to the bitmap to be displayed.
905
        ''' It is used when the "ItemMask.BITMAP" flag is set in the "fMask" member. 
906
        ''' </summary>
907
        Public hbmpItem As IntPtr
908
909
    End Structure
910
911
#End Region ' Structures
912
913
#Region " New Constructor "
914
915
    ''' <summary>
916
    ''' Creates a new SystemMenuManager object for the specified form
917
    ''' </summary>
918
    ''' <param name="form">
919
    ''' The form for which to manage the system menu.
920
    ''' </param>
921
    Public Sub New(ByVal form As Form)
922
923
        ' Set the Formulary.
924
        Me.form = form
925
926
        ' Set the handle of the form's system menu.
927
        MenuHandle = GetSystemMenu(form.Handle, False)
928
929
        ' Assign the form handle.
930
        SetFormHandle()
931
932
    End Sub
933
934
#End Region ' New Constructor
935
936
#Region " Public Methods "
937
938
    ''' <summary>
939
    ''' Set an state for a menu item.
940
    ''' </summary>
941
    ''' <param name="item">
942
    ''' The system menu item.
943
    ''' </param>
944
    ''' <param name="state">
945
    ''' The new state for the item.
946
    ''' </param>
947
    Public Function SetItemState(ByVal item As Item,
948
                                 ByVal state As ItemState) As Boolean
949
950
        ItemStates(item) = state
951
952
        If item = item.Close Then
953
            CloseItem_State = state
954
        End If
955
956
        If state = ItemState.Removed Then
957
            Return DeleteMenu(MenuHandle, item, ItemPosition.ByCommand Or 0)
958
        Else
959
            Return EnableMenuItem(MenuHandle, item, ItemPosition.ByCommand Or state)
960
        End If
961
962
    End Function
963
964
    ''' <summary>
965
    ''' Set an state for a menu item at given position.
966
    ''' </summary>
967
    ''' <param name="position">
968
    ''' The menu item position.
969
    ''' </param>
970
    ''' <param name="state">
971
    ''' The new state for the item.
972
    ''' </param>
973
    Public Function SetItemState(ByVal position As Integer,
974
                                 ByVal state As ItemState) As Boolean
975
976
        Try
977
            PositionItemStates.Add(position, state)
978
        Catch ' ex As ArgumentException
979
            PositionItemStates(position) = state
980
        End Try
981
982
        If state = ItemState.Removed Then
983
            Return DeleteMenu(MenuHandle, position, ItemPosition.ByPosition Or 0)
984
        Else
985
            Return EnableMenuItem(MenuHandle, position, ItemPosition.ByPosition Or state)
986
        End If
987
988
    End Function
989
990
    ''' <summary>
991
    ''' Set a custom Bitmap image for a MenuItem.
992
    ''' </summary>
993
    ''' <param name="item">
994
    ''' The menu item.
995
    ''' </param>
996
    Public Function SetItemBitmap(ByVal item As Item,
997
                                  ByVal bmp As Bitmap) As Boolean
998
999
        ItemBitmaps(item) = bmp
1000
1001
        Return SetMenuItemBitmaps(MenuHandle,
1002
                                  item,
1003
                                  ItemPosition.ByCommand,
1004
                                  bmp.GetHbitmap,
1005
                                  bmp.GetHbitmap)
1006
1007
    End Function
1008
1009
    ''' <summary>
1010
    ''' Set a custom Bitmap image for a MenuItem at given position.
1011
    ''' </summary>
1012
    ''' <param name="position">
1013
    ''' The menu item position.
1014
    ''' </param>
1015
    Public Function SetItemBitmap(ByVal position As Integer,
1016
                                  ByVal bmp As Bitmap) As Boolean
1017
1018
        Try
1019
            PositionItemBitmaps.Add(position, bmp)
1020
        Catch ' ex As System.ArgumentException
1021
            PositionItemBitmaps(position) = bmp
1022
        End Try
1023
1024
        Return SetMenuItemBitmaps(MenuHandle,
1025
                                  position,
1026
                                  ItemPosition.ByPosition,
1027
                                  bmp.GetHbitmap,
1028
                                  bmp.GetHbitmap)
1029
1030
    End Function
1031
1032
    ''' <summary>
1033
    ''' Returns the custom Bitmap image used by a MenuItem.
1034
    ''' </summary>
1035
    ''' <param name="item">
1036
    ''' The menu item.
1037
    ''' </param>
1038
    Public Function GetItemBitmap(ByVal item As Item) As Bitmap
1039
        Return ItemBitmaps(item)
1040
    End Function
1041
1042
    ''' <summary>
1043
    ''' Returns the custom Bitmap image used by a MenuItem at given position.
1044
    ''' </summary>
1045
    ''' <param name="position">
1046
    ''' The menu item position.
1047
    ''' </param>
1048
    Public Function GetItemBitmap(ByVal position As Integer) As Bitmap
1049
1050
        Return If(Not PositionItemBitmaps.FirstOrDefault(Function(item) item.Key = position).Key = Nothing,
1051
                  PositionItemBitmaps(position),
1052
                  Nothing)
1053
1054
    End Function
1055
1056
    ''' <summary>
1057
    ''' Removes the custom Bitmap image used by a MenuItem.
1058
    ''' </summary>
1059
    ''' <param name="item">
1060
    ''' The menu item.
1061
    ''' </param>
1062
    Public Function RemoveItemBitmap(ByVal item As Item) As Boolean
1063
1064
        ItemBitmaps(item) = Nothing
1065
1066
        Return SetMenuItemBitmaps(MenuHandle,
1067
                                  item,
1068
                                  ItemPosition.ByCommand,
1069
                                  Nothing,
1070
                                  Nothing)
1071
1072
    End Function
1073
1074
    ''' <summary>
1075
    ''' Removes the custom Bitmap image used by a MenuItem at given position.
1076
    ''' </summary>
1077
    ''' <param name="position">
1078
    ''' The menu item position.
1079
    ''' </param>
1080
    Public Function RemoveItemBitmap(ByVal position As Integer) As Boolean
1081
1082
        If Not PositionItemBitmaps.FirstOrDefault(Function(item) item.Key = position).Key = Nothing Then
1083
            PositionItemBitmaps(position) = Nothing
1084
        End If
1085
1086
        Return SetMenuItemBitmaps(MenuHandle,
1087
                                  position,
1088
                                  ItemPosition.ByPosition,
1089
                                  Nothing,
1090
                                  Nothing)
1091
1092
    End Function
1093
1094
    ''' <summary>
1095
    ''' Gets the amount of menu items.
1096
    ''' </summary>
1097
    Public Function GetItemCount() As Integer
1098
        Return GetMenuItemCount(MenuHandle) ' - 1
1099
    End Function
1100
1101
    ''' <summary>
1102
    ''' Enables all the menu items.
1103
    ''' </summary>
1104
    Public Sub EnableAllItems()
1105
1106
        For i As Integer = 0 To GetItemCount() - 1
1107
            SetItemState(i, ItemState.Enabled)
1108
        Next i
1109
1110
    End Sub
1111
1112
    ''' <summary>
1113
    ''' Disables all the menu items.
1114
    ''' </summary>
1115
    Public Sub DisableAllItems()
1116
1117
        For i As Integer = 0 To GetItemCount() - 1
1118
            SetItemState(i, ItemState.Disabled)
1119
        Next i
1120
1121
    End Sub
1122
1123
    ''' <summary>
1124
    ''' Removes all the menu items.
1125
    ''' </summary>
1126
    Public Sub RemoveAllItems()
1127
1128
        Do Until Not CBool(GetItemCount())
1129
            DeleteMenu(MenuHandle, 0, ItemPosition.ByPosition Or 0)
1130
        Loop
1131
1132
    End Sub
1133
1134
    ''' <summary>
1135
    ''' Restores the menu to defaults.
1136
    ''' </summary>
1137
    Public Sub Restore_Menu()
1138
        CloseItem_State = ItemState.Enabled
1139
        Me.MenuHandle = GetSystemMenu(Me.form.Handle, True)
1140
    End Sub
1141
1142
    ''' <summary>
1143
    ''' Add a separator at default position.
1144
    ''' </summary>
1145
    ''' <param name="position">
1146
    ''' The position where the item will be added.
1147
    ''' </param>
1148
    ''' <returns>
1149
    ''' True if the operation was successful, otherwise False.
1150
    ''' </returns>
1151
    Public Function AddSeparator(ByVal position As DefaultPositions) As Boolean
1152
1153
        mii = New MenuItemInfo
1154
1155
        With mii
1156
            .cbSize = Runtime.InteropServices.Marshal.SizeOf(GetType(MenuItemInfo))
1157
            .fMask = ItemMask.ID Or ItemMask.TYPE
1158
            .fType = ItemType.SEPARATOR
1159
            .wID = -1
1160
        End With
1161
1162
        Return InsertMenuItem(MenuHandle, GetPosition(position), True, mii)
1163
1164
    End Function
1165
1166
    ''' <summary>
1167
    ''' Add a separator at given position.
1168
    ''' </summary>
1169
    ''' <param name="position">
1170
    ''' The position where the item will be added.
1171
    ''' </param>
1172
    ''' <returns>
1173
    ''' True if the operation was successful, otherwise False.
1174
    ''' </returns>
1175
    Public Function AddSeparator(ByVal position As Integer) As Boolean
1176
1177
        mii = New MenuItemInfo
1178
1179
        With mii
1180
            .cbSize = Runtime.InteropServices.Marshal.SizeOf(GetType(MenuItemInfo))
1181
            .fMask = ItemMask.ID Or ItemMask.TYPE
1182
            .fType = ItemType.SEPARATOR
1183
            .wID = -1
1184
        End With
1185
1186
        Return InsertMenuItem(MenuHandle, position, True, mii)
1187
1188
    End Function
1189
1190
    ''' <summary>
1191
    ''' Add an Item at default position.
1192
    ''' </summary>
1193
    ''' <param name="Label">
1194
    ''' The text of the item.
1195
    ''' </param>
1196
    ''' <param name="ID">
1197
    ''' A Identifier to interact with this item when is clicked.
1198
    ''' </param>
1199
    ''' <param name="position">
1200
    ''' The position where the item will be added.
1201
    ''' </param>
1202
    ''' <param name="ImageChecked">
1203
    ''' Image displayed when Item is selected.
1204
    ''' </param>
1205
    ''' <param name="ImageUnchecked">
1206
    ''' Image displayed when Item is not selected.
1207
    ''' </param>
1208
    ''' <returns>
1209
    ''' True if the operation was successful, otherwise False.
1210
    ''' </returns>
1211
    Public Function AddItem(ByVal Label As String,
1212
                       ByVal ID As Integer,
1213
                       ByVal Position As DefaultPositions,
1214
                       Optional ByVal ImageChecked As Bitmap = Nothing,
1215
                       Optional ByVal ImageUnchecked As Bitmap = Nothing) As Boolean
1216
1217
        mii = New MenuItemInfo
1218
1219
        With mii
1220
            .cbSize = Runtime.InteropServices.Marshal.SizeOf(GetType(MenuItemInfo))
1221
            .fMask = ItemMask.STATE Or ItemMask.ID Or ItemMask.TYPE Or ItemMask.CHECKMARKS
1222
            .fType = ItemType.TEXT
1223
            .fState = ItemState.Enabled
1224
            .wID = ID
1225
            .dwTypeData = Label
1226
            .hbmpChecked = If(ImageChecked IsNot Nothing, ImageChecked.GetHbitmap, Nothing)
1227
            .hbmpUnchecked = If(ImageUnchecked IsNot Nothing, ImageUnchecked.GetHbitmap, Nothing)
1228
            .cch = .dwTypeData.Length
1229
        End With
1230
1231
        Return InsertMenuItem(MenuHandle, GetPosition(Position), True, mii)
1232
1233
    End Function
1234
1235
    ''' <summary>
1236
    ''' Adds an Item at the given position.
1237
    ''' </summary>
1238
    ''' <param name="Label">
1239
    ''' The text of the item.
1240
    ''' </param>
1241
    ''' <param name="ID">
1242
    ''' A Identifier to interact with this item when is clicked.
1243
    ''' </param>
1244
    ''' <param name="position">
1245
    ''' The position where the item will be added.
1246
    ''' </param>
1247
    ''' <param name="ImageChecked">
1248
    ''' Image displayed when Item is selected.
1249
    ''' </param>
1250
    ''' <param name="ImageUnchecked">
1251
    ''' Image displayed when Item is not selected.
1252
    ''' </param>
1253
    ''' <returns>
1254
    ''' True if the operation was successful, otherwise False.
1255
    ''' </returns>
1256
    Public Function AddItem(ByVal Label As String,
1257
                       ByVal ID As Integer,
1258
                       ByVal Position As Integer,
1259
                       Optional ByVal ImageChecked As Bitmap = Nothing,
1260
                       Optional ByVal ImageUnchecked As Bitmap = Nothing) As Boolean
1261
1262
        mii = New MenuItemInfo
1263
1264
        With mii
1265
            .cbSize = Runtime.InteropServices.Marshal.SizeOf(GetType(MenuItemInfo))
1266
            .fMask = ItemMask.STATE Or ItemMask.ID Or ItemMask.TYPE Or ItemMask.CHECKMARKS
1267
            .fType = ItemType.TEXT
1268
            .fState = ItemState.Enabled
1269
            .wID = ID
1270
            .dwTypeData = Label
1271
            .hbmpChecked = If(ImageChecked IsNot Nothing, ImageChecked.GetHbitmap, Nothing)
1272
            .hbmpUnchecked = If(ImageUnchecked IsNot Nothing, ImageUnchecked.GetHbitmap, Nothing)
1273
            .cch = .dwTypeData.Length
1274
        End With
1275
1276
        Return InsertMenuItem(MenuHandle, Position, True, mii)
1277
1278
    End Function
1279
1280
    ''' <summary>
1281
    ''' Determines whether a handle is a menu handle. 
1282
    ''' </summary>
1283
    ''' <returns>
1284
    ''' True if is a menu handle, otherwise False.
1285
    ''' </returns>
1286
    Public Function IsMenuHandle(ByVal Handle As IntPtr) As Boolean
1287
        Return IsMenu(Handle)
1288
    End Function
1289
1290
    ''' <summary>
1291
    ''' Gets the ID of a menu item.
1292
    ''' </summary>
1293
    Public Function GetItemID(ByVal Item As Item) As Integer
1294
        Return Item
1295
    End Function
1296
1297
    ''' <summary>
1298
    ''' Gets the ID of a menu item at given position.
1299
    ''' </summary>
1300
    Public Function GetItemID(ByVal position As Integer) As Integer
1301
        Return GetMenuItemID(MenuHandle, position)
1302
    End Function
1303
1304
    ''' <summary>
1305
    ''' Gets the text of a menu item.
1306
    ''' </summary>
1307
    Public Function GetItemText(ByVal Item As Item) As String
1308
        ItemText.Clear()
1309
        GetMenuString(MenuHandle, Item, ItemText, ItemText.Capacity, ItemPosition.ByCommand)
1310
        Return ItemText.ToString
1311
    End Function
1312
1313
    ''' <summary>
1314
    ''' Gets the text of a menu item at given position.
1315
    ''' </summary>
1316
    Public Function GetItemText(ByVal position As Integer) As String
1317
        ItemText.Clear()
1318
        GetMenuString(MenuHandle, position, ItemText, ItemText.Capacity, ItemPosition.ByPosition)
1319
        Return ItemText.ToString
1320
    End Function
1321
1322
    ''' <summary>
1323
    ''' Gets the state of a menu item.
1324
    ''' </summary>
1325
    Public Function GetItemState(ByVal Item As Item) As ItemState
1326
        Return [Enum].Parse(GetType(ItemState), GetMenuState(MenuHandle, Item, ItemPosition.ByCommand))
1327
    End Function
1328
1329
    ''' <summary>
1330
    ''' Gets the state of a menu item at given position.
1331
    ''' </summary>
1332
    Public Function GetItemState(ByVal position As Integer) As ItemState
1333
        Return [Enum].Parse(GetType(ItemState), GetMenuState(MenuHandle, position, ItemPosition.ByPosition))
1334
    End Function
1335
1336
    ''' <summary>
1337
    ''' Set the background color of a menu.
1338
    ''' </summary>
1339
    ''' <returns>
1340
    ''' True if the operation was successful, otherwise False.
1341
    ''' </returns>
1342
    Public Function SetMenuBackColor(ByVal color As Color) As Boolean
1343
1344
        MenuBrush = CreateSolidBrush(CUInt(ColorTranslator.ToWin32(color)))
1345
1346
        mi = New MenuInfo
1347
1348
        With mi
1349
            .cbSize = Runtime.InteropServices.Marshal.SizeOf(GetType(MenuInfo))
1350
            .fMask = MenuMask.BACKGROUND
1351
            .hbrBack = MenuBrush
1352
        End With
1353
1354
        Return SetMenuInfo(MenuHandle, mi)
1355
1356
    End Function
1357
1358
    ''' <summary>
1359
    ''' Set the menu style.
1360
    ''' </summary>
1361
    ''' <returns>
1362
    ''' True if the operation was successful, otherwise False.
1363
    ''' </returns>
1364
    Public Function SetMenuStyle(ByVal Style As MenuStyle) As Boolean
1365
1366
        mi = New MenuInfo
1367
1368
        With mi
1369
            .cbSize = Runtime.InteropServices.Marshal.SizeOf(GetType(MenuInfo))
1370
            .fMask = MenuMask.STYLE
1371
            .dwStyle = Style
1372
        End With
1373
1374
        Return SetMenuInfo(MenuHandle, mi)
1375
1376
    End Function
1377
1378
    ''' <summary>
1379
    ''' Set the text of a menu item.
1380
    ''' </summary>
1381
    ''' <param name="item">
1382
    ''' The menu item.
1383
    ''' </param>
1384
    ''' <param name="text">
1385
    ''' The new text for the item.
1386
    ''' </param>
1387
    Public Function SetItemText(ByVal item As Item,
1388
                                ByVal text As String) As Boolean
1389
1390
        mii = New MenuItemInfo
1391
1392
        With mii
1393
            .cbSize = Runtime.InteropServices.Marshal.SizeOf(GetType(MenuItemInfo))
1394
            .fMask = ItemMask.TEXT
1395
            .dwTypeData = text
1396
        End With
1397
1398
        Return SetMenuItemInfo(MenuHandle, item, False, mii)
1399
1400
    End Function
1401
1402
    ''' <summary>
1403
    ''' Set the text of a menu item at given position.
1404
    ''' </summary>
1405
    ''' <param name="position">
1406
    ''' The menu item position.
1407
    ''' </param>
1408
    ''' <param name="text">
1409
    ''' The new text for the item.
1410
    ''' </param>
1411
    Public Function SetItemText(ByVal position As Integer,
1412
                                ByVal text As String) As Boolean
1413
1414
        mii = New MenuItemInfo
1415
1416
        With mii
1417
            .cbSize = Runtime.InteropServices.Marshal.SizeOf(GetType(MenuItemInfo))
1418
            .fMask = ItemMask.TEXT
1419
            .dwTypeData = text
1420
        End With
1421
1422
        Return SetMenuItemInfo(MenuHandle, position, True, mii)
1423
1424
    End Function
1425
1426
#End Region ' Public Methods
1427
1428
#Region " Private Methods "
1429
1430
    ''' <summary>
1431
    ''' Converts a MenuItemPosition value to a menu item position.
1432
    ''' </summary>
1433
    ''' <param name="position">
1434
    ''' The MenuItemPosition value.
1435
    ''' </param>
1436
    Private Function GetPosition(ByVal position As ItemPosition) As Integer
1437
1438
        Select Case position
1439
1440
            Case DefaultPositions.First
1441
                Return 0
1442
1443
            Case DefaultPositions.Second
1444
                Return 1
1445
1446
            Case DefaultPositions.Third
1447
                Return 2
1448
1449
            Case DefaultPositions.Middle
1450
                Return (GetItemCount() \ 2)
1451
1452
            Case DefaultPositions.Penultimate
1453
                Return (GetItemCount() - 1)
1454
1455
            Case DefaultPositions.Last
1456
                Return (GetItemCount() + 1)
1457
1458
            Case Else
1459
                Return Nothing
1460
1461
        End Select
1462
1463
    End Function
1464
1465
    ''' <summary>
1466
    ''' Refreshes the state of the Close menu item.
1467
    ''' </summary>
1468
    ''' <remarks>
1469
    ''' Action is only taken if the state is Disabled or Grayed.
1470
    ''' </remarks>
1471
    Private Sub Refresh_CloseItem()
1472
1473
        If CloseItem_State = ItemState.Disabled _
1474
        OrElse CloseItem_State = ItemState.Grayed Then
1475
1476
            ' Set the Close menu item state.
1477
            EnableMenuItem(MenuHandle, Item.Close, ItemPosition.ByCommand Or CloseItem_State)
1478
1479
        End If
1480
1481
    End Sub
1482
1483
#End Region ' Private Methods
1484
1485
#Region " Form Event Handlers "
1486
1487
    ''' <summary>
1488
    ''' The Close menu item must have it's state refresehed,
1489
    ''' if it is present and not enabled.
1490
    ''' </summary>
1491
    Private Sub Refresh() _
1492
    Handles form.Load, form.Resize
1493
1494
        Refresh_CloseItem()
1495
1496
    End Sub
1497
1498
    ''' <summary>
1499
    ''' SetHandle
1500
    ''' Assign the handle of the target form to this NativeWindow,
1501
    ''' necessary to override WndProc.
1502
    ''' </summary>
1503
    Private Sub SetFormHandle() _
1504
    Handles form.HandleCreated, form.Load, form.Shown
1505
1506
        Try
1507
            If Not Me.Handle.Equals(Me.form.Handle) Then
1508
                Me.AssignHandle(Me.form.Handle)
1509
            End If
1510
        Catch ' ex As InvalidOperationException
1511
        End Try
1512
1513
    End Sub
1514
1515
    ''' <summary>
1516
    ''' Releases the Handle.
1517
    ''' </summary>
1518
    Private Sub OnHandleDestroyed() _
1519
    Handles form.HandleDestroyed
1520
1521
        Me.ReleaseHandle()
1522
1523
    End Sub
1524
1525
#End Region ' Form Event Handlers
1526
1527
#Region " Windows Messages "
1528
1529
    ''' <summary>
1530
    ''' Intercepts Menu messages.
1531
    ''' </summary>
1532
    Protected Overrides Sub WndProc(ByRef m As Message)
1533
1534
        Select Case m.Msg
1535
1536
            Case &H116 ' WM_INITMENU message
1537
                ' Message is sent when a menu is about to become active. 
1538
                ' It occurs when the user clicks an item on the menu bar or presses a menu key. 
1539
                ' This allows the application to modify the menu before it is displayed. 
1540
                MenuHandle = GetSystemMenu(form.Handle, False)
1541
1542
            Case &H117 ' WM_INITMENUPOPUP
1543
                ' Message is sent when a drop-down menu or submenu is about to become active.
1544
                ' This allows an application to modify the menu before it is displayed, 
1545
                ' without changing the entire menu. 
1546
1547
                ' Refresh the states of the Items by command.
1548
                If ItemStates.FirstOrDefault(Function(item) item.Key).Value <> Nothing Then
1549
                    ItemStates.ToList().
1550
                               ForEach(Function(item) SetItemState(item.Key, item.Value))
1551
                End If
1552
1553
                ' Refresh the states of the Items by position.
1554
                If PositionItemStates.FirstOrDefault(Function(item) item.Key).Value <> Nothing Then
1555
                    PositionItemStates.ToList().
1556
                    ForEach(Function(item) SetItemState(CInt(item.Key), item.Value))
1557
                End If
1558
1559
            Case &H112 ' WM_SYSCOMMAND
1560
                ' Message is sent when the user chooses a command from the system menu,
1561
                ' or when the user chooses the maximize button, minimize button, restore button, or close button.
1562
1563
                ' Begin step to retrieve the item Text
1564
                mii = New MenuItemInfo With {
1565
                    .cbSize = Runtime.InteropServices.Marshal.SizeOf(GetType(MenuItemInfo)),
1566
                    .fMask = ItemMask.TEXT
1567
                }
1568
1569
                ' Retrieve the text length member.
1570
                GetMenuItemInfo(MenuHandle, m.WParam, False, mii)
1571
1572
                ' Account for terminating NUL character and allocate String
1573
                mii.cch += 1
1574
                mii.dwTypeData = Space(mii.cch)
1575
1576
                ' Retrieve the rest of the information.
1577
                mii.fMask = ItemMask.ID Or ItemMask.TEXT Or ItemMask.STATE Or ItemMask.FTYPE
1578
                GetMenuItemInfo(MenuHandle, m.WParam, False, mii)
1579
1580
                ' Set the Event arguments
1581
                With ItemClickedArgs
1582
                    .ID = mii.wID
1583
                    .Text = mii.dwTypeData
1584
                    .State = [Enum].Parse(GetType(ItemState), mii.fState)
1585
                    .Type = [Enum].Parse(GetType(ItemType), mii.fType)
1586
                End With
1587
1588
                RaiseEvent ItemClicked(MenuHandle, ItemClickedArgs)
1589
1590
        End Select
1591
1592
        ' Return control to base message handler.
1593
        MyBase.WndProc(m)
1594
1595
    End Sub
1596
1597
#End Region ' Windows Messages
1598
1599
#Region " IDisposable "
1600
1601
    ''' <summary>
1602
    ''' Disposes the objects generated by this instance.
1603
    ''' </summary>
1604
    Public Sub Dispose() Implements IDisposable.Dispose
1605
        Dispose(True)
1606
        GC.SuppressFinalize(Me)
1607
    End Sub
1608
1609
    Protected Overridable Sub Dispose(IsDisposing As Boolean)
1610
1611
        Static IsBusy As Boolean = False ' To detect redundant calls.
1612
1613
        If Not IsBusy AndAlso IsDisposing Then
1614
1615
            DeleteObject(MenuBrush)
1616
1617
            Restore_Menu()
1618
            EndMenu()
1619
1620
            Me.form = Nothing
1621
            MenuHandle = IntPtr.Zero
1622
1623
            Me.ReleaseHandle()
1624
            Me.DestroyHandle()
1625
1626
        End If
1627
1628
        IsBusy = True
1629
1630
    End Sub
1631
1632
#End Region ' IDisposable
1633
1634
#Region " ToDO?: "
1635
1636
    ' función "AppendMenu"?
1637
    ' usar HotKeys? (&)
1638
    ' Alguna cosa interesante con los submenus?
1639
1640
#End Region ' ToDo
1641
1642
End Class
1643
1644
#End Region