简体   繁体   English

使用 JNA 实现 GetMenuItemInfoW 的参数无效

[英]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_PTRWinDef.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 the dwTypeData member of MENUITEMINFO to NULL and then calling GetMenuItemInfo .要检索MFT_STRING类型的菜单项,首先通过将MENUITEMINFOdwTypeData成员设置为NULL然后调用GetMenuItemInfo来查找字符串的大小。 The value of cch+1 is the size needed. cch+1的值是需要的大小。 Then allocate a buffer of this size, place the pointer to the buffer in dwTypeData , increment cch , and call GetMenuItemInfo 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 :因此,在这种情况下,你要映射PointerdwTypeData ,调用函数在第一时间与指针设置为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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM