如何解决使用JNA实现IContextMenu COM接口
我需要Windows资源管理器命令行管理程序中的所有项目。我正在用jna实现IShellFolder COM对象接口。但是现在我在实现用于查询上下文菜单的接口IContextMenu时遇到问题。当我调用QueryContextMenu函数时,HResult的结果像真实的一样为0,但是当我调用函数GetMenuItemCount时,HMenu为空,结果为0。
那么你能告诉我我哪里有错误。非常感谢。
这是我的IContextMenu代码:
public interface IContextMenu {
Guid.IID IID_IContextMenu = new Guid.IID("{000214E4-0000-0000-C000-000000000046}");
WinNT.HRESULT QueryContextMenu(WinDef.HMENU hMenu,int indexMenu,int idCmdFirst,int idCmdLast,int uFlags);
WinNT.HRESULT InvokeCommand(Pointer pici);
WinNT.HRESULT GetCommandString(IntByReference idCmd,int uType,IntByReference pReserved,WTypes.LPSTR pszName,int cchMax);
public static class Converter {
public Converter() {
}
public static IContextMenu PointerToIContextMenu(PointerByReference ptr) {
final Pointer interfacePointer = ptr.getValue();
final Pointer vTablePointer = interfacePointer.getPointer(0);
final Pointer[] vTable = new Pointer[3];
vTablePointer.read(0,vTable,3);
return new IContextMenu() {
@Override
public WinNT.HRESULT QueryContextMenu(WinDef.HMENU hMenu,int uFlags) {
Function f = Function.getFunction(vTable[2],Function.ALT_CONVENTION);
return new WinNT.HRESULT(f.invokeInt(new Object[] { interfacePointer,hMenu.getPointer(),indexMenu,idCmdFirst,idCmdLast,uFlags }));
}
@Override
public WinNT.HRESULT InvokeCommand(Pointer pici) {
Function f = Function.getFunction(vTable[1],Function.ALT_CONVENTION);
return new WinNT.HRESULT(f.invokeInt(new Object[]{ interfacePointer,pici }));
}
@Override
public WinNT.HRESULT GetCommandString(IntByReference idCmd,int cchMax) {
Function f = Function.getFunction(vTable[0],idCmd,uType,pReserved,pszName,cchMax }));
}
};
}
}
}
这是我调用QueryContextMenu的代码:
IContextMenu contextMenu = null;
PointerByReference contextMenuPtr = new PointerByReference();
Pointer ppidlsPointer = new Memory(Native.POINTER_SIZE * ppidls.length);
ppidlsPointer.setPointer(0,ppidls[0].getValue());
hResult = psfParentFolder.GetUIObjectOf(null,1,ppidls[0].getPointer(),new Guid.REFIID(IContextMenu.IID_IContextMenu),new IntByReference(0),contextMenuPtr);
if (!COMUtils.SUCCEEDED(hResult))
return false;
/* End Section */
/* Begin Get Context Menu Section */
contextMenu = IContextMenu.Converter.PointerToIContextMenu(contextMenuPtr);
WinDef.HMENU hMenu = User32Ex.INSTANCE.CreatePopupMenu();
hResult = contextMenu.QueryContextMenu(hMenu,30,0x00000004);
if (!COMUtils.SUCCEEDED(hResult)) {
int error = Native.getLastError();
return false;
}
int count = User32Ex.INSTANCE.GetMenuItemCount(hMenu.getPointer());
if (count > 0) {
}
/* End Section */
解决方法
您可能没有从IContextMenuVtbl
中读取您的想法。此代码表明您仅收集3个函数指针:
final Pointer[] vTable = new Pointer[3];
vTablePointer.read(0,vTable,3);
但是,此接口(与大多数COM接口一样)扩展了IUnknown
,因此自动在索引0处获取方法QueryInterface
,在索引1处获取方法AddRef
,在索引1处获取方法Release
索引2。这就是您似乎正在调用的三个方法,尽管参数错误。
从the header file开始,指针索引继续:
- 3:
QueryContextMenu
- 4:
InvokeCommand
- 5:
GetCommandString
您可以全部读入6个函数指针并引用最后3个指针,或者尝试使用现有编号(以相反的顺序)以3个指针的偏移量进行读取
我相信您还应该在界面定义中添加extends IUnknown
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。