(C#)Windows Shell 编程系列3 - 上下文菜单(iContextMenu)(一)右键菜单
原文 (C#)Windows Shell 編程系列3 - 上下文菜單(iContextMenu)(一)右鍵菜單
接上一節(jié):(C#)Windows Shell 編程系列2 - 解釋,從“桌面”開始展開
這里解釋上一節(jié)中獲取名稱的方法 GetDisplayNameOf 定義:
該方法是用來轉(zhuǎn)換PIDL成為可顯示的名稱字符串。PIDL必須是相對于對象的父目錄的。換句話說,它必須包含一個非空的SHITEMID 結(jié)構(gòu)。因為有多種命名對象的方式,資源管理器通過在uFlags參數(shù)中定義SHGNO標(biāo)識的組合來表示名稱類型。SHGDN_NORMAL或 SHGDN_INFOLDER將被用來指定名稱是相對于文件夾的還是相對于桌面的。其他三個值SHGDN_FOREDITING、 SHGDN_FORADDRESSBAR和SHGDN_FORPARSING可以用來指定名稱的用途。 名稱必須按STRRET的結(jié)構(gòu)形式返回,如果SHGDN_FOREDITING、SHGDN_FORADDRESSBAR和 SHGDN_FORPARSING沒有設(shè)定,就返回外殼對象的顯示名稱。
具體實現(xiàn)方法:
?
public?enum?SHGNO ????{ ????????NORMAL?=?0x0, ????????INFOLDER?=?0x1, ????????FOREDITING?=?0x1000, ????????FORADDRESSBAR?=?0x4000, ????????FORPARSING?=?0x8000, ????}事實上,只要修改 SHGNO ,就可以獲取其絕對路徑:
///?<summary> ????????///?根據(jù)路徑獲取?IShellFolder?和?PIDL ????????///?</summary> ????????public?static?IShellFolder?GetShellFolder(IShellFolder?desktop,?string?path,?out?IntPtr?Pidl) ????????{ ????????????IShellFolder?IFolder; ????????????uint?i,?j?=?0; ????????????desktop.ParseDisplayName(IntPtr.Zero,?IntPtr.Zero,?path,?out?i,?out?Pidl,?ref?j); ????????????desktop.BindToObject(Pidl,?IntPtr.Zero,?ref?Guids.IID_IShellFolder,?out?IFolder); ????????????return?IFolder; ????????}但我們還關(guān)心類似“桌面”、“我的文檔”這種既是普通文件夾又是特殊對象的絕對路徑如何獲得,這里就要用到 SHGetSpecialFolderPath API 了。
[DllImport("Shell32.Dll")] ????????private?static?extern?bool?SHGetSpecialFolderPath( ????????????IntPtr?hwndOwner,? ????????????StringBuilder?lpszPath, ????????????ShellSpecialFolders?nFolder, ????????????bool?fCreate);?
public?enum?ShellSpecialFolders ????{ ????????DESKTOP?=?0x0000,?????????//?<desktop> ????????INTERNET?=?0x0001, ????????PROGRAMS?=?0x0002,????????//?Start?Menu/Programs ????????CONTROLS?=?0x0003,????????//?My?Computer/Control?Panel ????????PRINTERS?=?0x0004,????????//?My?Computer/Printers ????????PERSONAL?=?0x0005,????????//?My?Documents ????????FAVORITES?=?0x0006,????????//?<user?name>/Favorites ????????STARTUP?=?0x0007,????????//?Start?Menu/Programs/Startup ????????RECENT?=?0x0008,????????//?<user?name>/Recent ????????SENDTO?=?0x0009,????????//?<user?name>/SendTo ????????BITBUCKET?=?0x000a,????????//?<desktop>/Recycle?Bin ????????STARTMENU?=?0x000b,????????//?<user?name>/Start?Menu ????????MYDOCUMENTS?=?0x000c,????????//?logical?"My?Documents"?desktop?icon ????????MYMUSIC?=?0x000d,????????//?"My?Music"?folder ????????MYVIDEO?=?0x000e,????????//?"My?Videos"?folder ????????DESKTOPDIRECTORY?=?0x0010,????????//?<user?name>/Desktop ????????DRIVES?=?0x0011,????????//?My?Computer ????????NETWORK?=?0x0012,????????//?Network?Neighborhood?(My?Network?Places) ????????NETHOOD?=?0x0013,????????//?<user?name>/nethood ????????FONTS?=?0x0014,????????//?windows/fonts ????????TEMPLATES?=?0x0015, ????????COMMON_STARTMENU?=?0x0016,????????//?All?Users/Start?Menu ????????COMMON_PROGRAMS?=?0X0017,????????//?All?Users/Start?Menu/Programs ????????COMMON_STARTUP?=?0x0018,????????//?All?Users/Startup ????????COMMON_DESKTOPDIRECTORY?=?0x0019,????????//?All?Users/Desktop ????????APPDATA?=?0x001a,????????//?<user?name>/Application?Data ????????PRINTHOOD?=?0x001b,????????//?<user?name>/PrintHood ????????LOCAL_APPDATA?=?0x001c,????????//?<user?name>/Local?Settings/Applicaiton?Data?(non?roaming) ????????ALTSTARTUP?=?0x001d,????????//?non?localized?startup ????????COMMON_ALTSTARTUP?=?0x001e,????????//?non?localized?common?startup ????????COMMON_FAVORITES?=?0x001f, ????????INTERNET_CACHE?=?0x0020, ????????COOKIES?=?0x0021, ????????HISTORY?=?0x0022, ????????COMMON_APPDATA?=?0x0023,????????//?All?Users/Application?Data ????????WINDOWS?=?0x0024,????????//?GetWindowsDirectory() ????????SYSTEM?=?0x0025,????????//?GetSystemDirectory() ????????PROGRAM_FILES?=?0x0026,????????//?C:/Program?Files ????????MYPICTURES?=?0x0027,????????//?C:/Program?Files/My?Pictures ????????PROFILE?=?0x0028,????????//?USERPROFILE ????????SYSTEMX86?=?0x0029,????????//?x86?system?directory?on?RISC ????????PROGRAM_FILESX86?=?0x002a,????????//?x86?C:/Program?Files?on?RISC ????????PROGRAM_FILES_COMMON?=?0x002b,????????//?C:/Program?Files/Common ????????PROGRAM_FILES_COMMONX86?=?0x002c,????????//?x86?Program?Files/Common?on?RISC ????????COMMON_TEMPLATES?=?0x002d,????????//?All?Users/Templates ????????COMMON_DOCUMENTS?=?0x002e,????????//?All?Users/Documents ????????COMMON_ADMINTOOLS?=?0x002f,????????//?All?Users/Start?Menu/Programs/Administrative?Tools ????????ADMINTOOLS?=?0x0030,????????//?<user?name>/Start?Menu/Programs/Administrative?Tools ????????CONNECTIONS?=?0x0031,????????//?Network?and?Dial-up?Connections ????????COMMON_MUSIC?=?0x0035,????????//?All?Users/My?Music ????????COMMON_PICTURES?=?0x0036,????????//?All?Users/My?Pictures ????????COMMON_VIDEO?=?0x0037,????????//?All?Users/My?Video ????????RESOURCES?=?0x0038,????????//?Resource?Direcotry ????????RESOURCES_LOCALIZED?=?0x0039,????????//?Localized?Resource?Direcotry ????????COMMON_OLINKS?=?0x003a,????????//?Links?to?All?Users?OEM?specific?apps ????????CDBURN_AREA?=?0x003b,????????//?USERPROFILE/Local?Settings/Application?Data/Microsoft/CD?Burning ????????COMPUTERSNEARME?=?0x003d,????????//?Computers?Near?Me?(computered?from?Workgroup?membership) ????????FLAG_CREATE?=?0x8000,????????//?combine?with??value?to?force?folder?creation?in?SHGetFolderPath() ????????FLAG_DONT_VERIFY?=?0x4000,????????//?combine?with??value?to?return?an?unverified?folder?path ????????FLAG_NO_ALIAS?=?0x1000,????????//?combine?with??value?to?insure?non-alias?versions?of?the?pidl ????????FLAG_PER_USER_INIT?=?0x0800,????????//?combine?with??value?to?indicate?per-user?init?(eg.?upgrade) ????????FLAG_MASK?=?0xFF00,????????//?mask?for?all?possible?flag?values ????}?
///?<summary> ????????///?獲取特殊文件夾的路徑 ????????///?</summary> ????????public?static?string?GetSpecialFolderPath(IntPtr?hwnd,?ShellSpecialFolders?nFolder) ????????{ ????????????StringBuilder?sb?=?new?StringBuilder(MAX_PATH); ????????????SHGetSpecialFolderPath(hwnd,?sb,?nFolder,?false); ????????????return?sb.ToString(); ????????}上下文菜單
對象的上下文菜單相關(guān)的接口是 IContextMenu,通過對象的父文件夾的IShellFolder.GetUIObjectOf方法可得到該接口。得到該接口后,可以用 IContextMenu.QueryContextMenu方法來生成上下文菜單的菜單項,用IContextMenu.InvokeCommand調(diào) 用相應(yīng)的命令。
好,讓我們一步一步來實現(xiàn) IShellFolder 對象的上下文菜單彈出。
首先假設(shè)我們已經(jīng)獲得某個 IShellFolder 對象的 PIDL 和其上級 IShellFolder 對象:
然后我們定義一個存放 PIDL 的數(shù)組:
IntPtr[]?pidls?=?new?IntPtr[1]; pidls[0]?=?PIDL;沒錯,我們的確要用到 PIDL 數(shù)組??梢岳斫?#xff0c;你在資源管理器中選擇了多個文件/文件夾,再點擊右鍵,彈出的上下文菜單將有所不同。你可以根據(jù)需要,把同一級的多個 PIDL 放到數(shù)組里面,實現(xiàn)這個效果。由于我們在例2的樹中彈出菜單,所以只存放一個節(jié)點的 PIDL。
IContextMenu 是一個接口,我們這樣定義:
然后,通過 IParent 的 GetUIObjectOf 方法我們可以得到該節(jié)點的一個或多個指定子節(jié)點的 IContextMenu 接口:
IntPtr?GetUIObjectOf( ????????????IntPtr?hwndOwner, ????????????uint?cidl, ????????????[MarshalAs(UnmanagedType.LPArray)]?IntPtr[]?apidl, ????????????[In()]?ref?Guid?riid, ????????????out?IntPtr?rgfReserved); //得到?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,如果該方法執(zhí)行成功的話,會在我們的菜單里加入相應(yīng)的菜單項。
//提供一個彈出式菜單的句柄 IntPtr?contextMenu?=?API.CreatePopupMenu(); iContextMenu.QueryContextMenu(contextMenu,?0, API.CMD_FIRST,?API.CMD_LAST,?CMF.NORMAL?|?CMF.EXPLORE);有了菜單項,我們就可以彈出該菜單了,我們用 TPM_RETURNCMD 標(biāo)志指定 TrackPopupMenu 必須返回用戶所選菜單項的 ID,以便稍后通過IContextMenu.InvokeCommand 來執(zhí)行菜單命令:
//彈出菜單 uint?cmd?=?API.TrackPopupMenuEx(contextMenu,TPM.RETURNCMD, MousePosition.X,?MousePosition.Y,?this.Handle,?IntPtr.Zero); //獲取命令序號,執(zhí)行菜單命令 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
下一節(jié)深入講述 iContextMenu,讓我們可以插入自己的菜單,或者直接調(diào)用菜單命令。
?
posted on 2013-10-30 15:48 NET未來之路 閱讀(...) 評論(...) 編輯 收藏轉(zhuǎn)載于:https://www.cnblogs.com/lonelyxmas/p/3396937.html
總結(jié)
以上是生活随笔為你收集整理的(C#)Windows Shell 编程系列3 - 上下文菜单(iContextMenu)(一)右键菜单的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于.h .lib .dll的总结
- 下一篇: Ajax调用webService(一)