VBA窗体文本框调用InsertMenuItem创建右键菜单报错87如何解决
问题根源
你遇到的错误码87(参数无效)完全是由MENUITEMINFO结构体定义错误导致的内存布局不匹配,Windows API无法识别你传入的结构体内容,核心错误有三点:
hbmpItem成员错误声明为Variant类型,标准结构中该成员为指针类型,内存长度完全不匹配dwTypeData成员错误声明为变长字符串,变长字符串在结构体中仅存储指针,未初始化时会指向无效内存地址- 结构体初始化未清空垃圾值,可能导致API读取到无效参数
修复方案
第一步:修正API、常量和结构体定义
要同时兼容32位和64位Office,使用如下定义:
#If VBA7 Then ' 64位/32位VBA7兼容声明 Private Declare PtrSafe Sub ZeroMemory Lib "kernel32.dll" Alias "RtlZeroMemory" (ByRef Destination As Any, ByVal Length As LongPtr) Private Declare PtrSafe Function InsertMenuItemA Lib "user32.dll" (ByVal hMenu As LongPtr, ByVal uItem As Long, ByVal fByPosition As Long, ByRef lpmii As MENUITEMINFO) As Long Private Const MAX_MENU_STRING_LENGTH As Long = 256 Private Type MENUITEMINFO cbSize As Long fMask As Long fType As Long fState As Long wID As Long hSubMenu As LongPtr hbmpChecked As LongPtr hbmpUnchecked As LongPtr dwItemData As LongPtr dwTypeData As String * MAX_MENU_STRING_LENGTH cch As Long hbmpItem As LongPtr End Type #Else ' 旧版32位VBA兼容声明 Private Declare Sub ZeroMemory Lib "kernel32.dll" Alias "RtlZeroMemory" (ByRef Destination As Any, ByVal Length As Long) Private Declare Function InsertMenuItemA Lib "user32.dll" (ByVal hMenu As Long, ByVal uItem As Long, ByVal fByPosition As Long, ByRef lpmii As MENUITEMINFO) As Long Private Const MAX_MENU_STRING_LENGTH As Long = 256 Private Type MENUITEMINFO cbSize As Long fMask As Long fType As Long fState As Long wID As Long hSubMenu As Long hbmpChecked As Long hbmpUnchecked As Long dwItemData As Long dwTypeData As String * MAX_MENU_STRING_LENGTH cch As Long hbmpItem As Long End Type #End If ' 必要常量定义 Private Const MIIM_FTYPE As Long = &H100 Private Const MFT_SEPARATOR As Long = &H800
第二步:修正调用代码
初始化结构体前先清空内存,避免垃圾值影响:
Dim oMenuItemInfo4 As MENUITEMINFO ' 先清空结构体内存 ZeroMemory oMenuItemInfo4, LenB(oMenuItemInfo4) With oMenuItemInfo4 .cbSize = Len(oMenuItemInfo4) .fMask = MIIM_FTYPE .fType = MFT_SEPARATOR End With Dim ff As Long, fg As Long ff = InsertMenuItemA(menu_hwnd, 0, True, oMenuItemInfo4) fg = Err.LastDllError
修改后即可正常创建分隔符菜单项,后续如果要添加普通文本菜单项,只需给dwTypeData赋值菜单文本,同时把cch设为文本长度,fMask加上MIIM_ID和MIIM_STRING参数即可。
内容的提问来源于stack exchange,提问作者IIyx
相关产品推荐
相关产品推荐

