簡體   English   中英

使用 JNA 實現 GetMenuItemInfoW 的參數無效

[英]Invalid parameter implementing GetMenuItemInfoW with JNA

我正在調用 win32 API 函數GetMenuItemInfoW 當我調用該函數時,它返回false ,而Native.getLastError()返回 87:

ERROR_INVALID_PARAMETER 87 (0x57) The parameter is incorrect.

我認為我的錯誤在於我對結構 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);
   }
}

這是我調用函數的代碼:

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);
}

我已經為你的提示編輯了我的代碼,但我得到了同樣的錯誤 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);                                                                                                
}               

這是我的結構的新版本:

@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();                                                                                                                                           
    }                                                                                                                                                          
}

謝謝您的答復。

您可以改進結構映射。

首先, ULONG_PTRWinDef.ULONGByReference ULONG_PTR是一個指針大小的值,但它實際上並不指向任何東西。

JNA 有一個內置的BaseTSD.LONG_PTR類型,你可以在這里使用它。

雖然Pointer技術上適用於hbmpItem和其他位圖字段,但類型WinDef.HBITMAP已在 JNA 中定義,因此您應該使用該映射。

最后,也是您錯誤的可能原因, dwTypeData接收一個字符串,但它是您需要分配和填充的緩沖區。 來自MENUITEMINFO文檔:

要檢索MFT_STRING類型的菜單項,首先通過將MENUITEMINFOdwTypeData成員設置為NULL然后調用GetMenuItemInfo來查找字符串的大小。 cch+1的值是需要的大小。 然后分配此大小的緩沖區,指針放置在緩沖dwTypeData ,增量cch ,並調用GetMenuItemInfo再次以填補該字符串的緩沖區。

因此,在這種情況下,你要映射PointerdwTypeData ,調用函數在第一時間與指針設置為Pointer.NULL ,然后根據遞增它alloating內存cch

menuiteminfow.cch++; 
// allocate 2 bytes per widechar
menuiteminfow.dwTypeData = new Memory(cch * 2);

您可以在使用menuiteminfow.dwTypeData.getWideString()函數調用后從那里獲取字符串。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM