【问题标题】:Implementation of IContextMenu COM interface using JNA使用 JNA 实现 IContextMenu COM 接口
【发布时间】:2020-12-13 11:55:55
【问题描述】:

我需要 Windows 资源管理器外壳菜单中的所有项目。我正在用 jna 实现 IShellFolder COM 对象接口。但是现在我在实现用于查询上下文菜单的接口 IContextMenu 时遇到了问题。当我调用 QueryContextMenu 函数时,HResult 的结果为 0,如 true,但当我调用函数 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, 0, 3);

        return new IContextMenu() {
            @Override
            public WinNT.HRESULT QueryContextMenu(WinDef.HMENU hMenu, int indexMenu, int idCmdFirst, int idCmdLast, 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 uType, IntByReference pReserved, WTypes.LPSTR pszName, int cchMax) {
                Function f = Function.getFunction(vTable[0], Function.ALT_CONVENTION);
                return new WinNT.HRESULT(f.invokeInt(new Object[] { interfacePointer, 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, 0, 1, 30, 0x00000004);
if (!COMUtils.SUCCEEDED(hResult)) {
   int error = Native.getLastError();
   return false;
}

int count = User32Ex.INSTANCE.GetMenuItemCount(hMenu.getPointer());
if (count > 0) {
}

/* End Section */

【问题讨论】:

    标签: java winapi com jna vtable


    【解决方案1】:

    您可能没有从IContextMenuVtbl 中读到您的想法。此代码表明您只收集 3 个函数指针:

    final Pointer[] vTable = new Pointer[3];
    vTablePointer.read(0, vTable, 0, 3);
    

    然而,这个接口(与大多数 COM 接口一样)扩展了 IUnknown,因此会自动获取索引 0 处的方法 QueryInterface、索引 1 处的 AddRef 和索引 2 处的 Release。所以这三个您似乎正在调用的方法,尽管参数错误。

    the header file,指针索引继续:

    • 3:QueryContextMenu
    • 4:InvokeCommand
    • 5:GetCommandString

    您可以读取所有 6 个函数指针并引用最后 3 个,或者尝试使用现有编号读取 3 个指针的偏移量(但顺序相反!)

    我相信您还应该在接口定义中添加extends IUnknown

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多