I just tested on Windows 7 and it worked with an older method, more complicated
The whole test (with a Button for the click) =>
(I let the first method and skipped it with "If False Then...")
I cannot paste it, then a link : VB_IContextMenu_New
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Hello...
What I want is to get the "New" context menu along with its submenus, so that I can use it in an application.
Example:
have searched the internet and there are no good references about this, so I turn to you.
I have tried to do, but could not solve.
Dim CLSID_NewMenu As New Guid("{D969A300-E7FF-11d0-A93B-00A0C90F2719}")
Dim iContextMenuPtr As IntPtr = IntPtr.Zero
Dim pContextMenu As IContextMenu = Nothing
If CoCreateInstance(CLSID_NewMenu, IntPtr.Zero, CLSCTX.INPROC_SERVER, IID_IContextMenu, iContextMenuPtr) = 0 Then
Dim hMenu As IntPtr
pContextMenu = DirectCast(Marshal.GetObjectForIUnknown(iContextMenuPtr), IContextMenu)
hMenu = CreatePopupMenu()
pContextMenu.QueryContextMenu(hMenu, 0, 1, &H7FFF, CMF.NORMAL)
Dim sbMenuItem As StringBuilder = New StringBuilder(260)
GetMenuString(hMenu, 0, sbMenuItem, sbMenuItem.Capacity, MF_BYPOSITION)
MsgBox(sbMenuItem.ToString)
End If
I hope you can help me thanks.
I just tested on Windows 7 and it worked with an older method, more complicated
The whole test (with a Button for the click) =>
(I let the first method and skipped it with "If False Then...")
I cannot paste it, then a link : VB_IContextMenu_New
This works for me (test in C:\Temp folder) =>
Dim sPath As String = "C:\Temp"
Dim pItemIDL As IntPtr = ILCreateFromPath(sPath)
Dim pContextMenu As IContextMenu = Nothing
Dim CLSID_NewMenu As New Guid("D969A300-E7FF-11d0-A93B-00A0C90F2719")
Dim NewMenuType As Type = Type.GetTypeFromCLSID(CLSID_NewMenu, True)
Dim NewMenu As Object = Activator.CreateInstance(NewMenuType)
pContextMenu = DirectCast(NewMenu, IContextMenu)
If pContextMenu IsNot Nothing Then
pContextMenu2 = CType(pContextMenu, IContextMenu2)
Dim hMenu As IntPtr = CreatePopupMenu()
Dim hr As HRESULT = pContextMenu.QueryContextMenu(hMenu, 0, 1, 256, 0)
If (hr = HRESULT.S_OK) Then
Dim psei As IShellExtInit = Nothing
psei = DirectCast(pContextMenu, IShellExtInit)
hr = psei.Initialize(pItemIDL, Nothing, IntPtr.Zero)
If (hr = HRESULT.S_OK) Then
Dim nX As Integer = Cursor.Position.X, nY = Cursor.Position.Y
Dim hPopupMenu As IntPtr = GetSubMenu(hMenu, 0)
Dim nCmd As UInteger = TrackPopupMenu(hPopupMenu, TPM_LEFTALIGN Or TPM_LEFTBUTTON Or TPM_RIGHTBUTTON Or TPM_RETURNCMD, nX, nY, 0, Me.Handle, IntPtr.Zero)
If (nCmd <> 0) Then
Dim cmi As CMINVOKECOMMANDINFO = New CMINVOKECOMMANDINFO()
cmi.cbSize = Marshal.SizeOf(GetType(CMINVOKECOMMANDINFO))
cmi.fMask = 0
cmi.hwnd = Me.Handle
cmi.lpVerb = CType((nCmd - 1), IntPtr)
cmi.lpParameters = IntPtr.Zero
cmi.lpDirectory = IntPtr.Zero
cmi.nShow = SW_SHOWNORMAL
cmi.dwHotKey = 0
cmi.hIcon = IntPtr.Zero
hr = pContextMenu.InvokeCommand(cmi)
End If
pContextMenu2 = Nothing
End If
End If
Marshal.ReleaseComObject(pContextMenu)
DestroyMenu(hMenu)
End If
If (pItemIDL <> IntPtr.Zero) Then ILFree(pItemIDL)
HandleMenuMsg to build the context menu :
Public pContextMenu2 As IContextMenu2 = Nothing
Public Const WM_INITMENUPOPUP As Integer = &H117
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WM_INITMENUPOPUP Then
If pContextMenu2 IsNot Nothing Then pContextMenu2.HandleMenuMsg(CUInt(m.Msg), CInt(m.WParam), m.LParam)
Return
Else
MyBase.WndProc(m)
End If
End Sub
Declarations :
Public Enum HRESULT As Integer
S_OK = 0
S_FALSE = 1
E_NOINTERFACE = &H80004002
E_NOTIMPL = &H80004001
E_FAIL = &H80004005
E_UNEXPECTED = &H8000FFFF
E_OUTOFMEMORY = &H8007000E
End Enum
<DllImport("Shell32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Shared Function ILCreateFromPath(<MarshalAs(UnmanagedType.LPWStr)> pszPath As String) As IntPtr
End Function
<DllImport("Shell32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Shared Sub ILFree(pidl As IntPtr)
End Sub
<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Shared Function CreatePopupMenu() As IntPtr
End Function
<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Shared Function TrackPopupMenu(hMenu As IntPtr, uFlags As UInteger, x As Integer, y As Integer, nReserved As Integer, hWnd As IntPtr, prcRect As IntPtr) As UInteger
End Function
Public Const TPM_LEFTBUTTON As Integer = &H0
Public Const TPM_RIGHTBUTTON As Integer = &H2
Public Const TPM_LEFTALIGN As Integer = &H0
Public Const TPM_CENTERALIGN As Integer = &H4
Public Const TPM_RIGHTALIGN As Integer = &H8
Public Const TPM_TOPALIGN As Integer = &H0
Public Const TPM_VCENTERALIGN As Integer = &H10
Public Const TPM_BOTTOMALIGN As Integer = &H20
Public Const TPM_HORIZONTAL As Integer = &H0
Public Const TPM_VERTICAL As Integer = &H40
Public Const TPM_NONOTIFY As Integer = &H80
Public Const TPM_RETURNCMD As Integer = &H100
Public Const TPM_RECURSE As Integer = &H1
Public Const TPM_HORPOSANIMATION As Integer = &H400
Public Const TPM_HORNEGANIMATION As Integer = &H800
Public Const TPM_VERPOSANIMATION As Integer = &H1000
Public Const TPM_VERNEGANIMATION As Integer = &H2000
Public Const TPM_NOANIMATION As Integer = &H4000
Public Const TPM_LAYOUTRTL As Integer = &H8000
Public Const TPM_WORKAREA As Integer = &H10000
<DllImport("User32.dll", SetLastError:=True)>
Public Shared Function GetSubMenu(hMenu As IntPtr, nPos As Integer) As IntPtr
End Function
<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Shared Function GetMenuItemCount(hMenu As IntPtr) As Integer
End Function
<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Shared Function DestroyMenu(hMenu As IntPtr) As Boolean
End Function
<ComImport>
<Guid("000214e4-0000-0000-c000-000000000046")>
<InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
Interface IContextMenu
Function QueryContextMenu(hmenu As IntPtr, indexMenu As UInteger, idCmdFirst As UInteger, idCmdLast As UInteger, uFlags As UInteger) As HRESULT
<PreserveSig()>
Function InvokeCommand(ByRef pici As CMINVOKECOMMANDINFO) As HRESULT
<PreserveSig()>
Function GetCommandString(idCmd As UInteger, uType As UInteger, pReserved As IntPtr, pszName As StringBuilder, cchMax As UInteger) As HRESULT
End Interface
<ComImport>
<Guid("000214f4-0000-0000-c000-000000000046")>
<InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
Interface IContextMenu2
Inherits IContextMenu
Overloads Function QueryContextMenu(hmenu As IntPtr, indexMenu As UInteger, idCmdFirst As UInteger, idCmdLast As UInteger, uFlags As UInteger) As HRESULT
<PreserveSig()>
Overloads Function InvokeCommand(ByRef pici As CMINVOKECOMMANDINFO) As HRESULT
<PreserveSig()>
Overloads Function GetCommandString(idCmd As UInteger, uType As UInteger, pReserved As IntPtr, pszName As StringBuilder, cchMax As UInteger) As HRESULT
<PreserveSig()>
Function HandleMenuMsg(uMsg As UInteger, wParam As Integer, lParam As IntPtr) As HRESULT
End Interface
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
Public Structure CMINVOKECOMMANDINFO
Public cbSize As Integer
Public fMask As Integer
Public hwnd As IntPtr
Public lpVerb As IntPtr
Public lpParameters As IntPtr
Public lpDirectory As IntPtr
Public nShow As Integer
Public dwHotKey As Integer
Public hIcon As IntPtr
End Structure
Public Const CMF_NORMAL As Integer = &H0
Public Const CMF_DEFAULTONLY As Integer = &H1
Public Const CMF_VERBSONLY As Integer = &H2
Public Const CMF_EXPLORE As Integer = &H4
Public Const CMF_NOVERBS As Integer = &H8
Public Const CMF_CANRENAME As Integer = &H10
Public Const CMF_NODEFAULT As Integer = &H20
Public Const CMF_INCLUDESTATIC As Integer = &H40
Public Const CMF_ITEMMENU As Integer = &H80
Public Const CMF_EXTENDEDVERBS As Integer = &H100
Public Const CMF_DISABLEDVERBS As Integer = &H200
Public Const CMF_ASYNCVERBSTATE As Integer = &H400
Public Const CMF_OPTIMIZEFORINVOKE As Integer = &H800
Public Const CMF_SYNCCASCADEMENU As Integer = &H1000
Public Const CMF_DONOTPICKDEFAULT As Integer = &H2000
Public Const CMF_RESERVED As Integer = &HFFFF0000
Public Const SW_SHOWNORMAL As Integer = 1
Public Const GCS_VERBA As Integer = &H0
Public Const GCS_HELPTEXTA As Integer = &H1
Public Const GCS_VALIDATEA As Integer = &H2
Public Const GCS_VERBW As Integer = &H4
Public Const GCS_HELPTEXTW As Integer = &H5
Public Const GCS_VALIDATEW As Integer = &H6
Public Const GCS_VERBICONW As Integer = &H14
Public Const GCS_UNICODE As Integer = &H4
<ComImport>
<Guid("000214E8-0000-0000-C000-000000000046")>
<InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
Interface IShellExtInit
Function Initialize(pidlFolder As IntPtr, pdtobj As IDataObject, hkeyProgID As IntPtr) As HRESULT
End Interface
Hi @jenCarlos ,
You can try to use ContextMenuStrip Control to implement the "New" context menu along with its submenus.
Add a new ContextMenuStrip control, add menu items to it in design view and implement the function for each menu item.
Then set the form's ContextMenuStrip property.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
MyBase.ContextMenuStrip = ContextMenuStrip1
End Sub
Hope this could be helpful.
Best Regards.
Jiachen Li
----------
If the answer is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.