Java 如何实现Win32宏MAKEINTRESOURCE

Java 如何实现Win32宏MAKEINTRESOURCE,java,winapi,jna,Java,Winapi,Jna,您好,您可以帮助实现宏MAKEINTRESOURCEW。查看头文件时,我发现以下内容: #define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i)))) 我的程序需要此功能,我正在实现IContextMenu功能以查看资源管理器上下文菜单。在我测试的所有项目中,我都可以使用函数GetCommandString获取命令字符串。但是有一项我没有得到命令字符串。并使用记事本++编辑该项。因此,我在文档中发现,在lpverb in结构中,使用

您好,您可以帮助实现宏MAKEINTRESOURCEW。查看头文件时,我发现以下内容:

#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());           
因此,我在文档中发现,在structure
CMINVOKECOMMANDINFOEX
中的
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字符串命令。