仅在我的应用程序中添加到shell上下文菜单

问题描述:

在我的.NET Framework 4应用程序中,我显示文件,文件夹和其他不属于文件系统的东西。对于文件和文件夹,我设法显示该项目的Windows Shell上下文菜单,这要归功于this code on MSDN。 (它仍然无法显示Carbonite Shell扩展,但我离题了)。仅在我的应用程序中添加到shell上下文菜单

我的奋斗是将我自己的子菜单添加到Shell上下文菜单。我所有的研究都提到了所谓的Shell 扩展,如果我理解正确的话,它是一个系统范围的变化。我只想在我的应用程序中访问它时,将其添加到Shell上下文菜单

在抓救命稻草,无可否认,我尝试添加在上面的类ShowContextMenu方法如下,它调用QueryContextMenu刚过:

var mii = new MENUITEMINFO(); 
mii.cbSize = Marshal.SizeOf(mii); 
mii.fMask = MIIM.SUBMENU | MIIM.STRING | MIIM.FTYPE | MIIM.ID; 
mii.fType = MFT.BYPOSITION; 
mii.wID = 0; 
mii.hSubMenu = subMenu.Handle; 
mii.dwTypeData = "Test"; 
var success = InsertMenuItem(pMenu, 0, true, ref mii); 

,但没有‘成功’。 (subMenuSystem.Windows.Forms.ContextMenuStrip我前面创建的。)

我的问题是:

  1. 我是正确什么我试图从创建一个Shell扩展不同?

  2. 这是否仍被认为是托管代码中的危险活动,按照this post

  3. 这其实是怎么做到的?

+0

1:不,我只是在QueryContextMenu中测试一个已命名的互斥体。一个只有你的应用程序创建。 – 2012-07-10 04:44:59

+0

因此,即使我有一个壳牌上下文菜单的句柄,我不能只为该实例添加它? – 2012-07-10 19:42:14

OK,看起来可以自定义菜单项添加到Windows外壳上下文菜单,只需在您的应用程序(不需要做任何事情,会影响整个Windows系统)。以下是我所做的。请记住,此答案应在首先提到的MSDN代码的上下文中进行。这里我们再次链接:

ShellContextMenu class on MSDN

在这一类,准确地说,方法ShowContextMenu,是QueryContextMenu的电话,其目的我学到的是填充菜单的项目 - 在这种情况下,适当的Windows要显示其上下文菜单的文件/文件夹的外壳菜单项。这一呼吁之后,我加入了下面的代码添加子菜单和分隔符:

var mii = new MENUITEMINFO(); 
mii.fMask = MIIM.SUBMENU | MIIM.STRING | MIIM.FTYPE | MIIM.ID | MIIM.STATE | MIIM.BITMAP; 
mii.fState = MFS.ENABLED; 
mii.fType = MFT.STRING; 
mii.wID = 0; // Application-defined value that identifies the menu item. 
mii.hSubMenu = **subMenu**.Handle; 
mii.dwTypeData = Program.ShortTitle; 
mii.cch = mii.dwTypeData.Length; 
var bmp = new System.Drawing.Icon(ac.Properties.NeutralResources.MyAppIcon, 16, 16).ToBitmap(); 
this.hMyAppSubmenuIcon = bmp.GetHbitmap(); 
mii.hbmpItem = this.hMyAppSubmenuIcon; 
mii.cbSize = Marshal.SizeOf(typeof(MENUITEMINFO)); 
var success = InsertMenuItem(pMenu, 0, true, ref mii); 

mii = new MENUITEMINFO(); 
mii.fMask = MIIM.FTYPE; 
mii.fType = MFT.SEPARATOR; 
mii.cbSize = Marshal.SizeOf(mii); 
success = InsertMenuItem(pMenu, 1, true, ref mii); 

System.Windows.Forms.ContextMenu类型。通过这种方式,整个上下文菜单有点混合,由托管菜单项和非托管菜单项组成。到目前为止,我没有看到这个问题。它只是意味着处理选择两种类型的菜单项必须以不同的方式完成,如下所述......

将管理项目插入菜单后,ShowContextMenu方法调用TrackPopupMenu。对于Shell菜单项,已经写好的类负责处理他们的选择。对于我自己的菜单项,我必须采取额外的步骤,因为TrackPopupMenu是Windows API函数,所以对于托管子菜单项“Click”事件不起作用。您可以将Click事件处理程序挂接到您的子菜单项,但是当从Shell上下文菜单中选择它们时,它们的Click事件不会触发。即使有时我只是自己显示我的管理菜单,我仍然连线他们的Click

采取行动以响应于来自壳牌上下文菜单中的管理菜单项选择,我使用的TrackPopupMenu返回值,它是被选择该菜单项的资源ID。这是事情有点迂回的地方。当创建托管上下文菜单时,每个菜单项都有一个索引。您可以在Windows API函数GetMenuItemID中使用此函数,该函数返回菜单项的资源ID。我从受管理的ContextMenu类继承,并封装了一个Dictionary,它帮助我从此资源ID映射到菜单项,稍后在调用TrackPopupMenu后稍后使用。出于我的目的,这就是为了调用处理程序所需的全部内容,因为在我的应用程序中,我使用命令模式,并在创建菜单时将命令对象存储在菜单项的Tag属性中。 (一旦字典给了我正确的菜单项,我就能够通过从Tag中提取命令对象来执行相应的处理程序)。

这几天现在运行良好。如果有人发现漏洞,比如我应该清理的非托管资源,请提及。