Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ' SystemMenu Manager
- '
- ' // By Elektor H@cker
- #Region " SystemMenu Manager "
- Public Class SystemMenuManager
- Inherits NativeWindow
- Implements IDisposable
- ' ----------------------------
- ' MSDN documentation Reference
- ' ----------------------------
- ' Menu Functions: http://msdn.microsoft.com/en-us/library/windows/desktop/ff468865%28v=vs.85%29.aspx
- ' MenuItemInfo : http://msdn.microsoft.com/en-us/library/windows/desktop/ms647578%28v=vs.85%29.aspx
- ' MenuInfo : http://msdn.microsoft.com/en-us/library/windows/desktop/ms647575%28v=vs.85%29.aspx
- #Region " Variables "
- ''' <summary>
- ''' The form for which the system menu will be managed.
- ''' </summary>
- Private WithEvents form As Form = Nothing
- ''' <summary>
- ''' The handle of the form's system menu.
- ''' </summary>
- Private MenuHandle As IntPtr = IntPtr.Zero
- ''' <summary>
- ''' Stores a MenuInfo structure.
- ''' </summary>
- Private mi As New MenuInfo
- ''' <summary>
- ''' Stores a menuiteminfo structure.
- ''' </summary>
- Private mii As New MenuItemInfo
- ''' <summary>
- ''' Stores a menu item Text.
- ''' </summary>
- Private ItemText As New System.Text.StringBuilder With {.Capacity = 260}
- ''' <summary>
- ''' Brush used to paint the menu background.
- ''' </summary>
- Private MenuBrush As IntPtr = IntPtr.Zero
- ''' <summary>
- ''' Stores the ItemClickedEventArgs members.
- ''' </summary>
- Private ItemClickedArgs As New ItemClickedEventArgs
- ''' <summary>
- ''' The State of the Close item.
- ''' </summary>
- Private CloseItem_State As ItemState = ItemState.Enabled
- ''' <summary>
- ''' Stores the current state of each MenuItem.
- ''' </summary>
- Private ItemStates As New Dictionary(Of Item, ItemState) From
- {
- {Item.Close, Nothing},
- {Item.Move, Nothing},
- {Item.Maximize, Nothing},
- {Item.Minimize, Nothing},
- {Item.Restore, Nothing},
- {Item.Size, Nothing}
- }
- ''' <summary>
- ''' Stores the Bitmap image of each MenuItem.
- ''' </summary>
- Private ItemBitmaps As New Dictionary(Of Item, Bitmap) From
- {
- {Item.Close, Nothing},
- {Item.Move, Nothing},
- {Item.Maximize, Nothing},
- {Item.Minimize, Nothing},
- {Item.Restore, Nothing},
- {Item.Size, Nothing}
- }
- ''' <summary>
- ''' Stores the current state of each MenuItem specified by position.
- ''' </summary>
- Private PositionItemStates As New Dictionary(Of Integer, ItemState)
- ''' <summary>
- ''' Stores the Bitmap image of each MenuItem specified by position.
- ''' </summary>
- Private PositionItemBitmaps As New Dictionary(Of Integer, Bitmap)
- #End Region ' Variables
- #Region " Events "
- ''' <summary>
- ''' Event raised when a menu item is clicked.
- ''' </summary>
- Public Event ItemClicked As EventHandler(Of ItemClickedEventArgs)
- Public Class ItemClickedEventArgs : Inherits EventArgs
- ''' <summary>
- ''' Item Identifier.
- ''' </summary>
- Public Property ID As Integer
- ''' <summary>
- ''' Item Text.
- ''' </summary>
- Public Property Text As String
- ''' <summary>
- ''' Item State.
- ''' </summary>
- Public Property State As ItemState
- ''' <summary>
- ''' Item Type.
- ''' </summary>
- Public Property Type As ItemType
- End Class
- #End Region ' Events
- #Region " Enumerations "
- ''' <summary>
- ''' The menu Position ttype.
- ''' </summary>
- Public Enum ItemPosition As Integer
- ''' <summary>
- ''' The menu item is specified by command.
- ''' </summary>
- ByCommand = &H0
- ''' <summary>
- ''' The menu item is specified by position.
- ''' </summary>
- ByPosition = &H410
- End Enum
- ''' <summary>
- ''' The Menu Items.
- ''' </summary>
- Public Enum Item As Integer
- ''' <summary>
- ''' Closes the window.
- ''' </summary>
- Close = &HF060
- ''' <summary>
- ''' Moves the window.
- ''' </summary>
- Move = &HF010
- ''' <summary>
- ''' Maximizes the window.
- ''' </summary>
- Maximize = &HF030
- ''' <summary>
- ''' Minimizes the window.
- ''' </summary>
- Minimize = &HF020
- ''' <summary>
- ''' Restores the window to its normal position and size.
- ''' </summary>
- Restore = &HF120
- ''' <summary>
- ''' Sizes the window.
- ''' </summary>
- Size = &HF000
- End Enum
- ''' <summary>
- ''' The states that a menu item can have.
- ''' </summary>
- Public Enum ItemState As Integer
- ''' <summary>
- ''' The menu item is present and can be selected.
- ''' </summary>
- ''' <remarks>
- ''' This is the default state.
- ''' </remarks>
- Enabled = &H0
- ''' <summary>
- ''' The menu item is present but greyed-out and cannot be selected.
- ''' </summary>
- Grayed = &H1
- ''' <summary>
- ''' The menu item is present but can not be selected.
- ''' </summary>
- Disabled = &H2
- ''' <summary>
- ''' The menu item is not present.
- ''' </summary>
- Removed = -1
- End Enum
- ''' <summary>
- ''' Predefined menu item positions.
- ''' </summary>
- Public Enum DefaultPositions As Short
- ''' <summary>
- ''' Top position.
- ''' </summary>
- First = 0
- ''' <summary>
- ''' Second position.
- ''' </summary>
- Second = 1
- ''' <summary>
- ''' Third position.
- ''' </summary>
- Third = 2
- ''' <summary>
- ''' Middle position.
- ''' </summary>
- Middle = 3
- ''' <summary>
- ''' Penultimate position.
- ''' </summary>
- Penultimate = 4
- ''' <summary>
- ''' Bottom position.
- ''' </summary>
- Last = 5
- End Enum
- ''' <summary>
- ''' Mask type of the MenuItemInfo structure.
- ''' </summary>
- Public Enum ItemMask As Integer
- ''' <summary>
- ''' Retrieves or sets the "hbmpItem" member.
- ''' </summary>
- BITMAP = &H80
- ''' <summary>
- ''' Retrieves or sets the "hbmpChecked" and "hbmpUnchecked" members.
- ''' </summary>
- CHECKMARKS = &H8
- ''' <summary>
- ''' Retrieves or sets the "dwItemData" member.
- ''' </summary>
- DATA = &H20
- ''' <summary>
- ''' Retrieves or sets the "fType" member.
- ''' </summary>
- FTYPE = &H100
- ''' <summary>
- ''' Retrieves or sets the "wID" member.
- ''' </summary>
- ID = &H2
- ''' <summary>
- ''' Retrieves or sets the "fState" member.
- ''' </summary>
- STATE = &H1
- ''' <summary>
- ''' Retrieves or sets the "dwTypeData" member.
- ''' </summary>
- TEXT = &H40
- ''' <summary>
- ''' Retrieves or sets the "hSubMenu" member.
- ''' </summary>
- SUBMENU = &H4
- ''' <summary>
- ''' Retrieves or sets the "fType" and "dwTypeData" members.
- ''' "ItemMask.TYPE" is replaced by "ItemMask.BITMAP", "ItemMask.FTYPE", and "ItemMask.TEXT".
- ''' </summary>
- TYPE = &H10
- End Enum
- ''' <summary>
- ''' Item Type of the MenuItemInfo structure.
- ''' </summary>
- Public Enum ItemType As Long
- ''' <summary>
- ''' Displays the menu item using a bitmap.
- ''' The low-order word of the dwTypeData member is the bitmap handle, and the cch member is ignored.
- ''' "ItemType.BITMAP" is replaced by "ItemMask.BITMAP" and "hbmpItem".
- ''' </summary>
- BITMAP = &H4L
- ''' <summary>
- ''' Displays selected menu items using a radio-button mark instead of a check mark if the hbmpChecked member is NULL.
- ''' </summary>
- RADIOCHECK = &H200L
- ''' <summary>
- ''' Specifies that the menu item is a separator.
- ''' A menu item separator appears as a horizontal dividing line.
- ''' The dwTypeData and cch members are ignored.
- ''' This value is valid only in a drop-down menu, submenu, or shortcut menu.
- ''' </summary>
- SEPARATOR = &H800L
- ''' <summary>
- ''' Displays the menu item using a text string.
- ''' The dwTypeData member is the pointer to a null-terminated string,
- ''' and the cch member is the length of the string.
- ''' "ItemType.TEXT" is replaced by "ItemMask.TEXT".
- ''' </summary>
- TEXT = &H0L
- ''' <summary>
- ''' Right-justifies the menu item and any subsequent items.
- ''' This value is valid only if the menu item is in a menu bar.
- ''' </summary>
- RIGHTJUSTIFY = &H4000L
- ''' <summary>
- ''' Specifies that menus cascade right-to-left (the default is left-to-right).
- ''' This is used to support right-to-left languages, such as Arabic and Hebrew.
- ''' </summary>
- RIGHTORDER = &H2000L
- ''' <summary>
- ''' Places the menu item on a new line (for a menu bar),
- ''' or in a new column (for a drop-down menu, submenu, or shortcut menu).
- ''' For a drop-down menu, submenu, or shortcut menu, a vertical line separates the new column from the old.
- ''' </summary>
- MENUBARBREAK = &H20L
- ''' <summary>
- ''' Places the menu item on a new line (for a menu bar),
- ''' or in a new column (for a drop-down menu, submenu, or shortcut menu).
- ''' For a drop-down menu, submenu, or shortcut menu, the columns are not separated by a vertical line.
- ''' </summary>
- MENUBREAK = &H40L
- ''' <summary>
- ''' Assigns responsibility for drawing the menu item to the window that owns the menu.
- ''' The window receives a "WM_MEASUREITEM" message before the menu is displayed for the first time,
- ''' and a "WM_DRAWITEM" message whenever the appearance of the menu item must be updated.
- ''' If this value is specified, the dwTypeData member contains an application-defined value.
- ''' </summary>
- OWNERDRAW = &H100L
- End Enum
- ''' <summary>
- ''' Mask type of the MenuInfo structure.
- ''' Indicates the members to be retrieved or set (except for "MenuMask.APPLYTOSUBMENUS").
- ''' This member can be one or more of the following values.
- ''' </summary>
- Public Enum MenuMask As Integer
- ''' <summary>
- ''' Settings apply to the menu and all of its submenus.
- ''' "SetMenuInfo" API function uses this flag and "GetMenuInfo" API function ignores this flag.
- ''' </summary>
- APPLYTOSUBMENUS = &H80000000
- ''' <summary>
- ''' Retrieves or sets the hbrBack member.
- ''' </summary>
- BACKGROUND = &H2
- ''' <summary>
- ''' Retrieves or sets the dwContextHelpID member.
- ''' </summary>
- HELPID = &H4
- ''' <summary>
- ''' Retrieves or sets the cyMax member.
- ''' </summary>
- MAXHEIGHT = &H1
- ''' <summary>
- ''' Retrieves or sets the dwMenuData member.
- ''' </summary>
- MENUDATA = &H8
- ''' <summary>
- ''' Retrieves or sets the dwStyle member.
- ''' </summary>
- STYLE = &H10
- End Enum
- ''' <summary>
- ''' The menu style.
- ''' This member can be one or more of the following values.
- ''' </summary>
- Public Enum MenuStyle As Integer
- ''' <summary>
- ''' Menu automatically ends when mouse is outside the menu for approximately 10 seconds..
- ''' </summary>
- AUTODISMIS = &H10000000
- ''' <summary>
- ''' The same space is reserved for the check mark and the bitmap.
- ''' If the check mark is drawn, the bitmap is not.
- ''' All checkmarks and bitmaps are aligned.
- ''' Used for menus where some items use checkmarks and some use bitmaps.
- ''' </summary>
- CHECKORBMP = &H4000000
- ''' <summary>
- ''' Menu items are OLE drop targets or drag sources.
- ''' Menu owner receives "WM_MENUDRAG" and "WM_MENUGETOBJECT" messages.
- ''' </summary>
- DRAGDROP = &H20000000
- ''' <summary>
- ''' Menu is modeless; that is,
- ''' there is no menu modal message loop while the menu is active.
- ''' </summary>
- MODELESS = &H40000000
- ''' <summary>
- ''' No space is reserved to the left of an item for a check mark.
- ''' The item can still be selected, but the check mark will not appear next to the item.
- ''' </summary>
- NOCHECK = &H80000000
- ''' <summary>
- ''' Menu owner receives a "WM_MENUCOMMAND" message,
- ''' instead of a "WM_COMMAND" message, when the user makes a selection.
- ''' "MenuStyle.NOTIFYBYPOS" is a menu header style and has no effect when applied to individual sub menus.
- ''' </summary>
- NOTIFYBYPOS = &H8000000
- End Enum
- #End Region ' Enumerations
- #Region " APIs "
- '''' <summary>
- '''' Creates an empty menu.
- '''' </summary>
- ' <Runtime.InteropServices.
- ' DllImport("user32.dll")>
- ' Private Shared Function CreateMenu() As IntPtr
- ' End Function
- '''' <summary>
- '''' Assigns a new menu to the specified window.
- '''' </summary>
- '<DllImport("user32.dll")> _
- 'Public Shared Function SetMenu(
- ' ByVal hWnd As IntPtr,
- ' ByVal hMenu As IntPtr
- ') As Boolean
- 'End Function
- ''' <summary>
- ''' Gets the handle of the form's system menu.
- ''' </summary>
- ''' <param name="hWnd">
- ''' The handle of the form for which to get the system menu.
- ''' </param>
- ''' <param name="bRevert">
- ''' Indicates whether the menu should be reset to its original state.
- ''' </param>
- ''' <returns>
- ''' The handle of the system menu of the specified form.
- ''' </returns>
- <Runtime.InteropServices.
- DllImport("user32.dll")>
- Private Shared Function GetSystemMenu(
- ByVal hWnd As IntPtr,
- ByVal bRevert As Integer
- ) As IntPtr
- End Function
- ''' <summary>
- ''' Sets the state of the specified menu item.
- ''' </summary>
- ''' <returns>
- ''' The previous state of the menu item if it exists, -1 otherwise.
- ''' </returns>
- <Runtime.InteropServices.
- DllImport("user32.dll")>
- Private Shared Function EnableMenuItem(
- ByVal hMenu As IntPtr,
- ByVal wIDEnableItem As UInteger,
- ByVal wEnable As UInteger
- ) As IntPtr
- End Function
- ''' <summary>
- ''' Determines the number of items in the specified menu.
- ''' </summary>
- <Runtime.InteropServices.
- DllImport("user32.dll")>
- Private Shared Function GetMenuItemCount(
- ByVal hMenu As IntPtr
- ) As Integer
- End Function
- ''' <summary>
- ''' Associates the specified bitmap with a menu item.
- ''' Whether the menu item is selected or clear,
- ''' the system displays the appropriate bitmap next to the menu item.
- ''' </summary>
- <Runtime.InteropServices.
- DllImport("user32.dll")>
- Private Shared Function SetMenuItemBitmaps(
- ByVal hMenu As IntPtr,
- ByVal uPosition As UInteger,
- ByVal uFlags As UInteger,
- ByVal hBitmapUnchecked As IntPtr,
- ByVal hBitmapChecked As IntPtr
- ) As Boolean
- End Function
- ''' <summary>
- ''' Destroys the specified menu and frees any memory that the menu occupies.
- ''' </summary>
- <Runtime.InteropServices.
- DllImport("user32.dll")>
- Private Shared Function DestroyMenu(
- ByVal hMenu As IntPtr
- ) As Boolean
- End Function
- ''' <summary>
- ''' Determines whether a handle is a menu handle.
- ''' </summary>
- <Runtime.InteropServices.
- DllImport("user32.dll")>
- Private Shared Function IsMenu(
- ByVal hMenu As IntPtr
- ) As Boolean
- End Function
- ''' <summary>
- ''' Insert a menu item into an existing menu.
- ''' </summary>
- <Runtime.InteropServices.
- DllImport("user32.dll",
- SetLastError:=True,
- CharSet:=Runtime.InteropServices.CharSet.Auto)>
- Friend Shared Function InsertMenuItem(
- ByVal hMenu As IntPtr, ByVal uItem As Integer,
- ByVal fByPosition As Boolean,
- ByRef lpmii As MenuItemInfo
- ) As Boolean
- End Function
- ''' <summary>
- ''' Deletes the specified menu item.
- ''' </summary>
- ''' <returns>
- ''' Non-zero if the function succeeds,
- ''' zero otherwise.
- ''' </returns>
- <Runtime.InteropServices.
- DllImport("user32.dll")>
- Private Shared Function DeleteMenu(
- ByVal hMenu As IntPtr,
- ByVal uPosition As UInteger,
- ByVal uFlags As UInteger
- ) As Boolean
- End Function
- ''' <summary>
- ''' Ends the calling thread's active menu
- ''' </summary>
- <Runtime.InteropServices.
- DllImport("user32.dll")>
- Private Shared Function EndMenu() As Boolean
- End Function
- ''' <summary>
- ''' Gets the ID of a menu item.
- ''' </summary>
- <Runtime.InteropServices.
- DllImport("user32.dll")>
- Public Shared Function GetMenuItemID(
- ByVal hMenu As IntPtr,
- ByVal nPos As Integer
- ) As Integer
- End Function
- ''' <summary>
- ''' Gets the text of a menu item.
- ''' </summary>
- <Runtime.InteropServices.
- DllImport("user32.dll")>
- Private Shared Function GetMenuString(
- ByVal hMenu As IntPtr,
- ByVal uIDItem As UInteger,
- <Runtime.InteropServices.Out,
- Runtime.InteropServices.MarshalAs(
- Runtime.InteropServices.UnmanagedType.LPStr)>
- ByVal lpString As System.Text.StringBuilder,
- ByVal nMaxCount As Integer,
- ByVal uFlag As UInteger
- ) As Integer
- End Function
- ''' <summary>
- ''' Gets the State of a menu item.
- ''' </summary>
- <Runtime.InteropServices.
- DllImport("user32.dll")>
- Private Shared Function GetMenuState(
- ByVal hMenu As IntPtr,
- ByVal uId As UInteger,
- ByVal uFlags As UInteger
- ) As UInteger
- End Function
- ''' <summary>
- ''' Gets the handle of the form's system menu.
- ''' </summary>
- ''' <param name="hMenu">
- ''' The handle to the menu that contains the menu item.
- ''' </param>
- ''' <param name="uItem">
- ''' The identifier or position of the menu item to get information about.
- ''' The meaning of this parameter depends on the value of fByPosition.
- ''' </param>
- ''' <param name="fByPosition">
- ''' The meaning of uItem.
- ''' If this parameter is FALSE, uItem is a menu item identifier,
- ''' If this parameter is TRUE, it is a menu item position.
- ''' </param>
- ''' <param name="lpmii">
- ''' A pointer to a MenuItemInfo structure that specifies the information to retrieve.
- ''' Note that you must set the cbSize member to sizeof(MENUITEMINFO) before calling this function.
- ''' </param>
- <Runtime.InteropServices.
- DllImport("user32.dll",
- CharSet:=Runtime.InteropServices.CharSet.Auto)> _
- Private Shared Function GetMenuItemInfo(
- ByVal hMenu As IntPtr,
- ByVal uItem As UInteger,
- ByVal fByPosition As Boolean,
- ByRef lpmii As MenuItemInfo
- ) As Boolean
- End Function
- ''' <summary>
- ''' Sets information for a specified menu..
- ''' </summary>
- ''' <param name="hMenu">
- ''' The handle to the menu that contains the menu item.
- ''' </param>
- ''' <param name="lpcmi">
- ''' A pointer to a MENUINFO structure that specifies the information to retrieve.
- ''' </param>
- <Runtime.InteropServices.
- DllImport("user32.dll")>
- Private Shared Function SetMenuInfo(
- ByVal hmenu As IntPtr,
- <Runtime.InteropServices.[In]>
- ByRef lpcmi As MenuInfo
- ) As Boolean
- End Function
- ''' <summary>
- ''' Creates a logical brush that has the specified solid color.
- ''' A solid brush is a bitmap that the system uses to paint the interiors of filled shapes.
- ''' After an application creates a brush by calling CreateSolidBrush,
- ''' it can select that brush into any device context by calling the "SelectObject" API function.
- ''' When you no longer need the brush, call the "DeleteObject" API function to delete it.
- ''' </summary>
- <Runtime.InteropServices.
- DllImport("gdi32.dll")>
- Private Shared Function CreateSolidBrush(
- ByVal crColor As UInteger
- ) As IntPtr
- End Function
- ''' <summary>
- ''' Selects an object into a specified device context.
- ''' The new object replaces the previous object of the same type.
- ''' </summary>
- <Runtime.InteropServices.
- DllImport("gdi32.dll")>
- Public Shared Function SelectObject(
- ByVal hdc As IntPtr,
- ByVal hObject As IntPtr
- ) As IntPtr
- End Function
- ''' <summary>
- ''' Deletes a logical pen, brush, font, bitmap, region, or palette,
- ''' freeing all system resources associated with the object.
- ''' After the object is deleted, the specified handle is no longer valid.
- ''' </summary>
- <Runtime.InteropServices.
- DllImport("gdi32.dll")>
- Private Shared Function DeleteObject(
- ByVal hObject As IntPtr
- ) As <Runtime.InteropServices.MarshalAs(
- Runtime.InteropServices.UnmanagedType.Bool)> Boolean
- End Function
- ''' <summary>
- ''' Changes information about a menu item.
- ''' </summary>
- ''' <param name="hMenu ">
- ''' A handle to the menu that contains the menu item.
- ''' </param>
- ''' <param name="uItem">
- ''' The identifier or position of the menu item to change.
- ''' The meaning of this parameter depends on the value of fByPosition.
- ''' </param>
- ''' <param name="fByPosition">
- ''' The meaning of "uItem".
- ''' If this parameter is set to "FALSE", "uItem" is a menu item identifier.
- ''' Otherwise, it is a menu item position.
- ''' </param>
- ''' <param name="lpmii">
- ''' A pointer to a MenuItemInfo structure that contains information about the menu item,
- ''' and specifies which menu item attributes to change.
- ''' </param>
- <Runtime.InteropServices.
- DllImport("user32.dll",
- SetLastError:=True,
- CharSet:=Runtime.InteropServices.CharSet.Auto)>
- Private Shared Function SetMenuItemInfo(
- ByVal hMenu As IntPtr,
- ByVal uItem As UInteger,
- ByVal fByPosition As Boolean,
- <Runtime.InteropServices.[In]>
- ByRef lpmii As MenuItemInfo
- ) As Boolean
- End Function
- #End Region ' APIs
- #Region " Structures "
- ''' <summary>
- ''' MenuItemInfo Structure,
- ''' Contains information about a menu,
- ''' Is used to set menu information.
- ''' </summary>
- <Runtime.InteropServices.
- StructLayout(Runtime.InteropServices.LayoutKind.Sequential,
- CharSet:=Runtime.InteropServices.CharSet.Auto)>
- Public Structure MenuInfo
- ''' <summary>
- ''' The size of the structure, in bytes.
- ''' The caller must set this member to sizeof(MenuInfo).
- ''' </summary>
- Public cbSize As UInteger
- ''' <summary>
- ''' Indicates the members to be retrieved or set (except for "MenuMask.APPLYTOSUBMENUS").
- ''' This member can be one or more of the "MenuMask" Enum values.
- ''' </summary>
- Public fMask As UInteger
- ''' <summary>
- ''' The menu style.
- ''' This member can be one or more of the following values.
- ''' </summary>
- Public dwStyle As UInteger
- ''' <summary>
- ''' The maximum height of the menu in pixels.
- ''' When the menu items exceed the space available, scroll bars are automatically used.
- ''' The default (0) is the screen height.
- ''' </summary>
- Public cyMax As UInteger
- ''' <summary>
- ''' A handle to the brush to be used for the menu's background.
- ''' </summary>
- Public hbrBack As IntPtr
- ''' <summary>
- ''' The context help identifier.
- ''' This is the same value used in the "GetMenuContextHelpId" and "SetMenuContextHelpId" API functions.
- ''' </summary>
- Public dwContextHelpID As UInteger
- ''' <summary>
- ''' An application-defined value.
- ''' </summary>
- Public dwMenuData As UIntPtr
- End Structure
- ''' <summary>
- ''' MenuItemInfo Structure,
- ''' Contains information about a menu item,
- ''' Is used to set a menu item info,
- ''' to add a new item or to get an existing item.
- ''' </summary>
- <Runtime.InteropServices.
- StructLayout(Runtime.InteropServices.LayoutKind.Sequential,
- CharSet:=Runtime.InteropServices.CharSet.Auto)>
- Public Structure MenuItemInfo
- ''' <summary>
- ''' The size of the structure, in bytes.
- ''' The caller must set this member to sizeof(MenuItemInfo).
- ''' </summary>
- Public cbSize As Integer
- ''' <summary>
- ''' Indicates the members to be retrieved or set.
- ''' This member can be one or more of the "ItemMask" Enum values.
- ''' </summary>
- Public fMask As Integer
- ''' <summary>
- ''' The menu item type.
- ''' This member can be one or more of the "ItemType" Enum values.
- ''' The "ItemType.BITMAP", "ItemType.SEPARATOR", and "ItemType.MFT_STRING" values cannot be combined with one another.
- ''' Set "fMask" member to "ItemMask.TYPE" to use "fType" member.
- ''' "fType" is used only if "fMask" has a value of "ItemMask.TYPE".
- ''' </summary>
- Public fType As Integer
- ''' <summary>
- ''' The menu item state.
- ''' This member can be one or more of the "ItemState" Enum values.
- ''' Set fMask to "ItemMask.STATE" to use "fState".
- ''' </summary>
- Public fState As Integer
- ''' <summary>
- ''' An application-defined value that identifies the menu item.
- ''' Set "fMask" to "ItemMask.ID" to use "wID".
- ''' </summary>
- Public wID As Integer
- ''' <summary>
- ''' A handle to the drop-down menu or submenu associated with the menu item.
- ''' If the menu item is not an item that opens a drop-down menu or submenu, this member is NULL.
- ''' Set "fMask" to "ItemMask.SUBMENU" to use "hSubMenu".
- ''' </summary>
- Public hSubMenu As IntPtr
- ''' <summary>
- ''' A handle to the bitmap to display next to the item if it is selected.
- ''' If this member is NULL, a default bitmap is used.
- ''' If the "ItemType.RADIOCHECK" type value is specified, the default bitmap is a bullet,
- ''' Otherwise it is a check mark.
- ''' Set "fMask" to "ItemMask.CHECKMARKS" to use "hbmpChecked".
- ''' </summary>
- Public hbmpChecked As IntPtr
- ''' <summary>
- ''' A handle to the bitmap to display next to the item if it is not selected.
- ''' If this member is NULL, no bitmap is used.
- ''' Set "fMask" to "ItemMask.CHECKMARKS" to use "hbmpUnchecked".
- ''' </summary>
- Public hbmpUnchecked As IntPtr
- ''' <summary>
- ''' An application-defined value associated with the menu item.
- ''' Set "fMask" to "ItemMask.DATA" to use "dwItemData".
- ''' </summary>
- Public dwItemData As IntPtr
- ''' <summary>
- ''' The contents of the menu item.
- ''' The meaning of this member depends on the value of fType,
- ''' and is used only if the "ItemMask.TYPE" flag is set in the "fMask" member.
- ''' </summary>
- Public dwTypeData As String
- ''' <summary>
- ''' The length of the menu item text, in characters,
- ''' when information is received about a menu item of the "ItemType.TEXT" type.
- ''' However, "cch" is used only if the "ItemMask.TYPE" flag is set in the "fMask" member and is zero otherwise.
- ''' Also, "cch" is ignored when the content of a menu item is set by calling "SetMenuItemInfo" API function.
- ''' The "cch" member is used when the "ItemMask.TEXT" flag is set in the "fMask" member.
- ''' </summary>
- Public cch As Integer
- ''' <summary>
- ''' A handle to the bitmap to be displayed.
- ''' It is used when the "ItemMask.BITMAP" flag is set in the "fMask" member.
- ''' </summary>
- Public hbmpItem As IntPtr
- End Structure
- #End Region ' Structures
- #Region " New Constructor "
- ''' <summary>
- ''' Creates a new SystemMenuManager object for the specified form
- ''' </summary>
- ''' <param name="form">
- ''' The form for which to manage the system menu.
- ''' </param>
- Public Sub New(ByVal form As Form)
- ' Set the Formulary.
- Me.form = form
- ' Set the handle of the form's system menu.
- MenuHandle = GetSystemMenu(form.Handle, False)
- ' Assign the form handle.
- SetFormHandle()
- End Sub
- #End Region ' New Constructor
- #Region " Public Methods "
- ''' <summary>
- ''' Set an state for a menu item.
- ''' </summary>
- ''' <param name="item">
- ''' The system menu item.
- ''' </param>
- ''' <param name="state">
- ''' The new state for the item.
- ''' </param>
- Public Function SetItemState(ByVal item As Item,
- ByVal state As ItemState) As Boolean
- ItemStates(item) = state
- If item = item.Close Then
- CloseItem_State = state
- End If
- If state = ItemState.Removed Then
- Return DeleteMenu(MenuHandle, item, ItemPosition.ByCommand Or 0)
- Else
- Return EnableMenuItem(MenuHandle, item, ItemPosition.ByCommand Or state)
- End If
- End Function
- ''' <summary>
- ''' Set an state for a menu item at given position.
- ''' </summary>
- ''' <param name="position">
- ''' The menu item position.
- ''' </param>
- ''' <param name="state">
- ''' The new state for the item.
- ''' </param>
- Public Function SetItemState(ByVal position As Integer,
- ByVal state As ItemState) As Boolean
- Try
- PositionItemStates.Add(position, state)
- Catch ' ex As ArgumentException
- PositionItemStates(position) = state
- End Try
- If state = ItemState.Removed Then
- Return DeleteMenu(MenuHandle, position, ItemPosition.ByPosition Or 0)
- Else
- Return EnableMenuItem(MenuHandle, position, ItemPosition.ByPosition Or state)
- End If
- End Function
- ''' <summary>
- ''' Set a custom Bitmap image for a MenuItem.
- ''' </summary>
- ''' <param name="item">
- ''' The menu item.
- ''' </param>
- Public Function SetItemBitmap(ByVal item As Item,
- ByVal bmp As Bitmap) As Boolean
- ItemBitmaps(item) = bmp
- Return SetMenuItemBitmaps(MenuHandle,
- item,
- ItemPosition.ByCommand,
- bmp.GetHbitmap,
- bmp.GetHbitmap)
- End Function
- ''' <summary>
- ''' Set a custom Bitmap image for a MenuItem at given position.
- ''' </summary>
- ''' <param name="position">
- ''' The menu item position.
- ''' </param>
- Public Function SetItemBitmap(ByVal position As Integer,
- ByVal bmp As Bitmap) As Boolean
- Try
- PositionItemBitmaps.Add(position, bmp)
- Catch ' ex As System.ArgumentException
- PositionItemBitmaps(position) = bmp
- End Try
- Return SetMenuItemBitmaps(MenuHandle,
- position,
- ItemPosition.ByPosition,
- bmp.GetHbitmap,
- bmp.GetHbitmap)
- End Function
- ''' <summary>
- ''' Returns the custom Bitmap image used by a MenuItem.
- ''' </summary>
- ''' <param name="item">
- ''' The menu item.
- ''' </param>
- Public Function GetItemBitmap(ByVal item As Item) As Bitmap
- Return ItemBitmaps(item)
- End Function
- ''' <summary>
- ''' Returns the custom Bitmap image used by a MenuItem at given position.
- ''' </summary>
- ''' <param name="position">
- ''' The menu item position.
- ''' </param>
- Public Function GetItemBitmap(ByVal position As Integer) As Bitmap
- Return If(Not PositionItemBitmaps.FirstOrDefault(Function(item) item.Key = position).Key = Nothing,
- PositionItemBitmaps(position),
- Nothing)
- End Function
- ''' <summary>
- ''' Removes the custom Bitmap image used by a MenuItem.
- ''' </summary>
- ''' <param name="item">
- ''' The menu item.
- ''' </param>
- Public Function RemoveItemBitmap(ByVal item As Item) As Boolean
- ItemBitmaps(item) = Nothing
- Return SetMenuItemBitmaps(MenuHandle,
- item,
- ItemPosition.ByCommand,
- Nothing,
- Nothing)
- End Function
- ''' <summary>
- ''' Removes the custom Bitmap image used by a MenuItem at given position.
- ''' </summary>
- ''' <param name="position">
- ''' The menu item position.
- ''' </param>
- Public Function RemoveItemBitmap(ByVal position As Integer) As Boolean
- If Not PositionItemBitmaps.FirstOrDefault(Function(item) item.Key = position).Key = Nothing Then
- PositionItemBitmaps(position) = Nothing
- End If
- Return SetMenuItemBitmaps(MenuHandle,
- position,
- ItemPosition.ByPosition,
- Nothing,
- Nothing)
- End Function
- ''' <summary>
- ''' Gets the amount of menu items.
- ''' </summary>
- Public Function GetItemCount() As Integer
- Return GetMenuItemCount(MenuHandle) ' - 1
- End Function
- ''' <summary>
- ''' Enables all the menu items.
- ''' </summary>
- Public Sub EnableAllItems()
- For i As Integer = 0 To GetItemCount() - 1
- SetItemState(i, ItemState.Enabled)
- Next i
- End Sub
- ''' <summary>
- ''' Disables all the menu items.
- ''' </summary>
- Public Sub DisableAllItems()
- For i As Integer = 0 To GetItemCount() - 1
- SetItemState(i, ItemState.Disabled)
- Next i
- End Sub
- ''' <summary>
- ''' Removes all the menu items.
- ''' </summary>
- Public Sub RemoveAllItems()
- Do Until Not CBool(GetItemCount())
- DeleteMenu(MenuHandle, 0, ItemPosition.ByPosition Or 0)
- Loop
- End Sub
- ''' <summary>
- ''' Restores the menu to defaults.
- ''' </summary>
- Public Sub Restore_Menu()
- CloseItem_State = ItemState.Enabled
- Me.MenuHandle = GetSystemMenu(Me.form.Handle, True)
- End Sub
- ''' <summary>
- ''' Add a separator at default position.
- ''' </summary>
- ''' <param name="position">
- ''' The position where the item will be added.
- ''' </param>
- ''' <returns>
- ''' True if the operation was successful, otherwise False.
- ''' </returns>
- Public Function AddSeparator(ByVal position As DefaultPositions) As Boolean
- mii = New MenuItemInfo
- With mii
- .cbSize = Runtime.InteropServices.Marshal.SizeOf(GetType(MenuItemInfo))
- .fMask = ItemMask.ID Or ItemMask.TYPE
- .fType = ItemType.SEPARATOR
- .wID = -1
- End With
- Return InsertMenuItem(MenuHandle, GetPosition(position), True, mii)
- End Function
- ''' <summary>
- ''' Add a separator at given position.
- ''' </summary>
- ''' <param name="position">
- ''' The position where the item will be added.
- ''' </param>
- ''' <returns>
- ''' True if the operation was successful, otherwise False.
- ''' </returns>
- Public Function AddSeparator(ByVal position As Integer) As Boolean
- mii = New MenuItemInfo
- With mii
- .cbSize = Runtime.InteropServices.Marshal.SizeOf(GetType(MenuItemInfo))
- .fMask = ItemMask.ID Or ItemMask.TYPE
- .fType = ItemType.SEPARATOR
- .wID = -1
- End With
- Return InsertMenuItem(MenuHandle, position, True, mii)
- End Function
- ''' <summary>
- ''' Add an Item at default position.
- ''' </summary>
- ''' <param name="Label">
- ''' The text of the item.
- ''' </param>
- ''' <param name="ID">
- ''' A Identifier to interact with this item when is clicked.
- ''' </param>
- ''' <param name="position">
- ''' The position where the item will be added.
- ''' </param>
- ''' <param name="ImageChecked">
- ''' Image displayed when Item is selected.
- ''' </param>
- ''' <param name="ImageUnchecked">
- ''' Image displayed when Item is not selected.
- ''' </param>
- ''' <returns>
- ''' True if the operation was successful, otherwise False.
- ''' </returns>
- Public Function AddItem(ByVal Label As String,
- ByVal ID As Integer,
- ByVal Position As DefaultPositions,
- Optional ByVal ImageChecked As Bitmap = Nothing,
- Optional ByVal ImageUnchecked As Bitmap = Nothing) As Boolean
- mii = New MenuItemInfo
- With mii
- .cbSize = Runtime.InteropServices.Marshal.SizeOf(GetType(MenuItemInfo))
- .fMask = ItemMask.STATE Or ItemMask.ID Or ItemMask.TYPE Or ItemMask.CHECKMARKS
- .fType = ItemType.TEXT
- .fState = ItemState.Enabled
- .wID = ID
- .dwTypeData = Label
- .hbmpChecked = If(ImageChecked IsNot Nothing, ImageChecked.GetHbitmap, Nothing)
- .hbmpUnchecked = If(ImageUnchecked IsNot Nothing, ImageUnchecked.GetHbitmap, Nothing)
- .cch = .dwTypeData.Length
- End With
- Return InsertMenuItem(MenuHandle, GetPosition(Position), True, mii)
- End Function
- ''' <summary>
- ''' Adds an Item at the given position.
- ''' </summary>
- ''' <param name="Label">
- ''' The text of the item.
- ''' </param>
- ''' <param name="ID">
- ''' A Identifier to interact with this item when is clicked.
- ''' </param>
- ''' <param name="position">
- ''' The position where the item will be added.
- ''' </param>
- ''' <param name="ImageChecked">
- ''' Image displayed when Item is selected.
- ''' </param>
- ''' <param name="ImageUnchecked">
- ''' Image displayed when Item is not selected.
- ''' </param>
- ''' <returns>
- ''' True if the operation was successful, otherwise False.
- ''' </returns>
- Public Function AddItem(ByVal Label As String,
- ByVal ID As Integer,
- ByVal Position As Integer,
- Optional ByVal ImageChecked As Bitmap = Nothing,
- Optional ByVal ImageUnchecked As Bitmap = Nothing) As Boolean
- mii = New MenuItemInfo
- With mii
- .cbSize = Runtime.InteropServices.Marshal.SizeOf(GetType(MenuItemInfo))
- .fMask = ItemMask.STATE Or ItemMask.ID Or ItemMask.TYPE Or ItemMask.CHECKMARKS
- .fType = ItemType.TEXT
- .fState = ItemState.Enabled
- .wID = ID
- .dwTypeData = Label
- .hbmpChecked = If(ImageChecked IsNot Nothing, ImageChecked.GetHbitmap, Nothing)
- .hbmpUnchecked = If(ImageUnchecked IsNot Nothing, ImageUnchecked.GetHbitmap, Nothing)
- .cch = .dwTypeData.Length
- End With
- Return InsertMenuItem(MenuHandle, Position, True, mii)
- End Function
- ''' <summary>
- ''' Determines whether a handle is a menu handle.
- ''' </summary>
- ''' <returns>
- ''' True if is a menu handle, otherwise False.
- ''' </returns>
- Public Function IsMenuHandle(ByVal Handle As IntPtr) As Boolean
- Return IsMenu(Handle)
- End Function
- ''' <summary>
- ''' Gets the ID of a menu item.
- ''' </summary>
- Public Function GetItemID(ByVal Item As Item) As Integer
- Return Item
- End Function
- ''' <summary>
- ''' Gets the ID of a menu item at given position.
- ''' </summary>
- Public Function GetItemID(ByVal position As Integer) As Integer
- Return GetMenuItemID(MenuHandle, position)
- End Function
- ''' <summary>
- ''' Gets the text of a menu item.
- ''' </summary>
- Public Function GetItemText(ByVal Item As Item) As String
- ItemText.Clear()
- GetMenuString(MenuHandle, Item, ItemText, ItemText.Capacity, ItemPosition.ByCommand)
- Return ItemText.ToString
- End Function
- ''' <summary>
- ''' Gets the text of a menu item at given position.
- ''' </summary>
- Public Function GetItemText(ByVal position As Integer) As String
- ItemText.Clear()
- GetMenuString(MenuHandle, position, ItemText, ItemText.Capacity, ItemPosition.ByPosition)
- Return ItemText.ToString
- End Function
- ''' <summary>
- ''' Gets the state of a menu item.
- ''' </summary>
- Public Function GetItemState(ByVal Item As Item) As ItemState
- Return [Enum].Parse(GetType(ItemState), GetMenuState(MenuHandle, Item, ItemPosition.ByCommand))
- End Function
- ''' <summary>
- ''' Gets the state of a menu item at given position.
- ''' </summary>
- Public Function GetItemState(ByVal position As Integer) As ItemState
- Return [Enum].Parse(GetType(ItemState), GetMenuState(MenuHandle, position, ItemPosition.ByPosition))
- End Function
- ''' <summary>
- ''' Set the background color of a menu.
- ''' </summary>
- ''' <returns>
- ''' True if the operation was successful, otherwise False.
- ''' </returns>
- Public Function SetMenuBackColor(ByVal color As Color) As Boolean
- MenuBrush = CreateSolidBrush(CUInt(ColorTranslator.ToWin32(color)))
- mi = New MenuInfo
- With mi
- .cbSize = Runtime.InteropServices.Marshal.SizeOf(GetType(MenuInfo))
- .fMask = MenuMask.BACKGROUND
- .hbrBack = MenuBrush
- End With
- Return SetMenuInfo(MenuHandle, mi)
- End Function
- ''' <summary>
- ''' Set the menu style.
- ''' </summary>
- ''' <returns>
- ''' True if the operation was successful, otherwise False.
- ''' </returns>
- Public Function SetMenuStyle(ByVal Style As MenuStyle) As Boolean
- mi = New MenuInfo
- With mi
- .cbSize = Runtime.InteropServices.Marshal.SizeOf(GetType(MenuInfo))
- .fMask = MenuMask.STYLE
- .dwStyle = Style
- End With
- Return SetMenuInfo(MenuHandle, mi)
- End Function
- ''' <summary>
- ''' Set the text of a menu item.
- ''' </summary>
- ''' <param name="item">
- ''' The menu item.
- ''' </param>
- ''' <param name="text">
- ''' The new text for the item.
- ''' </param>
- Public Function SetItemText(ByVal item As Item,
- ByVal text As String) As Boolean
- mii = New MenuItemInfo
- With mii
- .cbSize = Runtime.InteropServices.Marshal.SizeOf(GetType(MenuItemInfo))
- .fMask = ItemMask.TEXT
- .dwTypeData = text
- End With
- Return SetMenuItemInfo(MenuHandle, item, False, mii)
- End Function
- ''' <summary>
- ''' Set the text of a menu item at given position.
- ''' </summary>
- ''' <param name="position">
- ''' The menu item position.
- ''' </param>
- ''' <param name="text">
- ''' The new text for the item.
- ''' </param>
- Public Function SetItemText(ByVal position As Integer,
- ByVal text As String) As Boolean
- mii = New MenuItemInfo
- With mii
- .cbSize = Runtime.InteropServices.Marshal.SizeOf(GetType(MenuItemInfo))
- .fMask = ItemMask.TEXT
- .dwTypeData = text
- End With
- Return SetMenuItemInfo(MenuHandle, position, True, mii)
- End Function
- #End Region ' Public Methods
- #Region " Private Methods "
- ''' <summary>
- ''' Converts a MenuItemPosition value to a menu item position.
- ''' </summary>
- ''' <param name="position">
- ''' The MenuItemPosition value.
- ''' </param>
- Private Function GetPosition(ByVal position As ItemPosition) As Integer
- Select Case position
- Case DefaultPositions.First
- Return 0
- Case DefaultPositions.Second
- Return 1
- Case DefaultPositions.Third
- Return 2
- Case DefaultPositions.Middle
- Return (GetItemCount() \ 2)
- Case DefaultPositions.Penultimate
- Return (GetItemCount() - 1)
- Case DefaultPositions.Last
- Return (GetItemCount() + 1)
- Case Else
- Return Nothing
- End Select
- End Function
- ''' <summary>
- ''' Refreshes the state of the Close menu item.
- ''' </summary>
- ''' <remarks>
- ''' Action is only taken if the state is Disabled or Grayed.
- ''' </remarks>
- Private Sub Refresh_CloseItem()
- If CloseItem_State = ItemState.Disabled _
- OrElse CloseItem_State = ItemState.Grayed Then
- ' Set the Close menu item state.
- EnableMenuItem(MenuHandle, Item.Close, ItemPosition.ByCommand Or CloseItem_State)
- End If
- End Sub
- #End Region ' Private Methods
- #Region " Form Event Handlers "
- ''' <summary>
- ''' The Close menu item must have it's state refresehed,
- ''' if it is present and not enabled.
- ''' </summary>
- Private Sub Refresh() _
- Handles form.Load, form.Resize
- Refresh_CloseItem()
- End Sub
- ''' <summary>
- ''' SetHandle
- ''' Assign the handle of the target form to this NativeWindow,
- ''' necessary to override WndProc.
- ''' </summary>
- Private Sub SetFormHandle() _
- Handles form.HandleCreated, form.Load, form.Shown
- Try
- If Not Me.Handle.Equals(Me.form.Handle) Then
- Me.AssignHandle(Me.form.Handle)
- End If
- Catch ' ex As InvalidOperationException
- End Try
- End Sub
- ''' <summary>
- ''' Releases the Handle.
- ''' </summary>
- Private Sub OnHandleDestroyed() _
- Handles form.HandleDestroyed
- Me.ReleaseHandle()
- End Sub
- #End Region ' Form Event Handlers
- #Region " Windows Messages "
- ''' <summary>
- ''' Intercepts Menu messages.
- ''' </summary>
- Protected Overrides Sub WndProc(ByRef m As Message)
- Select Case m.Msg
- Case &H116 ' WM_INITMENU message
- ' Message is sent when a menu is about to become active.
- ' It occurs when the user clicks an item on the menu bar or presses a menu key.
- ' This allows the application to modify the menu before it is displayed.
- MenuHandle = GetSystemMenu(form.Handle, False)
- Case &H117 ' WM_INITMENUPOPUP
- ' Message is sent when a drop-down menu or submenu is about to become active.
- ' This allows an application to modify the menu before it is displayed,
- ' without changing the entire menu.
- ' Refresh the states of the Items by command.
- If ItemStates.FirstOrDefault(Function(item) item.Key).Value <> Nothing Then
- ItemStates.ToList().
- ForEach(Function(item) SetItemState(item.Key, item.Value))
- End If
- ' Refresh the states of the Items by position.
- If PositionItemStates.FirstOrDefault(Function(item) item.Key).Value <> Nothing Then
- PositionItemStates.ToList().
- ForEach(Function(item) SetItemState(CInt(item.Key), item.Value))
- End If
- Case &H112 ' WM_SYSCOMMAND
- ' Message is sent when the user chooses a command from the system menu,
- ' or when the user chooses the maximize button, minimize button, restore button, or close button.
- ' Begin step to retrieve the item Text
- mii = New MenuItemInfo With {
- .cbSize = Runtime.InteropServices.Marshal.SizeOf(GetType(MenuItemInfo)),
- .fMask = ItemMask.TEXT
- }
- ' Retrieve the text length member.
- GetMenuItemInfo(MenuHandle, m.WParam, False, mii)
- ' Account for terminating NUL character and allocate String
- mii.cch += 1
- mii.dwTypeData = Space(mii.cch)
- ' Retrieve the rest of the information.
- mii.fMask = ItemMask.ID Or ItemMask.TEXT Or ItemMask.STATE Or ItemMask.FTYPE
- GetMenuItemInfo(MenuHandle, m.WParam, False, mii)
- ' Set the Event arguments
- With ItemClickedArgs
- .ID = mii.wID
- .Text = mii.dwTypeData
- .State = [Enum].Parse(GetType(ItemState), mii.fState)
- .Type = [Enum].Parse(GetType(ItemType), mii.fType)
- End With
- RaiseEvent ItemClicked(MenuHandle, ItemClickedArgs)
- End Select
- ' Return control to base message handler.
- MyBase.WndProc(m)
- End Sub
- #End Region ' Windows Messages
- #Region " IDisposable "
- ''' <summary>
- ''' Disposes the objects generated by this instance.
- ''' </summary>
- Public Sub Dispose() Implements IDisposable.Dispose
- Dispose(True)
- GC.SuppressFinalize(Me)
- End Sub
- Protected Overridable Sub Dispose(IsDisposing As Boolean)
- Static IsBusy As Boolean = False ' To detect redundant calls.
- If Not IsBusy AndAlso IsDisposing Then
- DeleteObject(MenuBrush)
- Restore_Menu()
- EndMenu()
- Me.form = Nothing
- MenuHandle = IntPtr.Zero
- Me.ReleaseHandle()
- Me.DestroyHandle()
- End If
- IsBusy = True
- End Sub
- #End Region ' IDisposable
- #Region " ToDO?: "
- ' función "AppendMenu"?
- ' usar HotKeys? (&)
- ' Alguna cosa interesante con los submenus?
- #End Region ' ToDo
- End Class
- #End Region
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement