I am invoking the win32 API function GetMenuItemInfoW
. When I invoke the function I it returns false
, and Native.getLastError()
returns 87:
ERROR_INVALID_PARAMETER 87 (0x57) The parameter is incorrect.
I think that my error is in my implementation of the structure 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:
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
. The ULONG_PTR
is a pointer-sized value, but it does not actually point to anything.
JNA has a built-in BaseTSD.LONG_PTR
type which you could use here.
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.
Finally, and the likely cause of your error, dwTypeData
receives a String, but it is a buffer that you need to allocate and fill. From the MENUITEMINFO docs:
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
. The value ofcch+1
is the size needed. 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.
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
:
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()
.
User contributions licensed under CC BY-SA 3.0