[英]Invalid parameter implementing GetMenuItemInfoW with JNA
I am invoking the win32 API function GetMenuItemInfoW
.我正在调用 win32 API 函数
GetMenuItemInfoW
。 When I invoke the function I it returns false
, and Native.getLastError()
returns 87:当我调用该函数时,它返回
false
,而Native.getLastError()
返回 87:
ERROR_INVALID_PARAMETER 87 (0x57) The parameter is incorrect.
I think that my error is in my implementation of the structure MenuItemInfoW:我认为我的错误在于我对结构 MenuItemInfoW 的实现:
@Structure.FieldOrder({"cbSize", "fMask", "fType", "fState", "wId", "hSubMenu", "hBmpChecked", "hBmpUnchecked", "dwItemData", "dwTypeData", "cch", "hbmpItem"})
public class MENUITEMINFOW extends Structure {
public int cbSize;
public int fMask;
public int fType;
public int fState;
public int wId;
public Pointer hSubMenu;
public Pointer hBmpChecked;
public Pointer hBmpUnchecked;
public WinDef.ULONGByReference dwItemData;
public WString dwTypeData;
public int cch;
public Pointer hbmpItem;
public MENUITEMINFOW() {
super();
}
public MENUITEMINFOW(Pointer pointer) {
super(pointer);
}
}
And this is my code for invoking the function:这是我调用函数的代码:
MENUITEMINFOW menuiteminfow = new MENUITEMINFOW();
menuiteminfow.fMask = 0x00000040 | 0x00000080 | 0x00000004 | 0x00000002;
menuiteminfow.fType = 0x00000000;
menuiteminfow.cch = 256;
menuiteminfow.dwTypeData = new WString(String.join("", Collections.nCopies(256, " ")));
menuiteminfow.cbSize = Native.getNativeSize(menuiteminfow.getClass());
WinDef.BOOL result = User32Ex.INSTANCE.GetMenuItemInfoW(hMenu.getPointer(), 0, true, menuiteminfow.getPointer());
if (!result.booleanValue()) {
int errorCode = Native.getLastError();
System.out.println("Error Code: " + errorCode);
}
I have edited my editing my code for your tip, but I get the same error 87. This is my new code:我已经为你的提示编辑了我的代码,但我得到了同样的错误 87。这是我的新代码:
MENUITEMINFOW menuiteminfow = new MENUITEMINFOW();
menuiteminfow.fMask = 0x00000040 | 0x00000080 | 0x00000004 | 0x00000002;
menuiteminfow.fType = 0x00000000;
menuiteminfow.cch = 0;
menuiteminfow.dwTypeData = Pointer.NULL;
menuiteminfow.cbSize = Native.getNativeSize(menuiteminfow.getClass());
WinDef.BOOL result = User32Ex.INSTANCE.GetMenuItemInfoW(hMenu.getPointer(),
new WinDef.UINT(0), new WinDef.BOOL(true), menuiteminfow.getPointer());
if (!result.booleanValue()) {
int errorCode = Native.getLastError();
System.out.println("Error Code: " + errorCode);
}
And this is new version of my structure:这是我的结构的新版本:
@Structure.FieldOrder({"cbSize", "fMask", "fType", "fState", "wId", "hSubMenu", "hBmpChecked", "hBmpUnchecked", "dwItemData", "dwTypeData", "cch", "hbmpItem"})
public class MENUITEMINFOW extends Structure {
public int cbSize;
public int fMask;
public int fType;
public int fState;
public int wId;
public Pointer hSubMenu;
public Pointer hBmpChecked;
public Pointer hBmpUnchecked;
public BaseTSD.LONG_PTR dwItemData;
public Pointer dwTypeData;
public int cch;
public WinDef.HBITMAP hbmpItem;
public MENUITEMINFOW() {
super();
}
public MENUITEMINFOW(Pointer pointer) {
super(pointer);
this.read();
}
}
Thank you for your response.谢谢您的答复。
Your structure mapping can be improved.您可以改进结构映射。
First, a ULONG_PTR
is not the same as a WinDef.ULONGByReference
.首先,
ULONG_PTR
与WinDef.ULONGByReference
。 The ULONG_PTR
is a pointer-sized value, but it does not actually point to anything. ULONG_PTR
是一个指针大小的值,但它实际上并不指向任何东西。
JNA has a built-in BaseTSD.LONG_PTR
type which you could use here. JNA 有一个内置的
BaseTSD.LONG_PTR
类型,你可以在这里使用它。
While a Pointer
technically works for hbmpItem
and the other bitmap fields, the type WinDef.HBITMAP
is already defined in JNA so you should use that mapping.虽然
Pointer
技术上适用于hbmpItem
和其他位图字段,但类型WinDef.HBITMAP
已在 JNA 中定义,因此您应该使用该映射。
Finally, and the likely cause of your error, dwTypeData
receives a String, but it is a buffer that you need to allocate and fill.最后,也是您错误的可能原因,
dwTypeData
接收一个字符串,但它是您需要分配和填充的缓冲区。 From the MENUITEMINFO docs:来自MENUITEMINFO文档:
To retrieve a menu item of type
MFT_STRING
, first find the size of the string by setting thedwTypeData
member ofMENUITEMINFO
toNULL
and then callingGetMenuItemInfo
.要检索
MFT_STRING
类型的菜单项,首先通过将MENUITEMINFO
的dwTypeData
成员设置为NULL
然后调用GetMenuItemInfo
来查找字符串的大小。 The value ofcch+1
is the size needed.cch+1
的值是需要的大小。 Then allocate a buffer of this size, place the pointer to the buffer indwTypeData
, incrementcch
, and callGetMenuItemInfo
once again to fill the buffer with the string.然后分配此大小的缓冲区,指针放置在缓冲
dwTypeData
,增量cch
,并调用GetMenuItemInfo
再次以填补该字符串的缓冲区。
So in this case, you'd want to map a Pointer
to dwTypeData
, call the function the first time with that pointer set to Pointer.NULL
, and then alloating memory for it based on incrementing cch
:因此,在这种情况下,你要映射
Pointer
到dwTypeData
,调用函数在第一时间与指针设置为Pointer.NULL
,然后根据递增它alloating内存cch
:
menuiteminfow.cch++;
// allocate 2 bytes per widechar
menuiteminfow.dwTypeData = new Memory(cch * 2);
You can fetch the string from there after the function call with menuiteminfow.dwTypeData.getWideString()
.您可以在使用
menuiteminfow.dwTypeData.getWideString()
函数调用后从那里获取字符串。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.