(本系列文章由柠檬的(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 MFT

MF_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)(二)嵌入菜单和执行命令的更多相关文章

  1. (C#)Windows Shell 外壳编程系列3 - 上下文菜单(iContextMenu)(一)右键菜单

    (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一节:(C#)Windows Shell 外壳编程系列2 - 解释,从“桌面”开始展开 这里解释上一节中获取名称的方法 GetD ...

  2. (C#)Windows Shell 外壳编程系列5 - 获取图标

    (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一节:(C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令 有 ...

  3. (C#)Windows Shell 外壳编程系列7 - ContextMenu 注册文件右键菜单

    原文 (C#)Windows Shell 外壳编程系列7 - ContextMenu 注册文件右键菜单 (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一节:(C#)Windo ...

  4. (C#)Windows Shell 外壳编程系列2 - 解释,从“桌面”开始展开

    (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一篇:(C#)Windows Shell 外壳编程系列1 - 基础,浏览一个文件夹 让我们详细解释一下 Shell 编程中最基本 ...

  5. (C#)Windows Shell 外壳编程系列8 - 同后缀名不同图标?

    原文 (C#)Windows Shell 外壳编程系列8 - 同后缀名不同图标? (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一节:(C#)Windows Shell 外壳 ...

  6. (C#)Windows Shell 外壳编程系列9 - QueryInfo 扩展提示

    原文 (C#)Windows Shell 外壳编程系列9 - QueryInfo 扩展提示 (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一节:(C#)Windows She ...

  7. (C#)Windows Shell 外壳编程系列6 - 执行

    原文(C#)Windows Shell 外壳编程系列6 - 执行 (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一节:(C#)Windows Shell 外壳编程系列5 - ...

  8. (C#)Windows Shell 外壳编程系列1 - 基础,浏览一个文件夹

    1 - 基础,浏览一个文件夹 我们知道,在win32中是以外壳名字空间的形式来组织文件系统的,在外壳名字空间里的每一个对象(注)都实现了一个IShellFolder的接口,通过这个接口我们可以直接查询 ...

  9. (C#)Windows Shell 编程系列3 - 上下文菜单(iContextMenu)(一)右键菜单

    原文 (C#)Windows Shell 编程系列3 - 上下文菜单(iContextMenu)(一)右键菜单 接上一节:(C#)Windows Shell 编程系列2 - 解释,从“桌面”开始展开这 ...

随机推荐

  1. hadoop03---nginx+keepalived

    1.1.反向代理 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求 ...

  2. Linux脚本程序包及安装

    概述 脚本程序并不多见,所以在软件包分类中并没有把它列为一类.它更加类似于 Windows 下的程序安装,有一个可执行的安装程序,只要运行安装程序,然后进行简单的功能定制选择(比如指定安装目录等),就 ...

  3. Java中ArrayList和LinkedList区别、ArrayList和Vector的区别

    一般大家都知道ArrayList和LinkedList的大致区别: 1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构. 2.对于随机访问get和set,Ar ...

  4. Django-Ajax进阶

    一.Ajax上传文件 1.form表单上传文件 文件和其他的数据类型不一样,是一个二进制的形式 Form上传文件的时候切记要加上:enctype="multipart/form-data&q ...

  5. hql join

    文章一: 1.用hql语句 ` String hql="select student.id, student.name ,class.name from student映射实体类名 as s ...

  6. maven 内置属性有哪些?该如何使用?

    maven 共有6类内置属性: 内置属性(maven预定义,用户可以直接使用的) ${basedir}表示项目的根目录,既包含pom.xml文件的目录: ${version}表示项目版本: ${pro ...

  7. CSS3的transform属性

    CSS3的一些属性可能比较新,有一些书从国外翻译到国内的时间上会延缓1-2年.所以有一些东西还需要及时整理. 下面说一下CSS3的一个属性:transform 其实字面上的意思已经很明显了就是变化,变 ...

  8. AOP理解,待细看

    http://jinnianshilongnian.iteye.com/blog/1474325

  9. AODH: ALARM EVENTS IN OPENSTACK

    AODH是从Ceilometer分离出来的一个子项目,开始于OpenStack Liberty,用来提供alarm机制. 除了之前Ceilometer有的基于sample的警报机制,AODH还添加了基 ...

  10. web自动化:selenium原理和元素定位(一)

    一. Selenium2 WebDriver 当Selenium2.x提出了WebDriver的概念后,它提供了完全另外的一种方式与浏览器交互 那就是利用浏览器原生的API,封装成一套更加面向对象的S ...