(C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令
(本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢~)
接上一节:(C#)Windows Shell 外壳编程系列3 - 上下文菜单(iContextMenu)(一)右键菜单
上一节说到如何弹出 IShellFolder 的上下文菜单,也就是 IContextMenu。有时候我们需要在这个菜单上面,加入一些属于自己的菜单项。举个例子,你打开资源管理器,查看左边目录树的右键菜单,会发现顶层多了一个折叠/展开的菜单项。好,我们也动手来加入这个菜单项。
修改例子3,我们找到 QueryContextMenu 处,这时候提供了一个菜单句柄:
//提供一个弹出式菜单的句柄
IntPtr contextMenu = API.CreatePopupMenu();
iContextMenu.QueryContextMenu(contextMenu, 0,
API.CMD_FIRST, API.CMD_LAST, CMF.NORMAL | CMF.EXPLORE);然后增加以下代码:
/////////////////////////增加一个自定义菜单
string topInvoke = Tree1.SelectedNode.IsExpanded ? "折叠(&A)" : "展开(&A)";
MFT extraFlag = (Tree1.SelectedNode.Nodes.Count > 0) ? 0 : MFT.GRAYED;
API.InsertMenu(contextMenu, 0, MFT.BYPOSITION | extraFlag,
(int)(API.CMD_LAST+1), topInvoke);
//增加分隔线
API.InsertMenu(contextMenu, 1, MFT.BYPOSITION | MFT.SEPARATOR, 0, "-");
//把第一项菜单设置为默认菜单,也就是加粗
API.SetMenuDefaultItem(contextMenu, 0, true);
/////////////////////////这里我们用到了 InsertMenu 这个 API:
[DllImport("user32",
SetLastError = true,
CharSet = CharSet.Auto)]
public static extern bool InsertMenu(
IntPtr hmenu,
uint uPosition,
MFT uflags,
uint uIDNewItem,
[MarshalAs(UnmanagedType.LPTStr)]
string lpNewItem);参数2表示增加菜单项的位置,从0开始。
参数3表示flag,这里提供了菜单状态,以及位置的计算方法,它是一个枚举:
public enum MFTMF_BYPOSITION 表示位置的计算方法是使用索引项,第一个菜单就是0,第二个菜单就是1,如此类推...
参数4表示命令值。我们可以根据这个命令值来执行对应的功能。
然后就可以弹出菜单了:
//弹出菜单
uint cmd = API.TrackPopupMenuEx(contextMenu,TPM.RETURNCMD,
MousePosition.X, MousePosition.Y, this.Handle, IntPtr.Zero);可以看到弹出菜单的效果。当然,我们还必须做点事情来响应这个菜单的执行:
//获取命令序号,执行菜单命令
if (cmd >= API.CMD_FIRST)
{


//自定义菜单命令
if (cmd == API.CMD_LAST + 1)
{
if (Tree1.SelectedNode.IsExpanded)
Tree1.SelectedNode.Collapse();
else
Tree1.SelectedNode.Expand();
}
}如图:

执行菜单命令
能不能不弹出菜单直接调用菜单项相应的命令?答案是肯定的。
大家还记得怎么显示一个文件或文件夹的属性对话框吗?
Yes,用ShellExecuteEx并指定SHELLEXECUTEINFO的lpVerb域为properties就可,但是这种方法只能查看一个文件的属性,怎么同时查看多个的?
要知道ShellExecuteEx查看文件属性最终也是靠IContextMenu帮忙的,所以答案还是在IContextMenu上,我们只要在调用GetUIObjectOf时把想查看的文件或文件件的PIDL做为参数传进去,然后直接调用InvokeCommand方法就OK啦。
当然,我们做的例子,还是弹出一个对象的属性,靠你自己修改了。
我们必须先得到 IContextMenu 接口:
//得到 IContextMenu 接口
IntPtr iContextMenuPtr = IntPtr.Zero;
iContextMenuPtr = IParent.GetUIObjectOf(IntPtr.Zero, (uint)pidls.Length,
pidls, ref Guids.IID_IContextMenu, out iContextMenuPtr);
IContextMenu iContextMenu = (IContextMenu)Marshal.GetObjectForIUnknown(iContextMenuPtr);但我们不弹出这个菜单,仅仅是调用 InvokeCommand 来执行命令而已:
//直接执行命令
CMINVOKECOMMANDINFOEX invoke = new CMINVOKECOMMANDINFOEX();
invoke.cbSize = Marshal.SizeOf(typeof(CMINVOKECOMMANDINFOEX));
invoke.lpVerb = Marshal.StringToHGlobalAnsi("properties");
invoke.lpDirectory = string.Empty;
invoke.fMask = 0;
invoke.nShow = 1;
iContextMenu.InvokeCommand(ref invoke);关于verb的更多信息请参考MSDN。我这里做的是执行“属性”,如果你要执行其他命令,或者按照索引来执行,也是可以的。这里不做深入研究。

源代码:/Files/lemony/WinShell4.rar
我正在考虑下一节是讲图标,还是继续讲iContextMenu。大家也知道,某个文件的右键菜单里面,往往会有几个 winrar 的选项,还带着可爱的图标。

很有可能下一节就讲述如何在C#中也实现这样的效果哦。希望大家多多支持^_^。
(C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令的更多相关文章
- (C#)Windows Shell 外壳编程系列3 - 上下文菜单(iContextMenu)(一)右键菜单
(本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一节:(C#)Windows Shell 外壳编程系列2 - 解释,从“桌面”开始展开 这里解释上一节中获取名称的方法 GetD ...
- (C#)Windows Shell 外壳编程系列5 - 获取图标
(本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一节:(C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令 有 ...
- (C#)Windows Shell 外壳编程系列7 - ContextMenu 注册文件右键菜单
原文 (C#)Windows Shell 外壳编程系列7 - ContextMenu 注册文件右键菜单 (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一节:(C#)Windo ...
- (C#)Windows Shell 外壳编程系列2 - 解释,从“桌面”开始展开
(本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一篇:(C#)Windows Shell 外壳编程系列1 - 基础,浏览一个文件夹 让我们详细解释一下 Shell 编程中最基本 ...
- (C#)Windows Shell 外壳编程系列8 - 同后缀名不同图标?
原文 (C#)Windows Shell 外壳编程系列8 - 同后缀名不同图标? (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一节:(C#)Windows Shell 外壳 ...
- (C#)Windows Shell 外壳编程系列9 - QueryInfo 扩展提示
原文 (C#)Windows Shell 外壳编程系列9 - QueryInfo 扩展提示 (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一节:(C#)Windows She ...
- (C#)Windows Shell 外壳编程系列6 - 执行
原文(C#)Windows Shell 外壳编程系列6 - 执行 (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一节:(C#)Windows Shell 外壳编程系列5 - ...
- (C#)Windows Shell 外壳编程系列1 - 基础,浏览一个文件夹
1 - 基础,浏览一个文件夹 我们知道,在win32中是以外壳名字空间的形式来组织文件系统的,在外壳名字空间里的每一个对象(注)都实现了一个IShellFolder的接口,通过这个接口我们可以直接查询 ...
- (C#)Windows Shell 编程系列3 - 上下文菜单(iContextMenu)(一)右键菜单
原文 (C#)Windows Shell 编程系列3 - 上下文菜单(iContextMenu)(一)右键菜单 接上一节:(C#)Windows Shell 编程系列2 - 解释,从“桌面”开始展开这 ...
随机推荐
- Android摄像头测量尺(Advanced Ruler Pro)使用方法
http://www.cnblogs.com/sinojelly/archive/2010/08/13/1799341.html Advanced Ruler Pro是一个Android手机应用程序, ...
- android 加固防止反编译-重新打包
http://blog.csdn.net/u010921385/article/details/52505094 1.需要加密的Apk(源Apk) 2.壳程序Apk(负责解密Apk工作) 3.加密工具 ...
- valn 配置
内核修改: /device drivers/Network device support/MAC-VLAN support 1.创建目录和文件#cd /usr#mkdir vlan#cd vlan#c ...
- 【Flask】sqlalchemy 排序
### 排序:1. order_by:可以指定根据这个表中的某个字段进行排序,如果在前面加了一个-,代表的是降序排序.2. 在模型定义的时候指定默认排序:有些时候,不想每次在查询的时候都指定排序的方式 ...
- Django---Blog系统开发之注册页面(验证码&ajax发送文件)
前端页面及渲染: 静态文件的配置:setting.py: static 文件放在app下 STATIC_URL = '/static/' STATIC_ROOT = ( os.path.join(BA ...
- 主攻ASP.NET.4.5.1 MVC5.0之重生:系统角色与权限(一)
数据结构 权限分配 1.在项目中新建文件夹Helpers 2.在HR.Helpers文件夹下添加EnumMoudle.Cs namespace HR.Helpers { public enum Enu ...
- linux 安装tomcat7
wget http://mirror.bit.edu.cn/apache/tomcat/tomcat-7/v7.0.81/bin/apache-tomcat-7.0.81.tar.gz 解压安装包 t ...
- 【codevs3012+codevs3037】线段覆盖4+线段覆盖5(DP)
线段覆盖4网址:http://codevs.cn/problem/3012/ 线段覆盖5网址:http://codevs.cn/problem/3037/ 题目大意:给出一条直线上的一坨线段,每条线段 ...
- json对象与字符串互转方法
字符串转json对象: var data = eval( '(' + str + ')' ); json对象转字符串: var jsonStr = JSON.stringify( obj );
- POJ 3667 & HDU 3308 & HDU 3397 线段树的区间合并
看到讲课安排上 线段树有一节课"区间合并" 我是迷茫的 因为并没有见过 然后了解了一下题目 发现以前写过 还是很麻烦的树链剖分 大概是 解决带修改的区间查询"连续问题&q ...