P/Invoke代碼不正確 ...它看起來是從VB 6源複製的,並且VB 6中的等效名稱的數據類型與VB.NET中的語義含義有很大不同。
另外,句柄/指針是使用固定整數類型聲明的,它在64位環境下無法正常工作。應始終使用專門爲此目的設計的IntPtr
類型聲明這些類型的值。
而且,指向結構的指針需要在VB.NET中傳遞ByRef
。你不能通過他們ByVal
。您需要使用System.Runtime.InteropServices
namespace和.NET編組中的工具來幫助您。
這是你不應該複製和粘貼你在網上找到的代碼而不理解它的意義和作用的另一個原因。
的聲明應該是這樣的:
Imports System.Runtime.InteropServices
Public NotInheritable Class NativeMethods
Public Const MIIM_STATE As Integer = &H1
Public Const MIIM_ID As Integer = &H2
Public Const MIIM_STRING As Integer = &H40
Public Const MIIM_BITMAP As Integer = &H80
Public Const MIIM_FTYPE As Integer = &H100
Public Const MFT_STRING As Integer = &H0
Public Const MFS_ENABLED As Integer = &H0
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Public Structure MENUITEMINFO
Public cbSize As Integer
Public fMask As Integer
Public fType As Integer
Public fState As Integer
Public wID As Integer
Public hSubMenu As IntPtr
Public hbmpChecked As IntPtr
Public hbmpUnchecked As IntPtr
Public dwItemData As IntPtr
<MarshalAs(UnmanagedType.LPTStr)> Public dwTypeData As String
Public cch As Integer
Public hbmpItem As IntPtr
End Structure
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=False)> _
Public Shared Function GetMenu(ByVal hWnd As IntPtr) As IntPtr
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Public Shared Function GetMenuItemCount(ByVal hMenu As IntPtr) As Integer
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=False)> _
Public Shared Function GetSubMenu(ByVal hMenu As IntPtr, ByVal nPos As Integer) As IntPtr
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Public Shared Function InsertMenuItem(ByVal hMenu As IntPtr,
ByVal uItem As Integer,
<MarshalAs(UnmanagedType.Bool)> fByPosition As Boolean,
ByRef lpmii As MENUITEMINFO) _
As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Public Shared Function DrawMenuBar(ByVal hWnd As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
End Class
然後你就可以使用這樣的功能(重新編寫代碼來匹配):按預期工作
' Get a handle to the menu assigned to a window (in this case, your form)
Dim hMenu As IntPtr = NativeMethods.GetMenu(Me.Handle)
' Get a count of the total items in that menu
Dim menuItemCount As Integer = NativeMethods.GetMenuItemCount(hMenu)
' Get a handle to the sub-menu at index 0
Dim hSubMenu As IntPtr = NativeMethods.GetSubMenu(hMenu, 0)
' Get a count of the total items in that sub-menu
Dim subMenuItemCount As Integer = NativeMethods.GetMenuItemCount(hSubMenu)
' Create and fill in a MENUITEMINFO structure, describing the menu item to add
Dim mii As New NativeMethods.MENUITEMINFO
With mii
.cbSize = Marshal.SizeOf(mii) ' prefer Marshal.SizeOf over the VB 6 Len() function
.fMask = NativeMethods.MIIM_FTYPE Or NativeMethods.MIIM_STATE Or NativeMethods.MIIM_ID Or NativeMethods.MIIM_STRING
.fType = NativeMethods.MFT_STRING
.fState = NativeMethods.MFS_ENABLED
.wID = 0 ' your custom menu item ID here
.hSubMenu = IntPtr.Zero
.hbmpChecked = IntPtr.Zero
.hbmpUnchecked = IntPtr.Zero
.dwItemData = IntPtr.Zero
.dwTypeData = "My Menu Item" ' the name of your custom menu item
End With
' Insert the menu item described by the above structure
' (notice that we're passing the structure by reference in the P/Invoke definition!)
NativeMethods.InsertMenuItem(hSubMenu, subMenuItemCount + 1, True, mii)
' Force an update of the window's menu bar (again, in this case, your form)
NativeMethods.DrawMenuBar(Me.Handle)
一切,至少在同一過程中。請注意,P/Invoke是一個相當困難的話題,您不僅需要深入瞭解VB.NET,還需要Win32 API才能使其正常工作。複製並粘貼您在網上找到的代碼是一個固有風險的提議。大多數時候,這是行不通的。其餘時間,這是一個可能的安全風險。不幸的是,你需要的不僅僅是堆棧溢出的答案,以向你解釋它是如何工作的。
編輯:實際上,上面的代碼也適用於跨進程。無需特別努力。我嘗試用記事本運行實例中的菜單進行操作,並且一切正常。不,我建議這樣做,沒有非常很好的理由...
你使用一個鉤子執行到其他進程的上下文嗎? –
是我的初學者 – sozai