Java 如何实现Win32宏MAKEINTRESOURCE
您好,您可以帮助实现宏MAKEINTRESOURCEW。查看头文件时,我发现以下内容:Java 如何实现Win32宏MAKEINTRESOURCE,java,winapi,jna,Java,Winapi,Jna,您好,您可以帮助实现宏MAKEINTRESOURCEW。查看头文件时,我发现以下内容: #define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i)))) 我的程序需要此功能,我正在实现IContextMenu功能以查看资源管理器上下文菜单。在我测试的所有项目中,我都可以使用函数GetCommandString获取命令字符串。但是有一项我没有得到命令字符串。并使用记事本++编辑该项。因此,我在文档中发现,在lpverb in结构中,使用
#define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i))))
我的程序需要此功能,我正在实现IContextMenu功能以查看资源管理器上下文菜单。在我测试的所有项目中,我都可以使用函数GetCommandString获取命令字符串。但是有一项我没有得到命令字符串。并使用记事本++编辑该项。因此,我在文档中发现,在lpverb in结构中,使用带有MAKEINTRESOURCE宏的项的id
但现在我不知道如何使用此项的id调用命令并替换此宏
这是我的java代码:
Memory numberVerb = new Memory(Native.POINTER_SIZE);
numberVerb.setLong(0, 109);
CMINVOKECOMMANDINFOEX cmInvokeCommandEx = new CMINVOKECOMMANDINFOEX();
cmInvokeCommandEx.cbSize = cmInvokeCommandEx.size();
cmInvokeCommandEx.fMask = 0x00004000;
cmInvokeCommandEx.hwnd = null;
cmInvokeCommandEx.lpVerbW = new WTypes.LPWSTR(numberVerb);
cmInvokeCommandEx.lpVerb = new WTypes.LPSTR(verb);
cmInvokeCommandEx.lpParameters = null;
cmInvokeCommandEx.lpParametersW = null;
cmInvokeCommandEx.lpDirectory = new WTypes.LPSTR(parentDir.getAbsolutePath());
cmInvokeCommandEx.lpDirectoryW = new WTypes.LPWSTR(parentDir.getAbsolutePath());
cmInvokeCommandEx.nShow = 5;
cmInvokeCommandEx.dwHotKey = 0;
cmInvokeCommandEx.hIcon = Pointer.NULL;
cmInvokeCommandEx.lpTitle = null;
cmInvokeCommandEx.lpTitleW = null;
cmInvokeCommandEx.ptInvoke = point;
cmInvokeCommandEx.write();
hResult = contextMenu2.InvokeCommand(cmInvokeCommandEx.getPointer());
因此,我在文档中发现,在structureCMINVOKECOMMANDINFOEX
中的lpverb
中,使用带有宏MAKEINTRESOURCE
再次仔细阅读文档,您不提供ID,而是提供偏移量:
lpVerb
类型:LPCSTR
以null结尾的字符串的地址,该字符串指定要执行的命令的独立于语言的名称。当应用程序激活命令时,此成员通常是字符串。系统为以下命令字符串提供预定义的常量值
Constant Command string
CMDSTR_RUNAS "RunAs"
CMDSTR_PRINT "Print"
CMDSTR_PREVIEW "Preview"
CMDSTR_OPEN "Open"
常量命令字符串
CMDSTRU运行方式“运行方式”
CMDSTRU打印“打印”
CMDSRU预览“预览”
CMDSTRU打开“打开”
这不是固定的一套;上下文菜单处理程序可以发明新的规范动词,应用程序可以调用它们
如果存在规范谓词,且菜单处理程序未实现规范谓词,则必须返回故障代码,以使下一个处理程序能够处理此谓词。否则将破坏系统中的功能,包括ShellExecute
或者,该参数可以是MAKEINTRESOURCE(offset)
,而不是指针,其中offset
是要执行的命令的菜单标识符offset。实现可以使用is_INTRESOURCE
宏来检测是否使用了该替代方法当用户选择菜单命令时,Shell使用此选项。
因此,当将MAKEINTRESOURCE()
与CMINVOKECOMMANDINFOEX::lpVerb
一起使用时,您不应该提供要调用的菜单项的实际ID(特别是因为您不知道IContextMenu::QueryContextMenu()
为哪个菜单项分配了哪个ID)。您应该提供菜单项的偏移量(其中偏移量的值按类型转换为字符指针-这就是MAKEINTRESOURCE()
所做的)
当您调用IContextMenu::QueryContextMenu()
来设置菜单项时,您可以自己控制这些偏移量。文件中说明了这一点:
IContextMenu
接口由几个Shell扩展处理程序和命名空间扩展导出。它用于向快捷菜单添加命令。当用户选择处理程序或命名空间扩展添加到快捷菜单的命令之一时,Shell将调用该命令的InvokeCommand
方法该命令可以通过调用IContextMenu::QueryContextMenu
时定义的菜单标识符偏移量指定,也可以通过其关联动词指定。应用程序可以通过获取指向对象IContextMenu
接口的指针直接调用此方法。应用程序还可以通过调用ShellExecute
或ShellExecuteEx
并指定命名空间扩展或处理程序支持的谓词来间接调用此方法
因此,当调用每个处理程序的QueryContextMenu()
方法时,必须指定处理程序可以插入其菜单项的HMENU
内的偏移量,以及处理程序可以分配给这些菜单项的ID的最小和最大范围。这样,当稍后通过WM_命令
通知您选择了哪个菜单项ID时,您可以通过将报告的ID与指定的范围进行比较来确定它属于哪个处理程序,找到匹配项后,从报告的ID中减去该处理程序的最小ID,并将结果偏移量传递给该处理程序的InvokeCommand()
方法。或者,您可以使用处理程序的GetCommandString()
方法获取该偏移量处菜单项的动词字符串,然后将该动词字符串传递给InvokeCommand()
仅供参考,
“用记事本++编辑”
是记事本++的IContextMenu::GetCommandString()
实现为该菜单项报告的帮助字符串,因此Windows资源管理器可以显示该文本这一事实意味着记事本++的处理程序工作正常。如果您自己调用GetCommandString()
时无法检索相同的文本,则说明您没有正确使用GetCommandString()
。您应该能够显示和执行每个处理程序的QueryContextMenu()
创建的每个菜单项,就像标准的Windows资源管理器外壳一样。我已经找到了这个问题的解决方案。我正在为此升级我的代码:
result = User32Ex.INSTANCE.GetMenuItemInfoW(hMenu.getPointer(), 4, true, menuiteminfow.getPointer());
if (!result.booleanValue()) {
int errorCode = Native.getLastError();
System.out.println("Error Code: " + errorCode);
return false;
}
CMINVOKECOMMANDINFOEX cmInvokeCommandEx = new CMINVOKECOMMANDINFOEX();
cmInvokeCommandEx.cbSize = cmInvokeCommandEx.size();
cmInvokeCommandEx.fMask = 0x00004000;
cmInvokeCommandEx.hwnd = null;
cmInvokeCommandEx.lpVerbW = new WTypes.LPWSTR(new Pointer(menuiteminfow.wId - 1));
cmInvokeCommandEx.lpVerb = new WTypes.LPSTR(new Pointer(menuiteminfow.wId - 1));
cmInvokeCommandEx.lpParameters = null;
cmInvokeCommandEx.lpParametersW = null;
cmInvokeCommandEx.lpDirectory = new WTypes.LPSTR(parentDir.getAbsolutePath());
cmInvokeCommandEx.lpDirectoryW = new WTypes.LPWSTR(parentDir.getAbsolutePath());
cmInvokeCommandEx.nShow = 5;
cmInvokeCommandEx.dwHotKey = 0;
cmInvokeCommandEx.hIcon = Pointer.NULL;
cmInvokeCommandEx.lpTitle = null;
cmInvokeCommandEx.lpTitleW = null;
cmInvokeCommandEx.ptInvoke = point;
cmInvokeCommandEx.write();
hResult = contextMenu2.InvokeCommand(cmInvokeCommandEx.getPointer());
关键的变化是,如果希望invoke命令抛出id而不是命令,则必须将wId定义为lpVerb变量,而不是lpVerbW或两者。因为lpVerbW仅用于unicode字符串命令。