技术开发 频道

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


    对象的上下文菜单相关的接口是IContextMenu,通过对象的父文件夹的IShellFolder.GetUIObjectOf方法可得到该接口。得到该接口后,可以用IContextMenu.QueryContextMenu方法来生成上下文菜单的菜单项,用IContextMenu.InvokeCommand调用相应的命令。

    好,让我们一步一步来实现 IShellFolder 对象的上下文菜单弹出。

    首先假设我们已经获得某个 IShellFolder 对象的 PIDL 和其上级 IShellFolder 对象:
IntPtr PIDL; IShellFolder IParent;
    然后我们定义一个存放 PIDL 的数组:
IntPtr[] pidls = new IntPtr[1]; pidls[0] = PIDL;
    我们的确要用到 PIDL 数组。可以理解,你在资源管理器中选择了多个文件/文件夹,再点击右键,弹出的上下文菜单将有所不同。你可以根据需要,把同一级的多个 PIDL 放到数组里面,实现这个效果。由于我们在例2的树中弹出菜单,所以只存放一个节点的 PIDL。

    IContextMenu 是一个接口,我们这样定义:
IContextMenu.cs
    然后,通过 IParent 的 GetUIObjectOf 方法我们可以得到该节点的一个或多个指定子节点的 IContextMenu 接口:
GetUIObjectOf
//得到 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);
    得到 IContextMenu 后我们需要提供一个弹出式菜单的句柄,并把他传给 IContextMenu.QueryContextMenu,如果该方法执行成功的话,会在我们的菜单里加入相应的菜单项。
//提供一个弹出式菜单的句柄 IntPtr contextMenu = API.CreatePopupMenu(); iContextMenu.QueryContextMenu(contextMenu, 0, API.CMD_FIRST, API.CMD_LAST, CMF.NORMAL | CMF.EXPLORE);
    有了菜单项,我们就可以弹出该菜单了,我们用 TPM_RETURNCMD 标志指定 TrackPopupMenu 必须返回用户所选菜单项的 ID,以便稍后通过IContextMenu.InvokeCommand 来执行菜单命令:
//弹出菜单 uint cmd = API.TrackPopupMenuEx(contextMenu,TPM.RETURNCMD, MousePosition.X, MousePosition.Y, this.Handle, IntPtr.Zero); //获取命令序号,执行菜单命令 if (cmd >= API.CMD_FIRST) { CMINVOKECOMMANDINFOEX invoke = new CMINVOKECOMMANDINFOEX(); invoke.cbSize = Marshal.SizeOf(typeof(CMINVOKECOMMANDINFOEX)); invoke.lpVerb = (IntPtr)(cmd - 1); invoke.lpDirectory = string.Empty; invoke.fMask = 0; invoke.ptInvoke = new POINT(MousePosition.X, MousePosition.Y); invoke.nShow = 1; iContextMenu.InvokeCommand(ref invoke); }
惯例附上图片和源代码:



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

下一节深入讲述 iContextMenu,让我们可以插入自己的菜单,或者直接调用菜单命令。


0
相关文章