【问题标题】:How to implement Win32 macro MAKEINTRESOURCE如何实现 Win32 宏 MAKEINTRESOURCE
【发布时间】:2020-09-14 21:04:28
【问题描述】:

您好,您能帮忙实现宏 MAKEINTRESOURCEW。当我查看头文件时,我发现:

#define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i))))

我的程序需要此功能,我正在实现 IContextMenu 功能以查看资源管理器上下文菜单。在我测试过的所有项目中,我都可以使用函数 GetCommandString 获取命令字符串。但在一项中,我没有得到命令字符串。该项目是使用记事本++编辑。所以我在文档中发现,在结构 CMINVOKECOMMANDINFOEX 的 lpverb 中,使用带有宏 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());           

【问题讨论】:

    标签: java winapi jna


    【解决方案1】:

    所以我在文档中发现,在结构 CMINVOKECOMMANDINFOEX 中的 lpverb 中,使用带有宏 MAKEINTRESOURCE 的项目 id

    再次仔细阅读CMINVOKECOMMANDINFOEX 文档,您不提供ID,而是提供OFFSET

    lpVerb

    输入:LPCSTR

    以空字符结尾的字符串的地址,指定要执行的命令的语言无关名称。当应用程序激活命令时,此成员通常是字符串。系统为以下命令字符串提供了预定义的常量值。

    常量命令字符串 CMDSTR_RUNAS "运行方式" CMDSTR_PRINT "打印" CMDSTR_PREVIEW "预览" CMDSTR_OPEN "打开"

    这不是一个固定的集合;上下文菜单处理程序可以发明新的规范动词,应用程序可以调用它们。

    如果存在规范动词并且菜单处理程序未实现规范动词,则它必须返回失败代码以使下一个处理程序能够处理此动词。不这样做会破坏系统中的功能,包括 ShellExecute。

    或者,这个参数可以是MAKEINTRESOURCE(offset),而不是一个指针,其中offset是要执行的命令的菜单标识符偏移量。实现可以使用IS_INTRESOURCE宏来检测到正在使用此替代方法。 当用户选择菜单命令时,Shell 会使用此替代方法。

    因此,当使用 MAKEINTRESOURCE()CMINVOKECOMMANDINFOEX::lpVerb 时,您不应该提供要调用的菜单项的实际 ID(尤其是因为您不知道 @ 分配给哪个菜单项的 ID 987654334@)。您应该提供菜单项的 offset (其中 value 的偏移量按原样类型转换为字符指针 - 这就是@987654335 @ 确实)。

    当您调用IContextMenu::QueryContextMenu() 设置菜单项时,您可以自己控制这些偏移量。这在IContextMenu::InvokeCommand() 文档中有说明:

    IContextMenu 接口由多个 Shell 扩展处理程序和命名空间扩展导出。它用于向快捷菜单添加命令。当用户选择处理程序或命名空间扩展添加到快捷菜单的命令之一时,Shell 调用该命令的InvokeCommand 方法。 该命令可以通过它的菜单标识符偏移量来指定,在调用IContextMenu::QueryContextMenu 时定义,或者通过它的关联动词来指定。 应用程序可以通过获取指向对象的IContextMenu 接口的指针来直接调用此方法.应用程序还可以通过调用 ShellExecuteShellExecuteEx 并指定命名空间扩展或处理程序支持的动词来间接调用此方法。

    因此,当您调用每个处理程序的 QueryContextMenu() 方法时,您必须在自己的 HMENU 内指定处理程序可以插入其菜单项的偏移量,以及处理程序可以分配的最小和最大 ID 范围那些菜单项。这样,当您稍后通过WM_COMMAND 通知您选择了哪个菜单项 ID 时,您可以通过将报告的 ID 与您指定的范围进行比较来确定它属于哪个处理程序,并且当您找到匹配项时减去该处理程序的最小值报告 ID 中的 ID 并将结果偏移量传递给该处理程序的 InvokeCommand() 方法。或者,您可以使用处理程序的GetCommandString() 方法获取该偏移处的菜单项的动词字符串,然后将该动词字符串传递给InvokeCommand()

    仅供参考,"Edit with Notepad++" 是 Notepad++ 的 IContextMenu::GetCommandString() 实现为该菜单项报告的帮助字符串,因此 Windows 资源管理器可以显示该文本的事实意味着 Notepad++ 的处理程序工作得很好。如果您在自己调用GetCommandString() 时无法检索到相同的文本,那么您没有正确使用GetCommandString()。您应该能够显示和执行由每个处理程序的QueryContextMenu() 创建的每个菜单项,就像标准的 Windows Explorer Shell 一样。

    【讨论】:

      【解决方案2】:

      我已经找到了这个问题的解决方案。我正在为此升级我的代码:

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

      关键的变化是,当您希望调用命令抛出 id 而不是命令时,您必须将 wId 定义到 lpVerb 变量而不是 lpVerbW 或两者。因为 lpVerbW 仅适用于 unicode 字符串命令。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-12
        • 1970-01-01
        • 1970-01-01
        • 2010-10-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多