locked
MenuItem RRS feed

  • Question

  • good...
    1. What I want is to add a menuItem with the text "PASTE" to the form menu system

    2. I also want to add key combinations, such as ctrl + v to paste.

    By last
    3. Adding a SubMenuItem to the form menu system

    first of all, Thanks

    Monday, September 5, 2016 9:56 PM

Answers

  • Hello,

    I always believe if there is a solution out there use it be it C# or VB.NET. With that here is a C# library which I obtained from GitHub, placed it into a C# project and compiled it.

    • Download the library.
    • Add the project to your Visual Studio solution
    • Add a reference in your project to the C# project.
    • Add an Import Statement e.g. Imports MenuLibrary
    • Sample code below
    Imports MenuLibrary
    Public Class Form1
        Private systemMenu As SystemMenu
        Public Sub New()
            InitializeComponent()
            systemMenu = New SystemMenu(Me)
            systemMenu.AddCommand("&Paste", AddressOf OnSystemPaste, True)
        End Sub
        Protected Overrides Sub WndProc(ByRef msg As Message)
            MyBase.WndProc(msg)
    
            ' Let it know all messages so it can handle WM_SYSCOMMAND
            ' (This method is inlined)
            systemMenu.HandleMessage(msg)
        End Sub
        Private Sub OnSystemPaste()
            If Clipboard.ContainsText Then
                MessageBox.Show("Paste code goes here")
            End If
        End Sub
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim dataOps As New DataOperations
            If dataOps.GetCustomerDataAndContactName() Then
                cboCompanies.DataSource = dataOps.Customers
                cboCompanies.DisplayMember = "Name"
                cboContactNames.DataSource = dataOps.ContactNames
            End If
        End Sub
    End Class


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    • Marked as answer by JenCarlos Tuesday, September 6, 2016 4:19 PM
    • Unmarked as answer by JenCarlos Tuesday, September 6, 2016 4:19 PM
    • Marked as answer by JenCarlos Tuesday, September 6, 2016 4:19 PM
    Monday, September 5, 2016 10:29 PM
  • good...
    1. What I want is to add a menuItem with the text "PASTE" to the form menu system

    2. I also want to add key combinations, such as ctrl + v to paste.

    By last
    3. Adding a SubMenuItem to the form menu system

    first of all, Thanks

    Working with the API's for the System menu is long involved learning process as there are many of them. It took hours to get just this little bit to work from searching the net and I already had some of it that worked. So if you have further questions on this I suspect you should search the net and study until you learn enough to do it on your own.

    I have no idea how to bold the Paste .. Ctrl+V text but I believe you have to use API to owner draw it in System Menu somehow.

    The Hot Key code came from a thread answered by IronRazerz. And they are global so even if your app does not have focus they work for your app. I'm not sure how to remove and readd them if the app loses then gains focus although perhaps the Forms focus events could be used for that. As well as the forms resize event so if the form is minimized, not normal or maximized, they could be removed then added again when the form is normalized or maximized.

    The bitmap from resources is a .Png file that was reduced in size to 20 x 20 pixels in paint and saved before adding the file as a resource.

    Option Strict On
    
    Imports System.Runtime.InteropServices
    
    Public Class Form1
    
        <DllImport("user32.dll", CharSet:=CharSet.Auto, EntryPoint:="SetMenuItemBitmaps")> _
        Private Shared Function SetMenuItemBitmaps( _
            ByVal hMenu As IntPtr, _
            ByVal nPosition As Integer, _
            ByVal wFlags As Integer, _
            ByVal hBitmapUnchecked As IntPtr, _
            ByVal hBitmapChecked As IntPtr) As Integer
        End Function
    
        <DllImport("user32.dll", CharSet:=CharSet.Auto, EntryPoint:="GetSystemMenu")> _
        Private Shared Function GetSystemMenu( _
            ByVal hWnd As IntPtr, _
            ByVal bRevert As Integer) As IntPtr
        End Function
    
        <DllImport("user32.dll", CharSet:=CharSet.Auto, EntryPoint:="DrawMenuBar")> _
        Private Shared Function DrawMenuBar( _
            ByVal hwnd As IntPtr) As Integer
        End Function
    
        <DllImport("user32.dll", CharSet:=CharSet.Auto, EntryPoint:="InsertMenu")> _
        Private Shared Function InsertMenu( _
            ByVal hMenu As IntPtr, _
            ByVal nPosition As Integer, _
            ByVal wFlags As Integer, _
            ByVal wIDNewItem As Integer, _
            ByVal lpNewItem As String) As Integer
        End Function
    
        <DllImport("user32.dll")> _
        Private Shared Function CreatePopupMenu() As IntPtr
        End Function
    
        Private Const MF_BYPOSITION As Integer = &H400
        Private Const MF_SEPARATOR As Integer = &H800
        Private Const MF_POPUP As Integer = &H10
        Private Const MF_STRING As Integer = &H0
    
        Private Const WM_SYSCOMMAND As Int32 = &H112
        Private Const Paste As Int32 = 1000
    
        <DllImport("user32.dll", EntryPoint:="RegisterHotKey")> _
        Private Shared Function RegisterHotKey(ByVal hWnd As IntPtr, ByVal id As Integer, ByVal fsModifiers As Integer, ByVal vk As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("user32.dll", EntryPoint:="UnregisterHotKey")> _
        Private Shared Function UnregisterHotKey(ByVal hWnd As IntPtr, ByVal id As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        Private Const MOD_ALT As Integer = &H1
        Private Const MOD_CONTROL As Integer = &H2
        Private Const MOD_SHIFT As Integer = &H4
        Private Const WM_HOTKEY As Integer = &H312
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.Location = New Point(CInt((Screen.PrimaryScreen.WorkingArea.Width / 2) - (Me.Width / 2)), CInt((Screen.PrimaryScreen.WorkingArea.Height / 2) - (Me.Height / 2)))
            Dim iMenu As IntPtr = GetSystemMenu(Me.Handle, 0)
            Dim Bmp As New Bitmap(My.Resources.Crossbones)
            Dim Hicon As IntPtr = Bmp.GetHbitmap
            InsertMenu(iMenu, 4, MF_BYPOSITION + MF_SEPARATOR, 0, String.Empty)
            InsertMenu(iMenu, 5, MF_BYPOSITION, Paste, "Paste            Ctrl+V")
    
            SetMenuItemBitmaps(iMenu, 5, MF_BYPOSITION, Hicon, Hicon)
            DrawMenuBar(iMenu)
            InsertMenu(iMenu, 6, MF_BYPOSITION + MF_SEPARATOR, 0, String.Empty)
    
            Dim SubMenuIntPtr As IntPtr = CreatePopupMenu()
            InsertMenu(iMenu, 7, MF_POPUP Or MF_STRING Or MF_BYPOSITION, CInt(SubMenuIntPtr), "More Stuff")
            InsertMenu(SubMenuIntPtr, 0, MF_BYPOSITION, 0, "Do This")
            InsertMenu(SubMenuIntPtr, 1, MF_BYPOSITION, 0, "Do That")
    
            '100 is just an ID to use for registering a hot key. The next one would be 101 or whatever.
            RegisterHotKey(MyBase.Handle, 100, MOD_CONTROL, Keys.V)
        End Sub
    
        Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
            UnregisterHotKey(MyBase.Handle, 100) ' Unregister hot key when app exits.
        End Sub
    
        Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
            MyBase.WndProc(m)
            If (m.Msg = WM_SYSCOMMAND) Then
                Select Case m.WParam.ToInt32
                    Case Paste
                        Invoke(New PasteItDelegate(AddressOf PasteIt))
                End Select
            End If
            If m.Msg = WM_HOTKEY Then 'Detects that a HotKey message has been sent to the Form
    
                If m.WParam.ToInt32 = 100 Then 'Detects if the HotKey Id is 100 which is the Id of the HotKey (Ctrl+V)
                    Invoke(New PasteItDelegate(AddressOf PasteItHotKey))
                End If
    
            End If
        End Sub
    
        Private Delegate Sub PasteItDelegate()
    
        Private Sub PasteIt()
            MessageBox.Show("Paste menu item selected")
        End Sub
    
        Private Delegate Sub PasteItHotKeyDelegate()
    
        Private Sub PasteItHotKey()
            MessageBox.Show("Paste hot key selected")
        End Sub
    
    End Class


    La vida loca

    • Marked as answer by JenCarlos Tuesday, September 6, 2016 4:21 PM
    • Unmarked as answer by JenCarlos Tuesday, September 6, 2016 4:21 PM
    • Marked as answer by JenCarlos Tuesday, September 6, 2016 4:21 PM
    • Edited by Mr. Monkeyboy Wednesday, September 7, 2016 2:12 AM
    Tuesday, September 6, 2016 8:48 AM
  • You don't, instead trap it

    https://channel9.msdn.com/Forums/TechOff/256326-How-to-Capture-Control-V-in-Net


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    • Marked as answer by JenCarlos Tuesday, September 6, 2016 4:23 PM
    Tuesday, September 6, 2016 12:45 AM

All replies

  • Hello,

    I always believe if there is a solution out there use it be it C# or VB.NET. With that here is a C# library which I obtained from GitHub, placed it into a C# project and compiled it.

    • Download the library.
    • Add the project to your Visual Studio solution
    • Add a reference in your project to the C# project.
    • Add an Import Statement e.g. Imports MenuLibrary
    • Sample code below
    Imports MenuLibrary
    Public Class Form1
        Private systemMenu As SystemMenu
        Public Sub New()
            InitializeComponent()
            systemMenu = New SystemMenu(Me)
            systemMenu.AddCommand("&Paste", AddressOf OnSystemPaste, True)
        End Sub
        Protected Overrides Sub WndProc(ByRef msg As Message)
            MyBase.WndProc(msg)
    
            ' Let it know all messages so it can handle WM_SYSCOMMAND
            ' (This method is inlined)
            systemMenu.HandleMessage(msg)
        End Sub
        Private Sub OnSystemPaste()
            If Clipboard.ContainsText Then
                MessageBox.Show("Paste code goes here")
            End If
        End Sub
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim dataOps As New DataOperations
            If dataOps.GetCustomerDataAndContactName() Then
                cboCompanies.DataSource = dataOps.Customers
                cboCompanies.DisplayMember = "Name"
                cboContactNames.DataSource = dataOps.ContactNames
            End If
        End Sub
    End Class


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    • Marked as answer by JenCarlos Tuesday, September 6, 2016 4:19 PM
    • Unmarked as answer by JenCarlos Tuesday, September 6, 2016 4:19 PM
    • Marked as answer by JenCarlos Tuesday, September 6, 2016 4:19 PM
    Monday, September 5, 2016 10:29 PM
  • there any way to add key combinations Ctrl + v added to the menu
    Monday, September 5, 2016 10:46 PM
  • You don't, instead trap it

    https://channel9.msdn.com/Forums/TechOff/256326-How-to-Capture-Control-V-in-Net


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    • Marked as answer by JenCarlos Tuesday, September 6, 2016 4:23 PM
    Tuesday, September 6, 2016 12:45 AM
  • good...
    1. What I want is to add a menuItem with the text "PASTE" to the form menu system

    2. I also want to add key combinations, such as ctrl + v to paste.

    By last
    3. Adding a SubMenuItem to the form menu system

    first of all, Thanks

    Working with the API's for the System menu is long involved learning process as there are many of them. It took hours to get just this little bit to work from searching the net and I already had some of it that worked. So if you have further questions on this I suspect you should search the net and study until you learn enough to do it on your own.

    I have no idea how to bold the Paste .. Ctrl+V text but I believe you have to use API to owner draw it in System Menu somehow.

    The Hot Key code came from a thread answered by IronRazerz. And they are global so even if your app does not have focus they work for your app. I'm not sure how to remove and readd them if the app loses then gains focus although perhaps the Forms focus events could be used for that. As well as the forms resize event so if the form is minimized, not normal or maximized, they could be removed then added again when the form is normalized or maximized.

    The bitmap from resources is a .Png file that was reduced in size to 20 x 20 pixels in paint and saved before adding the file as a resource.

    Option Strict On
    
    Imports System.Runtime.InteropServices
    
    Public Class Form1
    
        <DllImport("user32.dll", CharSet:=CharSet.Auto, EntryPoint:="SetMenuItemBitmaps")> _
        Private Shared Function SetMenuItemBitmaps( _
            ByVal hMenu As IntPtr, _
            ByVal nPosition As Integer, _
            ByVal wFlags As Integer, _
            ByVal hBitmapUnchecked As IntPtr, _
            ByVal hBitmapChecked As IntPtr) As Integer
        End Function
    
        <DllImport("user32.dll", CharSet:=CharSet.Auto, EntryPoint:="GetSystemMenu")> _
        Private Shared Function GetSystemMenu( _
            ByVal hWnd As IntPtr, _
            ByVal bRevert As Integer) As IntPtr
        End Function
    
        <DllImport("user32.dll", CharSet:=CharSet.Auto, EntryPoint:="DrawMenuBar")> _
        Private Shared Function DrawMenuBar( _
            ByVal hwnd As IntPtr) As Integer
        End Function
    
        <DllImport("user32.dll", CharSet:=CharSet.Auto, EntryPoint:="InsertMenu")> _
        Private Shared Function InsertMenu( _
            ByVal hMenu As IntPtr, _
            ByVal nPosition As Integer, _
            ByVal wFlags As Integer, _
            ByVal wIDNewItem As Integer, _
            ByVal lpNewItem As String) As Integer
        End Function
    
        <DllImport("user32.dll")> _
        Private Shared Function CreatePopupMenu() As IntPtr
        End Function
    
        Private Const MF_BYPOSITION As Integer = &H400
        Private Const MF_SEPARATOR As Integer = &H800
        Private Const MF_POPUP As Integer = &H10
        Private Const MF_STRING As Integer = &H0
    
        Private Const WM_SYSCOMMAND As Int32 = &H112
        Private Const Paste As Int32 = 1000
    
        <DllImport("user32.dll", EntryPoint:="RegisterHotKey")> _
        Private Shared Function RegisterHotKey(ByVal hWnd As IntPtr, ByVal id As Integer, ByVal fsModifiers As Integer, ByVal vk As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("user32.dll", EntryPoint:="UnregisterHotKey")> _
        Private Shared Function UnregisterHotKey(ByVal hWnd As IntPtr, ByVal id As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        Private Const MOD_ALT As Integer = &H1
        Private Const MOD_CONTROL As Integer = &H2
        Private Const MOD_SHIFT As Integer = &H4
        Private Const WM_HOTKEY As Integer = &H312
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.Location = New Point(CInt((Screen.PrimaryScreen.WorkingArea.Width / 2) - (Me.Width / 2)), CInt((Screen.PrimaryScreen.WorkingArea.Height / 2) - (Me.Height / 2)))
            Dim iMenu As IntPtr = GetSystemMenu(Me.Handle, 0)
            Dim Bmp As New Bitmap(My.Resources.Crossbones)
            Dim Hicon As IntPtr = Bmp.GetHbitmap
            InsertMenu(iMenu, 4, MF_BYPOSITION + MF_SEPARATOR, 0, String.Empty)
            InsertMenu(iMenu, 5, MF_BYPOSITION, Paste, "Paste            Ctrl+V")
    
            SetMenuItemBitmaps(iMenu, 5, MF_BYPOSITION, Hicon, Hicon)
            DrawMenuBar(iMenu)
            InsertMenu(iMenu, 6, MF_BYPOSITION + MF_SEPARATOR, 0, String.Empty)
    
            Dim SubMenuIntPtr As IntPtr = CreatePopupMenu()
            InsertMenu(iMenu, 7, MF_POPUP Or MF_STRING Or MF_BYPOSITION, CInt(SubMenuIntPtr), "More Stuff")
            InsertMenu(SubMenuIntPtr, 0, MF_BYPOSITION, 0, "Do This")
            InsertMenu(SubMenuIntPtr, 1, MF_BYPOSITION, 0, "Do That")
    
            '100 is just an ID to use for registering a hot key. The next one would be 101 or whatever.
            RegisterHotKey(MyBase.Handle, 100, MOD_CONTROL, Keys.V)
        End Sub
    
        Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
            UnregisterHotKey(MyBase.Handle, 100) ' Unregister hot key when app exits.
        End Sub
    
        Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
            MyBase.WndProc(m)
            If (m.Msg = WM_SYSCOMMAND) Then
                Select Case m.WParam.ToInt32
                    Case Paste
                        Invoke(New PasteItDelegate(AddressOf PasteIt))
                End Select
            End If
            If m.Msg = WM_HOTKEY Then 'Detects that a HotKey message has been sent to the Form
    
                If m.WParam.ToInt32 = 100 Then 'Detects if the HotKey Id is 100 which is the Id of the HotKey (Ctrl+V)
                    Invoke(New PasteItDelegate(AddressOf PasteItHotKey))
                End If
    
            End If
        End Sub
    
        Private Delegate Sub PasteItDelegate()
    
        Private Sub PasteIt()
            MessageBox.Show("Paste menu item selected")
        End Sub
    
        Private Delegate Sub PasteItHotKeyDelegate()
    
        Private Sub PasteItHotKey()
            MessageBox.Show("Paste hot key selected")
        End Sub
    
    End Class


    La vida loca

    • Marked as answer by JenCarlos Tuesday, September 6, 2016 4:21 PM
    • Unmarked as answer by JenCarlos Tuesday, September 6, 2016 4:21 PM
    • Marked as answer by JenCarlos Tuesday, September 6, 2016 4:21 PM
    • Edited by Mr. Monkeyboy Wednesday, September 7, 2016 2:12 AM
    Tuesday, September 6, 2016 8:48 AM
  • Thanks you
    • Edited by JenCarlos Tuesday, September 6, 2016 4:20 PM
    Tuesday, September 6, 2016 4:20 PM
  • Thanks you
    Tuesday, September 6, 2016 4:21 PM