日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > C# >内容正文

C#

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

發(fā)布時(shí)間:2025/7/14 C# 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (C#)Windows Shell 编程系列3 - 上下文菜单(iContextMenu)(一)右键菜单 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
(C#)Windows Shell 編程系列3 - 上下文菜單(iContextMenu)(一)右鍵菜單

原文 (C#)Windows Shell 編程系列3 - 上下文菜單(iContextMenu)(一)右鍵菜單

接上一節(jié):(C#)Windows Shell 編程系列2 - 解釋,從“桌面”開(kāi)始展開(kāi)
這里解釋上一節(jié)中獲取名稱(chēng)的方法 GetDisplayNameOf 定義:

void?GetDisplayNameOf( ????????????IntPtr?pidl, ????????????SHGNO?uFlags, ????????????IntPtr?lpName);

該方法是用來(lái)轉(zhuǎn)換PIDL成為可顯示的名稱(chēng)字符串。PIDL必須是相對(duì)于對(duì)象的父目錄的。換句話(huà)說(shuō),它必須包含一個(gè)非空的SHITEMID 結(jié)構(gòu)。因?yàn)橛卸喾N命名對(duì)象的方式,資源管理器通過(guò)在uFlags參數(shù)中定義SHGNO標(biāo)識(shí)的組合來(lái)表示名稱(chēng)類(lèi)型。SHGDN_NORMAL或 SHGDN_INFOLDER將被用來(lái)指定名稱(chēng)是相對(duì)于文件夾的還是相對(duì)于桌面的。其他三個(gè)值SHGDN_FOREDITING、 SHGDN_FORADDRESSBAR和SHGDN_FORPARSING可以用來(lái)指定名稱(chēng)的用途。 名稱(chēng)必須按STRRET的結(jié)構(gòu)形式返回,如果SHGDN_FOREDITING、SHGDN_FORADDRESSBAR和 SHGDN_FORPARSING沒(méi)有設(shè)定,就返回外殼對(duì)象的顯示名稱(chēng)。
具體實(shí)現(xiàn)方法:

///?<summary> ????????///?獲取顯示名稱(chēng) ????????///?</summary> ????????public?static?string?GetNameByIShell(IShellFolder?Root,?IntPtr?pidlSub) ????????{ ????????????IntPtr?strr?=?Marshal.AllocCoTaskMem(MAX_PATH?*?2?+?4); ????????????Marshal.WriteInt32(strr,?0,?0); ????????????StringBuilder?buf?=?new?StringBuilder(MAX_PATH); ????????????Root.GetDisplayNameOf(pidlSub,?SHGNO.INFOLDER,?strr); ????????????API.StrRetToBuf(strr,?pidlSub,?buf,?MAX_PATH); ????????????Marshal.FreeCoTaskMem(strr); ????????????return?buf.ToString(); ????????}

?

public?enum?SHGNO ????{ ????????NORMAL?=?0x0, ????????INFOLDER?=?0x1, ????????FOREDITING?=?0x1000, ????????FORADDRESSBAR?=?0x4000, ????????FORPARSING?=?0x8000, ????}

事實(shí)上,只要修改 SHGNO ,就可以獲取其絕對(duì)路徑:

///?<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)心類(lèi)似“桌面”、“我的文檔”這種既是普通文件夾又是特殊對(duì)象的絕對(duì)路徑如何獲得,這里就要用到 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(); ????????}

上下文菜單
對(duì)象的上下文菜單相關(guān)的接口是 IContextMenu,通過(guò)對(duì)象的父文件夾的IShellFolder.GetUIObjectOf方法可得到該接口。得到該接口后,可以用 IContextMenu.QueryContextMenu方法來(lái)生成上下文菜單的菜單項(xiàng),用IContextMenu.InvokeCommand調(diào) 用相應(yīng)的命令。
好,讓我們一步一步來(lái)實(shí)現(xiàn) IShellFolder 對(duì)象的上下文菜單彈出。
首先假設(shè)我們已經(jīng)獲得某個(gè) IShellFolder 對(duì)象的 PIDL 和其上級(jí) IShellFolder 對(duì)象:

IntPtr?PIDL; IShellFolder?IParent;

然后我們定義一個(gè)存放 PIDL 的數(shù)組:

IntPtr[]?pidls?=?new?IntPtr[1]; pidls[0]?=?PIDL;

沒(méi)錯(cuò),我們的確要用到 PIDL 數(shù)組??梢岳斫?#xff0c;你在資源管理器中選擇了多個(gè)文件/文件夾,再點(diǎn)擊右鍵,彈出的上下文菜單將有所不同。你可以根據(jù)需要,把同一級(jí)的多個(gè) PIDL 放到數(shù)組里面,實(shí)現(xiàn)這個(gè)效果。由于我們?cè)诶?的樹(shù)中彈出菜單,所以只存放一個(gè)節(jié)點(diǎn)的 PIDL。
IContextMenu 是一個(gè)接口,我們這樣定義:

using?System; using?System.Collections.Generic; using?System.Text; using?System.Runtime.InteropServices; namespace?WinShell { ????[ComImport(),?InterfaceType(ComInterfaceType.InterfaceIsIUnknown),?GuidAttribute("000214e4-0000-0000-c000-000000000046")] ????public?interface?IContextMenu ????{ ????????[PreserveSig()] ????????Int32?QueryContextMenu( ????????????IntPtr?hmenu, ????????????uint?iMenu, ????????????uint?idCmdFirst, ????????????uint?idCmdLast, ????????????CMF?uFlags); ????????[PreserveSig()] ????????Int32?InvokeCommand( ????????????ref?CMINVOKECOMMANDINFOEX?info); ????????[PreserveSig()] ????????void?GetCommandString( ????????????int?idcmd, ????????????GetCommandStringInformations?uflags, ????????????int?reserved, ????????????StringBuilder?commandstring, ????????????int?cch); ????} }

然后,通過(guò) IParent 的 GetUIObjectOf 方法我們可以得到該節(jié)點(diǎn)的一個(gè)或多個(gè)指定子節(jié)點(diǎn)的 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 后我們需要提供一個(gè)彈出式菜單的句柄,并把他傳給 IContextMenu.QueryContextMenu,如果該方法執(zhí)行成功的話(huà),會(huì)在我們的菜單里加入相應(yīng)的菜單項(xiàng)。

//提供一個(gè)彈出式菜單的句柄 IntPtr?contextMenu?=?API.CreatePopupMenu(); iContextMenu.QueryContextMenu(contextMenu,?0, API.CMD_FIRST,?API.CMD_LAST,?CMF.NORMAL?|?CMF.EXPLORE);

有了菜單項(xiàng),我們就可以彈出該菜單了,我們用 TPM_RETURNCMD 標(biāo)志指定 TrackPopupMenu 必須返回用戶(hù)所選菜單項(xiàng)的 ID,以便稍后通過(guò)IContextMenu.InvokeCommand 來(lái)執(zhí)行菜單命令:

//彈出菜單 uint?cmd?=?API.TrackPopupMenuEx(contextMenu,TPM.RETURNCMD, MousePosition.X,?MousePosition.Y,?this.Handle,?IntPtr.Zero); //獲取命令序號(hào),執(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未來(lái)之路 閱讀(...) 評(píng)論(...) 編輯 收藏

轉(zhuǎn)載于:https://www.cnblogs.com/lonelyxmas/p/3396937.html

總結(jié)

以上是生活随笔為你收集整理的(C#)Windows Shell 编程系列3 - 上下文菜单(iContextMenu)(一)右键菜单的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久久久久99精品成人片毛片 | 久久久久久久久久成人 | 五月天开心激情 | 在线视频观看一区 | 丁香婷婷综合激情五月色 | 日本少妇吞精囗交视频 | 国精产品一区一区三区有限公司杨 | 日韩免费毛片 | 亚洲精品国产精品乱码不99热 | 国产日韩精品在线 | 免费成人结看片 | 日日碰日日操 | 黑人与亚洲人色ⅹvideos | 国产日韩一区二区三免费高清 | 一区二区三区在线观看免费视频 | 久久人妻一区二区 | 视频在线不卡 | 美丽的小蜜桃2:美丽人生 | 色婷婷av在线 | 欧美精产国品一二三区 | 国产精品免费一区二区三区都可以 | 青青草一区二区 | 美女高潮视频在线观看 | 国产69精品久久久 | 黄色免费视频观看 | 成人精品在线视频 | av在线播放一区二区三区 | 日本免费一区二区三区 | 色偷偷成人 | 久草剧场 | 天天干网站 | 亚洲天堂av一区二区三区 | 国产黄色精品网站 | 日韩免费二区 | 日韩一区二区三 | 欧美黑吊大战白妞 | 欧美日韩一区二区三区在线视频 | 亚洲熟妇av一区二区三区漫画 | 国产精品成人久久久 | 大奶在线播放 | 国产成人a人亚洲精品无码 在线aa | 国产精品国产三级国产专播品爱网 | 久久另类ts人妖一区二区 | 先锋影音av资源网 | 亚洲美女视频在线观看 | 国产精品无码毛片 | 成年人视频在线播放 | 中文字幕欧美在线 | 毛片在哪里看 | wwwww在线观看| 深夜成人福利 | a∨鲁丝一区鲁丝二区鲁丝三区 | 日韩精品国产一区 | 国产日韩精品一区二区三区 | 成人无高清96免费 | 色综合视频在线观看 | 美女屁股眼视频网站 | 日韩免费影院 | 成人福利视频导航 | 99自拍偷拍 | 亚洲精品6 | 久久黄色一级片 | 国产欧美另类 | 天天干网址 | 美国特色黄a大片 | 天天操天天插 | 欧洲mv日韩mv国产 | 国产女人在线视频 | xxav在线 | 日韩人妻精品中文字幕 | 国产精品成人国产乱一区 | 青青青av| www.haoav| 国模小丫大尺度啪啪人体 | 日本在线视频www | 三大队在线观看 | 国产一区二区三区四区视频 | 最近中文字幕第一页 | 免费在线h | 日日操日日摸 | 人人看人人插 | 国产91在线高潮白浆在线观看 | 亚洲一区二区三区日韩 | 欧美成人dvd在线视频 | 羞羞涩涩网站 | 亚洲色p | 久久婷婷丁香 | 亚洲美女久久久 | 俄罗斯一级片 | 亚洲最新 | 999免费视频| 中文字幕日韩国产 | 少妇熟女一区二区三区 | 爱情岛论坛自拍亚洲品质极速最新章 | 蜜桃精品一区二区 | 欧洲美女毛片 | 亚洲成在线观看 | 不卡av影院 | 亚洲免费在线视频观看 |