(C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令...
(本系列文章由檸檬的(lc_mtt)原創(chuàng),轉(zhuǎn)載請注明出處,謝謝~)
接上一節(jié):(C#)Windows Shell 外殼編程系列3 - 上下文菜單(iContextMenu)(一)右鍵菜單
上一節(jié)說到如何彈出 IShellFolder 的上下文菜單,也就是 IContextMenu。有時候我們需要在這個菜單上面,加入一些屬于自己的菜單項(xiàng)。舉個例子,你打開資源管理器,查看左邊目錄樹的右鍵菜單,會發(fā)現(xiàn)頂層多了一個折疊/展開的菜單項(xiàng)。好,我們也動手來加入這個菜單項(xiàng)。
修改例子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,?"-");
//把第一項(xiàng)菜單設(shè)置為默認(rèn)菜單,也就是加粗
API.SetMenuDefaultItem(contextMenu,?0,?true);
/
這里我們用到了 InsertMenu 這個 API:
????????????SetLastError?=?true,
????????????CharSet?=?CharSet.Auto)]
????????public?static?extern?bool?InsertMenu(
????????????IntPtr?hmenu,
????????????uint?uPosition,
????????????MFT?uflags,
????????????uint?uIDNewItem,
????????????[MarshalAs(UnmanagedType.LPTStr)]
????????????string?lpNewItem);
參數(shù)2表示增加菜單項(xiàng)的位置,從0開始。
參數(shù)3表示flag,這里提供了菜單狀態(tài),以及位置的計算方法,它是一個枚舉:
MF_BYPOSITION 表示位置的計算方法是使用索引項(xiàng),第一個菜單就是0,第二個菜單就是1,如此類推...
參數(shù)4表示命令值。我們可以根據(jù)這個命令值來執(zhí)行對應(yīng)的功能。
然后就可以彈出菜單了:
uint?cmd?=?API.TrackPopupMenuEx(contextMenu,TPM.RETURNCMD,
MousePosition.X,?MousePosition.Y,?this.Handle,?IntPtr.Zero);
可以看到彈出菜單的效果。當(dāng)然,我們還必須做點(diǎn)事情來響應(yīng)這個菜單的執(zhí)行:
if?(cmd?>=?API.CMD_FIRST)
{
????
????//自定義菜單命令
????if?(cmd?==?API.CMD_LAST?+?1)
????{
????????if?(Tree1.SelectedNode.IsExpanded)
????????????Tree1.SelectedNode.Collapse();
????????else
????????????Tree1.SelectedNode.Expand();
????}
}
如圖:
執(zhí)行菜單命令
能不能不彈出菜單直接調(diào)用菜單項(xiàng)相應(yīng)的命令?答案是肯定的。
大家還記得怎么顯示一個文件或文件夾的屬性對話框嗎?
Yes,用ShellExecuteEx并指定SHELLEXECUTEINFO的lpVerb域?yàn)閜roperties就可,但是這種方法只能查看一個文件的屬性,怎么同時查看多個的?
要知道ShellExecuteEx查看文件屬性最終也是靠IContextMenu幫忙的,所以答案還是在IContextMenu上,我們只要在調(diào)用GetUIObjectOf時把想查看的文件或文件件的PIDL做為參數(shù)傳進(jìn)去,然后直接調(diào)用InvokeCommand方法就OK啦。
當(dāng)然,我們做的例子,還是彈出一個對象的屬性,靠你自己修改了。
我們必須先得到 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);
但我們不彈出這個菜單,僅僅是調(diào)用 InvokeCommand 來執(zhí)行命令而已:
//直接執(zhí)行命令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);
關(guān)于verb的更多信息請參考MSDN。我這里做的是執(zhí)行“屬性”,如果你要執(zhí)行其他命令,或者按照索引來執(zhí)行,也是可以的。這里不做深入研究。
源代碼:/Files/lemony/WinShell4.rar
我正在考慮下一節(jié)是講圖標(biāo),還是繼續(xù)講iContextMenu。大家也知道,某個文件的右鍵菜單里面,往往會有幾個 winrar 的選項(xiàng),還帶著可愛的圖標(biāo)。
很有可能下一節(jié)就講述如何在C#中也實(shí)現(xiàn)這樣的效果哦。希望大家多多支持^_^。
總結(jié)
以上是生活随笔為你收集整理的(C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【小松教你手游开发】【unity系统模块
- 下一篇: Win8 Metro(C#)数字图像处理