设为首页 收藏本站
查看: 1271|回复: 0

(C#)Windows Shell 外壳编程系列4

[复制链接]

尚未签到

发表于 2015-4-28 11:49:23 | 显示全部楼层 |阅读模式
(本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢~)

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

上一节说到如何弹出 IShellFolder 的上下文菜单,也就是 IContextMenu。有时候我们需要在这个菜单上面,加入一些属于自己的菜单项。举个例子,你打开资源管理器,查看左边目录树的右键菜单,会发现顶层多了一个折叠/展开的菜单项。好,我们也动手来加入这个菜单项。

修改例子3,我们找到 QueryContextMenu 处,这时候提供了一个菜单句柄:


DSC0000.gif //提供一个弹出式菜单的句柄
IntPtr contextMenu = API.CreatePopupMenu();
iContextMenu.QueryContextMenu(contextMenu, 0,
    API.CMD_FIRST, API.CMD_LAST, CMF.NORMAL | CMF.EXPLORE);
然后增加以下代码:


DSC0001.gif DSC0002.gif /**//////////////////////////增加一个自定义菜单
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
public enum MFT : uint
DSC0003.gif {
DSC0004.gif     GRAYED = 0x00000003,
    DISABLED = 0x00000003,
    CHECKED = 0x00000008,
    SEPARATOR = 0x00000800,
    RADIOCHECK = 0x00000200,
    BITMAP = 0x00000004,
    OWNERDRAW = 0x00000100,
    MENUBARBREAK = 0x00000020,
    MENUBREAK = 0x00000040,
    RIGHTORDER = 0x00002000,
    BYCOMMAND = 0x00000000,
    BYPOSITION = 0x00000400,
    POPUP = 0x00000010
DSC0005.gif }
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)
DSC0006.gif DSC0007.gif     {
        if (Tree1.SelectedNode.IsExpanded)
            Tree1.SelectedNode.Collapse();
        else
            Tree1.SelectedNode.Expand();
DSC0008.gif     }
}  
如图:

DSC0009.jpg

执行菜单命令

能不能不弹出菜单直接调用菜单项相应的命令?答案是肯定的。
  大家还记得怎么显示一个文件或文件夹的属性对话框吗?
  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。我这里做的是执行“属性”,如果你要执行其他命令,或者按照索引来执行,也是可以的。这里不做深入研究。

DSC00010.jpg

源代码:/Files/lemony/WinShell4.rar

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

DSC00011.jpg

很有可能下一节就讲述如何在C#中也实现这样的效果哦。希望大家多多支持^_^。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-61547-1-1.html 上篇帖子: 【自动构建系列】自动部署环境的shell脚本 下篇帖子: MongoDB shell
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表