Advertisement
PiToLoKo

VB.NET SystemMenu Manager by Elektro H@cker

Nov 12th, 2013
312
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VB.NET 51.12 KB | None | 0 0
  1. ' SystemMenu Manager
  2. '
  3. ' // By Elektor 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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement