我有这个mii
变量,它分配一个MenuItemInfo结构来设置(或获取)系统菜单的项目。
Private mii As New MenuItemInfo
<System.Runtime.InteropServices.
StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential,
CharSet:=System.Runtime.InteropServices.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
Public dwTypeData As String
Public cch As Integer
Public hbmpItem As IntPtr
End Structure
当我尝试使用变量来存储使用API函数GetMenuItemInfo
的现有菜单项的信息时,会出现问题,变量不会改变任何内容,所有结构成员仍然为空。
这是API函数(注意Byref
已正确设置)
''' <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>
<System.Runtime.InteropServices.
DllImport("user32.dll")> _
Private Shared Function GetMenuItemInfo(
ByVal hMenu As IntPtr,
ByVal uItem As UInteger,
ByVal fByPosition As Boolean,
ByRef lpmii As MenuItemInfo) As Boolean
End Function
这就是我试图检索点击的菜单项的信息,(请查看里面的评论):
Protected Overrides Sub WndProc(ByRef m As Message)
Select Case m.Msg
Case &H112 ' WM_SYSCOMMAND
mii = New MenuItemInfo
mii.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(mii)
' NOTE:
' MSDN says that I need to put the dwTypeData to a null value,
' if I want to retrieve a TEXT type item so...
mii.dwTypeData = Nothing
' NOTE:
' m.WParam contains the ID of the clicked Item,
' so I use True to set is an Identifier and not a position.
Dim success? As Boolean = _
GetMenuItemInfo(MenuHandle, m.WParam, True, mii)
MsgBox(success) ' Result: True
MsgBox(mii.wID) ' Result: 0 (empty)
MsgBox(mii.dwTypeData) ' Result: (empty)
MsgBox(m.wParam) ' Result: (The expected item ID)
End Select
' Return control to base message handler.
MyBase.WndProc(m)
End Sub
我如何解决这个问题?
更新:
现在我的代码看起来像这样,它检索任何项目的ID,但不检索字符串:
Dim mii As New MenuItemInfo()
mii.cbSize = Marshal.SizeOf(GetType(MenuItemInfo))
mii.fMask = Mask.ID Or Mask.TEXT ' &H40 Or &H2
' mii.fType = ItemType.TEXT ' &H0
Dim success? As Boolean = GetMenuItemInfo(MenuHandle, m.WParam, False, mii)
MsgBox(mii.wID) ' Result: (The Expected ID)
MsgBox(mii.dwTypeData) ' Result: (empty string)
答案 0 :(得分:2)
您必须设置fMask
成员以指定要检索的数据MIIM_STRING | MIIM_ID
(&H40 Or &H2
)以检索文本和ID成员。
检索文本成员需要两个步骤:检索文本长度以分配具有适当长度的String
,然后实际检索文本:
mii = New MenuItemInfo
mii.cbSize = Marshal.SizeOf(GetType(MenuItemInfo))
mii.dwTypeData = Nothing
mii.fMask = Mask.TEXT ' &H40
' Retrieve the text length member
GetMenuItemInfo(MenuHandle, m.wParam, True, mii)
' Account for terminating NUL character and allocate String
mii.cch += 1
mii.dwTypeData = Space(mii.cch)
' Specify MIIM_STRING | MIIM_ID to retrieve both text and ID
mii.fMask = Mask.TEXT Or Mask.ID ' &H40 Or &H2
' Retrieve data
GetMenuItemInfo(MenuHandle, m.wParam, True, mii)
请注意,您必须分配具有适当大小的字符串,并在mii.cch
中指定缓冲区大小。上面的代码使用Strings.Space Method返回由指定数量的空格组成的字符串。这只是为了方便起见,您也可以使用StringBuilder
。
如果您在导入Windows API函数时遇到字符编码问题(看起来像中文字符的文本)。大多数Windows API有两种形式:ANSI和UNICODE分别带有A
和W
后缀。在这种情况下,您应指定GetMenuItemInfoW
。