NEWS DETAIL

旧版快捷菜单(IContextMenu)实现

发布时间:2026/9/27 7:52:47 · 栏目:资讯中心

尧图网络原创建站知识分享正文
图例文件资源管理器右键菜单 | | V 初始化 IShellExtInit | | 调用 Initialize V 启用 IContextMenu (快捷菜单拓展接口) | | 调用 QueryContextMenu V InsertMenuItem 对象1 - 显示为菜单项1 InsertMenu 对象2 - 显示为菜单项2 (可能是带子菜单的项) | | 调用 InvokeCommand V 执行命令IShellExtInit的实现/** [in] pidlFolder 类型 PCIDLIST_ABSOLUTE 指向唯一标识文件夹的 ITEMIDLIST 结构的指针。 对于属性表扩展此参数为 NULL。 对于快捷菜单扩展它是包含要显示其快捷菜单的项的文件夹的项目标识符列表。 对于非默认拖放菜单扩展此参数指定目标文件夹。 [in] pdtobj 类型 IDataObject* 指向 IDataObject 接口对象的指针该对象可用于检索正在执行操作的对象。 [in] hkeyProgID 类型 HKEY 文件对象或文件夹类型的注册表项。 */ HRESULT Initialize( _In_ PCIDLIST_ABSOLUTE pidlFolder, _In_ IDataObject* pdtobj, _In_ HKEY hkeyProgID );案例private: std::vectorstd::wstring m_selectedFiles; std::wstring m_folderPath; public: STDMETHOD(Initialize)( _In_ PCIDLIST_ABSOLUTE pidlFolder, _In_ IDataObject* pdtobj, _In_ HKEY hkeyProgID )override{ // 获取文件夹folderPath TCHAR szFolderPath[MAX_PATH] { 0 }; if (pidlFolder ! NULL) { if (SHGetPathFromIDListW(pidlFolder, szFolderPath)) { // szFolderPath 现在包含文件夹的完整路径 // 例如C:\Users\Username\Documents m_folderPath szFolderPath; } } // 获取选中的文件 if (pdtobj) { FORMATETC fmt { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; STGMEDIUM stg { 0 }; if (SUCCEEDED(pdtobj-GetData(fmt, stg))) { HDROP hDrop (HDROP)GlobalLock(stg.hGlobal); if (hDrop) { UINT nFiles DragQueryFileW(hDrop, 0xFFFFFFFF, NULL, 0); for (UINT i 0; i nFiles; i) { wchar_t szFile[MAX_PATH]; if (DragQueryFileW(hDrop, i, szFile, MAX_PATH)) { m_selectedFiles.push_back(szFile); } } GlobalUnlock(stg.hGlobal); } ReleaseStgMedium(stg); } } return S_OK; }IContextMenu的实现方法声明STDMETHOD(QueryContextMenu)(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) override; STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO pici) override; STDMETHOD(GetCommandString)(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax) override;/// summary /// 获取有关快捷菜单命令的信息包括命令的帮助字符串和与语言无关或 规范的名称。 /// /summary /// param nameidCmd菜单命令标识符偏移量/param /// param nameuType指定要返回的信息的标志。 /param /// param namepReserved保留。 应用程序在调用此方法时必须指定 NULL 处理程序在调用时必须忽略此参数。/param /// param namepszName要接收正在检索的以 null 结尾的字符串的缓冲区的地址。/param /// param namecchMax要接收以 null 结尾的字符串的缓冲区的大小以字符为单位。/param /// returnsS_OK/returns HRESULT GetCommandString( UINT_PTR idCmd, UINT uType, UINT* pReserved, CHAR* pszName, UINT cchMax ); /// summary /// 执行与快捷菜单项关联的命令。 /// /summary /// param namepici指向 CMINVOKECOMMANDINFO 或 CMINVOKECOMMANDINFOEX 结构的指针该结构包含有关命令的详细信息。/param /// returnsS_OK/returns HRESULT InvokeCommand( CMINVOKECOMMANDINFO* pici ); /// summary /// 将命令添加到快捷菜单。 /// /summary /// param namehmenu快捷菜单的句柄。 添加菜单项时处理程序应指定此句柄。/param /// param nameindexMenu要插入第一个新菜单项的从零开始的位置。/param /// param nameidCmdFirst处理程序可以为菜单项标识符指定的最小值。/param /// param nameidCmdLast处理程序可以为菜单项标识符指定的最大值。/param /// param nameuFlags指定如何更改快捷菜单的可选标志。 可多选/param /// returnsS_OK/returns HRESULT QueryContextMenu( HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags );QueryContextMenu/// summary /// 将程序菜单添加到快捷菜单。 /// /summary /// param namehmenu快捷菜单的句柄。 添加菜单项时处理程序应指定此句柄。/param /// param nameindexMenu 定位参数要插入第一个新菜单项的从零开始的位置。 /// 定位菜单程序总快捷菜单中的位置0为首-1为末 /// /param /// param nameidCmdFirst第一个命令ID处理程序可以为菜单项标识符指定的最小值。/param /// param nameidCmdLast最后一个命令ID处理程序可以为菜单项标识符指定的最大值。/param /// param nameuFlags指定如何更改快捷菜单的可选标志。 可多选 // uFlags 简要说明 // CMF_DEFAULTONLY : (最重要!) 用户意图为双击/回车执行默认操作而非打开菜单。应立即返回不添加任何项。 // CMF_EXTENDEDVERBS : 通常由 Shift右键 触发应显示高级/扩展菜单项。 // CMF_VERBSONLY : 通常来自“发送到”菜单应仅添加核心操作命令避免分隔符等。 // CMF_EXPLORE : 菜单在资源管理器窗口内弹出而非桌面或对话框。 // CMF_CANRENAME : 当前选择项支持重命名操作通常为单个对象。 // CMF_ASYNCVERBSTATE : 允许异步计算菜单项状态启用/禁用用于避免耗时操作阻塞菜单弹出。 // CMF_DISABLEDVERBS : 应显示即使为灰色不可用的菜单项。 // CMF_NORMAL : 无特殊标志常规菜单模式。 // CMF_NODEFAULT : 菜单不应包含默认命令无粗体项。 // CMF_INCLUDESTATIC : (主要用于旧式静态扩展) 应包含静态菜单项。 // CMF_RESERVED : 保留标志应忽略。 /// CMF_NOVERBS × /// CMF_ITEMMENU × /// CMF_OPTIMIZEFORINVOKE × /// CMF_SYNCCASCADEMENU × /// CMF_DONOTPICKDEFAULT × /// /// /param /// returnsS_OK/returns HRESULT QueryContextMenu( HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags );InsertMenu/// summary /// 创建普通菜单并绑定到程序菜单上。 /// /summary /// param namehmenu快捷菜单的句柄。/param /// param nameuPosition由uFlags决定/param /// param nameuFlags /// MF_BYCOMMAND : uPosition为标识符 /// MF_BYPOSITION : uPosition为菜单相对位置 /// MF_BITMAP : lpNewItem包含位图 /// MF_CHECKED : 复选标记 /// MF_DISABLED : 禁用模式(不灰色) /// MF_ENABLED : 启用模式 /// MF_GRAYED : 禁用模式(灰色) /// MF_MENUBARBREAK : 新列通过垂直线与旧列分割 /// MF_MENUBREAK : 新列不分割 /// MF_OWNERDRAW : 自定义菜单lpNewItem /// MF_POPUP : uIDNewItem包含子菜单 /// MF_SEPARATOR : 水平分隔线 /// MF_STRING : lpNewItem是文本字符串 /// MF_UNCHECKED : 取消复选标记 /// /param /// param nameuIDNewItem新菜单项的标识符或子菜单的句柄/param /// param namelpNewItem /// 由uFlags决定 /// 如果uFlags MF_BITMAP : 位图句柄 /// 如果uFlags MF_OWNERDRAW : 自定义菜单参数 /// 如果uFlags MF_STRING : 字符串指针 /// /param BOOL InsertMenuA( HMENU hMenu, UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, LPCSTR lpNewItem );InsertMenuItem/// summary /// 创建普通菜单并绑定到程序菜单上。 /// /summary /// param namehmenu快捷菜单的句柄/param /// param nameitem由fByPosition决定/param /// param namefByPosition /// FALSE : 菜单项标识符 /// TRUE : 菜单项位置 /// /param /// param namelpmi /// 指向 MENUITEMINFOA 结构体 /// /param BOOL InsertMenuItemA( HMENU hmenu, UINT item, BOOL fByPosition, LPCMENUITEMINFOA lpmi );MENUITEMINFO/* UINT cbSize; 结构的大小直接设置为sizeof(MENUITEMINFO) UINT fMask; 配置项 MIIM_BITMAP 开启配置hbmpItem参数 MIIM_CHECKMARKS 开启配置hbmpChecked 和 hbmpUnchecked 参数 MIIM_DATA 开启配置dwItemData 参数 MIIM_FTYPE 开启配置fType 参数 MIIM_ID 开启配置wID 参数 MIIM_STATE 开启配置fState 参数 MIIM_STRING 开启配置dwTypeData 参数 MIIM_SUBMENU 开启配置hSubMenu 参数 MIIM_TYPE 开启配置fType 和 dwTypeData 参数 UINT fType; MFT_BITMAP 启用位图dwTypeData低位为位图句柄 MFT_MENUBARBREAK 垂直线项新列与旧列分开 MFT_MENUBREAK 垂直线项新列不会与旧列分开 MFT_OWNERDRAW 自定义菜单配置dwTypeData值 MFT_RADIOCHECK 由hbmpChecked决定单选按钮 MFT_RIGHTJUSTIFY 右对齐菜单项和任何后续项 MFT_RIGHTORDER 指定菜单从右向左级联 MFT_SEPARATOR 水平分隔线 MFT_STRING 启用文本字符串dwTypeData参数为字符串句柄 UINT fState; MFS_CHECKED 启用hbmpChecked 项 MFS_DEFAULT 指定菜单项为默认值菜单只能包含一个默认菜单项以粗体显示。 MFS_DISABLED 禁用菜单项并将其灰显 MFS_ENABLED 启用菜单项 MFS_GRAYED 禁用菜单项并将其灰显 MFS_HILITE 突出显示菜单项 MFS_UNCHECKED 取消选中菜单项 MFS_UNHILITE 从菜单项中删除突出显示 UINT wID; 标识菜单项的应用程序定义值 HMENU hSubMenu; 下拉菜单或子菜单的句柄可为NULL HBITMAP hbmpChecked; 可选框 HBITMAP hbmpUnchecked; 可选框 ULONG_PTR dwItemData; LPSTR dwTypeData; UINT cch; HBITMAP hbmpItem; HBMMENU_CALLBACK 自定义 HBMMENU_MBAR_CLOSE 菜单栏的“关闭”按钮。 HBMMENU_MBAR_CLOSE_D 菜单栏的“已禁用关闭”按钮。 HBMMENU_MBAR_MINIMIZE 菜单栏的最小化按钮 HBMMENU_MBAR_MINIMIZE_D 已禁用菜单栏的最小化按钮。 HBMMENU_MBAR_RESTORE 菜单栏的“还原”按钮。 HBMMENU_POPUP_CLOSE 子菜单的“关闭”按钮。 HBMMENU_POPUP_MAXIMIZE 子菜单的最大化按钮 HBMMENU_POPUP_MINIMIZE 子菜单的最小化按钮。 HBMMENU_POPUP_RESTORE 子菜单的“还原”按钮。 HBMMENU_SYSTEM dwItemData中指定的窗口的 Windows 图标或图标。 */ typedef struct tagMENUITEMINFOA { UINT cbSize; UINT fMask; UINT fType; UINT fState; UINT wID; HMENU hSubMenu; HBITMAP hbmpChecked; HBITMAP hbmpUnchecked; ULONG_PTR dwItemData; LPSTR dwTypeData; UINT cch; HBITMAP hbmpItem; } MENUITEMINFOA, *LPMENUITEMINFOA;InvokeCommand/// summary /// 执行与快捷菜单项关联的命令。 /// /summary /// param namepici指向 CMINVOKECOMMANDINFO 或 CMINVOKECOMMANDINFOEX 结构的指针该结构包含有关命令的详细信息。/param /// returnsS_OK/returns HRESULT InvokeCommand( CMINVOKECOMMANDINFO* pici );CMINVOKECOMMANDINFO/* DWORD cbSize; 此结构的大小 DWORD fMask; 标志位 CMIC_MASK_HOTKEY 激活dwHotKey参数键盘快捷方式 CMIC_MASK_ICON 激活hIcon参数图标 CMIC_MASK_FLAG_NO_UI 系统无法显示用户界面元素 CMIC_MASK_NO_CONSOLE 禁止创建新控制台 CMIC_MASK_FLAG_SEP_VDM 16 位应用程序时才有效在专用虚拟 DOS 中运行 CMIC_MASK_ASYNCOK 等待 DDE 会话终止然后再返回 CMIC_MASK_NOASYNC CMIC_MASK_SHIFT_DOWN 已按下 SHIFT 键 CMIC_MASK_CONTROL_DOWN 已按下 CTRL 键 CMIC_MASK_FLAG_LOG_USAGE 指示InvokeCommand的实现可能需要跟踪为“最近使用的文档”菜单等功能调用的项。 CMIC_MASK_NOZONECHECKS 不要执行区域检查 HWND hwnd; 父窗口句柄 LPCSTR lpVerb; 命令行为 CMDSTR_RUNAS Runas CMDSTR_PRINT 打印 CMDSTR_PREVIEW 预览 CMDSTR_OPEN 打开 LPCSTR lpParameters; 命令参数 LPCSTR lpDirectory; 工作目录 int nShow; 窗口显示参数 DWORD dwHotKey; 指定键盘快捷方式由fMask的 CMIC_MASK_HOTKEY 控制 HANDLE hIcon; 指定图标由fMask的 CMIC_MASK_ICON 控制 */ typedef struct _CMINVOKECOMMANDINFO { DWORD cbSize; DWORD fMask; HWND hwnd; LPCSTR lpVerb; LPCSTR lpParameters; LPCSTR lpDirectory; int nShow; DWORD dwHotKey; HANDLE hIcon; } CMINVOKECOMMANDINFO;CMINVOKECOMMANDINFOEX/* DWORD cbSize; 此结构的大小 DWORD fMask; 标志位 CMIC_MASK_HOTKEY 激活dwHotKey参数键盘快捷方式 CMIC_MASK_ICON 激活hIcon参数图标 CMIC_MASK_FLAG_NO_UI 系统无法显示用户界面元素 CMIC_MASK_UNICODE 激活Unicode字符串数据包括 lpVerbW、 lpParametersW、 lpDirectoryW 和 lpTitleW 成员 CMIC_MASK_NO_CONSOLE 禁止创建新控制台 CMIC_MASK_HASLINKNAME lpTitle 成员包含快捷方式文件的完整路径 CMIC_MASK_HASTITLE 激活 lpTitle 参数 CMIC_MASK_FLAG_SEP_VDM 16 位应用程序时才有效在专用虚拟 DOS 中运行 CMIC_MASK_ASYNCOK 等待 DDE 会话终止然后再返回 CMIC_MASK_NOASYNC CMIC_MASK_SHIFT_DOWN 已按下 SHIFT 键 CMIC_MASK_CONTROL_DOWN 已按下 CTRL 键 CMIC_MASK_FLAG_LOG_USAGE 指示InvokeCommand的实现可能需要跟踪为“最近使用的文档”菜单等功能调用的项。 CMIC_MASK_NOZONECHECKS 不要执行区域检查 CMIC_MASK_PTINVOKE 激活 ptInvoke 参数 HWND hwnd; 父窗口句柄 LPCSTR lpVerb; 命令行为 CMDSTR_RUNAS Runas CMDSTR_PRINT 打印 CMDSTR_PREVIEW 预览 CMDSTR_OPEN 打开 LPCSTR lpParameters; 命令参数 LPCSTR lpDirectory; 工作目录 int nShow; 窗口显示参数 DWORD dwHotKey; 指定键盘快捷方式由fMask的 CMIC_MASK_HOTKEY 控制 HANDLE hIcon; 指定图标由fMask的 CMIC_MASK_ICON 控制 LPCSTR lpTitle; LPCWSTR lpVerbW; Unicode 谓词 LPCWSTR lpParametersW; Unicode 参数 LPCWSTR lpDirectoryW; Unicode 目录 LPCWSTR lpTitleW; Unicode 标题 POINT ptInvoke; 命令调用点 */ typedef struct _CMINVOKECOMMANDINFOEX { DWORD cbSize; DWORD fMask; HWND hwnd; LPCSTR lpVerb; LPCSTR lpParameters; LPCSTR lpDirectory; int nShow; DWORD dwHotKey; HANDLE hIcon; LPCSTR lpTitle; LPCWSTR lpVerbW; LPCWSTR lpParametersW; LPCWSTR lpDirectoryW; LPCWSTR lpTitleW; POINT ptInvoke; } CMINVOKECOMMANDINFOEX;GetCommandString/** * brief 获取有关快捷菜单命令的信息包括命令的帮助字符串和与语言无关或 规范的名称。 * param idCmd [in]菜单命令标识符偏移量 * param uType [in]指定要返回的信息的标志 * GCS_HELPTEXTA (ANSI)将 pszName 设置为包含命令帮助文本 * GCS_HELPTEXTW (Unicode)将 pszName 设置为包含命令帮助文本 * GCS_VALIDATEA 如果菜单项存在则返回S_OK否则返回S_FALSE。 * GCS_VALIDATEW * GCS_VERBA 将 pszName 设置为包含菜单项与语言无关的命令名称的字符串 * GCS_VERBW * param pReserved 保留。 应用程序在调用此方法时必须指定 NULL 处理程序在调用时必须忽略此参数。 * param pszName [out]要接收正在检索的以 null 结尾的字符串的缓冲区的地址。 * param cchOut [out]要接收以 null 结尾的字符串的缓冲区的大小以字符为单位 * return S_OK * summary * */ HRESULT GetCommandString( UINT_PTR idCmd, UINT uType, UINT* pReserved, CHAR* pszName, UINT cchMax );注册表结构IContextMenu的注册表需求分为两部分一部分是标记拓展组件唯一标识的CLSID key另一部分是注册到右键菜单指定环境的 file_extension Key 如全部文件的* 和AllFilesystemObjects 、DesktopBackground桌面背景目录等详细参考COM注册表项架构。HKCR { file_extension { shell {...} shellex {...} } CLSID { ...ATL项目自动生成 } }参考链接微软文档-IContextMenu (shobjidl_core.h) - Win32 apps | Microsoft Learn微软文档-InsertMenuA 函数 winuser.h - Win32 apps | Microsoft Learn微软文档-InsertMenuItemA 函数 (winuser.h) - Win32 apps | Microsoft Learn微软文档-IContextMenuGetCommandString (shobjidl_core.h) - Win32 apps | Microsoft Learn微软文档-IContextMenuInvokeCommand (shobjidl_core.h) - Win32 apps | Microsoft Learn微软文档-CMINVOKECOMMANDINFO (shobjidl_core.h) - Win32 apps | Microsoft Learn微软文档-CMINVOKECOMMANDINFOEX (shobjidl_core.h) - Win32 apps | Microsoft Learn
✦

本文为尧图网络原创建站知识分享。想针对自身行业获取定制化建站方案?欢迎咨询,资深顾问免费为你出思路。

RELATED

相关 资讯推荐

MORE

更多 新鲜资讯

JMeter入门实战:从零构建HTTP接口性能测试脚本与结果分析
2026/9/27 7:43:30

JMeter入门实战:从零构建HTTP接口性能测试脚本与结果分析

1. 项目概述:从零开始,用JMeter搞定HTTP性能测试 刚接触性能测试的新手,或者是从功能测试转过来的朋友,一听到“压测”两个字,心里可能就有点发怵。工具那么多,概念那么杂,从哪儿下手呢&#xf…

Earendel: 一个纯TS写的POSIX兼容的微内核Web操作系统
2026/9/25 19:05:45

Earendel: 一个纯TS写的POSIX兼容的微内核Web操作系统

最近我用TypeScript写了一个运行在浏览器里的Web操作系统 Earendel(目前已知的距离地球最遥远的恒星)。开发它的初衷主要是为了Linux和操作系统课程的教学。市面上绝大多数Web OS项目,要么只是做了一个长得像Windows/macOS的网页UI拼盘&#…

5分钟掌握Windows防撤回神器:让微信QQ撤回消息无处遁形[特殊字符]
2026/9/25 16:12:04

5分钟掌握Windows防撤回神器:让微信QQ撤回消息无处遁形[特殊字符]

5分钟掌握Windows防撤回神器:让微信QQ撤回消息无处遁形🚀 【免费下载链接】RevokeMsgPatcher :trollface: A hex editor for WeChat/QQ/TIM - PC版微信/QQ/TIM防撤回补丁(我已经看到了,撤回也没用了) 项目地址: http…

从零制作同人动画:技术路线、流程与实战避坑指南
2026/9/26 12:28:39

从零制作同人动画:技术路线、流程与实战避坑指南

1. 先搞清楚这个“粉丝动画”到底是什么,以及它能解决什么问题看到“五条悟VS宿傩/咒术回战粉丝动画”这个标题,很多人的第一反应可能是去找一个现成的视频。但如果你是一个想自己动手创作、或者想了解这类作品背后技术流程的创作者,这个标题…

闭源降价80%,开源却在涨价:AI定价的交叉路口
2026/9/25 16:10:12

闭源降价80%,开源却在涨价:AI定价的交叉路口

8月6日,两条价格曲线悄然交汇。 一条向下:OpenAI把GPT-5.6 Luna的输出价格从6美元砍到1.2美元/百万Token,降幅80%。另一条向上:同一天,DeepSeek公告全线涨价,措辞是"涨幅较大",非试探…

产线三防平板选哪个牌子?5个品牌实测告诉你别瞎买
2026/9/25 20:15:12

产线三防平板选哪个牌子?5个品牌实测告诉你别瞎买

产线三防平板选哪个牌子?5个品牌实测告诉你别瞎买经常有工厂朋友拿着网上的"三防平板十大品牌排行榜"来问我:到底选哪个?说实话排行榜看看就行,真正选型得看你产线什么场景。今天挑五个在产线数字化里用得比较多的品牌—…

看完这篇,还想了解更多?

预约尧图网络顾问一对一沟通,针对你的行业与现状给出建站建议,全程免费。

免费咨询