![](/img/trans.png)
[英]How can i add more context menus and commands to the shell file extensions?
[英]How can i add sub context menus to registered context menu using shell file extensions?
在Program.cs中,我添加了一個類:
public static class Menus
{
public static string MenuShare1 = "FaceBook";
public static string MenyShare2 = "Tapuz";
}
然后我還添加了一個上下文菜單字符串變量:
const string MenuText2 = "Share >";
我想要做的是當我在今天位於目錄中的鼠標上單擊鼠標右鍵時,它向我顯示“復制到灰度”和“調整所有圖像的大小”,我希望它也顯示上下文菜單“共享>”。當我在“共享>”上單擊或將鼠標移到上方時,它將打開菜單類下的子上下文菜單:
FaceBook Tapuz
如果我單擊FaceBook或Tapuz,它將執行某些操作。
在Program.cs中
using System;
using System.Windows.Forms;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
[assembly: CLSCompliant(true)]
namespace SimpleContextMenu
{
static class Program
{
public static class Menus
{
public static string MenuShare1 = "FaceBook";
public static string MenyShare2 = "Tapuz";
}
// file type to register
const string FileType = "bitmapfile";//"jpegfile";
// context menu name in the registry
const string KeyName = "Simple Context Menu";
const string KeyName1 = "Simple Context Menu1";
// context menu text
const string MenuText = "Copy to Grayscale";
const string MenuText1 = "Resize all images";
const string MenuText2 = "Share >";
[STAThread]
static void Main(string[] args)
{
// process register or unregister commands
if (!ProcessCommand(args))
{
string action = args[0];
//MessageBox.Show(action);
string fileName = args[1];
if (action == "Copy")
{
// invoked from shell, process the selected file
CopyGrayscaleImage(fileName);
}
else if (action == "Resize")
{
string FilePath = Path.Combine(
Path.GetDirectoryName(fileName),
string.Format("{0} (resized){1}",
Path.GetFileNameWithoutExtension(fileName),
Path.GetExtension(fileName)));
//MessageBox.Show(FilePath);
Bitmap bmp1 = new Bitmap(ResizeImages(fileName,100,100));
bmp1.Save(FilePath);
bmp1.Dispose();
}
}
}
/// <summary>
/// Process command line actions (register or unregister).
/// </summary>
/// <param name="args">Command line arguments.</param>
/// <returns>True if processed an action in the command line.</returns>
static bool ProcessCommand(string[] args)
{
// register
if (args.Length == 0 || string.Compare(args[0], "-register", true) == 0)
{
// full path to self, %L is placeholder for selected file
string menuCommand = string.Format("\"{0}\" Copy \"%L\"", Application.ExecutablePath);
// register the context menu
FileShellExtension.Register(Program.FileType,
Program.KeyName, Program.MenuText,
menuCommand);
string menuCommand1 = string.Format("\"{0}\" Resize \"%L\"", Application.ExecutablePath);
FileShellExtension.Register(Program.FileType,
Program.KeyName1, Program.MenuText1,
menuCommand1);
MessageBox.Show(string.Format(
"The {0} shell extension was registered.",
Program.KeyName), Program.KeyName);
return true;
}
// unregister
if (string.Compare(args[0], "-unregister", true) == 0)
{
// unregister the context menu
FileShellExtension.Unregister(Program.FileType, Program.KeyName);
MessageBox.Show(string.Format(
"The {0} shell extension was unregistered.",
Program.KeyName), Program.KeyName);
return true;
}
// command line did not contain an action
return false;
}
/// <summary>
/// Make a grayscale copy of the image.
/// </summary>
/// <param name="filePath">Full path to the image to copy.</param>
static void CopyGrayscaleImage(string filePath)
{
try
{
// full path to the grayscale copy
string grayFilePath = Path.Combine(
Path.GetDirectoryName(filePath),
string.Format("{0} (grayscale){1}",
Path.GetFileNameWithoutExtension(filePath),
Path.GetExtension(filePath)));
// using calls Dispose on the objects, important
// so the file is not locked when the app terminates
using (Image image = new Bitmap(filePath))
using (Bitmap grayImage = new Bitmap(image.Width, image.Height))
using (Graphics g = Graphics.FromImage(grayImage))
{
// setup grayscale matrix
ImageAttributes attr = new ImageAttributes();
attr.SetColorMatrix(new ColorMatrix(new float[][]{
new float[]{0.3086F,0.3086F,0.3086F,0,0},
new float[]{0.6094F,0.6094F,0.6094F,0,0},
new float[]{0.082F,0.082F,0.082F,0,0},
new float[]{0,0,0,1,0,0},
new float[]{0,0,0,0,1,0},
new float[]{0,0,0,0,0,1}}));
// create the grayscale image
g.DrawImage(image, new Rectangle(0, 0, image.Width, image.Height),
0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attr);
// save to the file system
grayImage.Save(grayFilePath, ImageFormat.Jpeg);
// success
MessageBox.Show(string.Format("Copied grayscale image {0}", grayFilePath), Program.KeyName);
}
}
catch (Exception ex)
{
MessageBox.Show(string.Format("An error occurred: {0}", ex.Message), Program.KeyName);
return;
}
}
private static Bitmap ResizeImages(String filename, int maxWidth, int maxHeight)
{
using (Image originalImage = Image.FromFile(filename))
{
//Caluate new Size
int newWidth = originalImage.Width;
int newHeight = originalImage.Height;
double aspectRatio = (double)originalImage.Width / (double)originalImage.Height;
if (aspectRatio <= 1 && originalImage.Width > maxWidth)
{
newWidth = maxWidth;
newHeight = (int)Math.Round(newWidth / aspectRatio);
}
else if (aspectRatio > 1 && originalImage.Height > maxHeight)
{
newHeight = maxHeight;
newWidth = (int)Math.Round(newHeight * aspectRatio);
}
if (newWidth >= 0 && newHeight >= 0)
{
Bitmap newImage = new Bitmap(newWidth, newHeight);
using (Graphics g = Graphics.FromImage(newImage))
{
//--Quality Settings Adjust to fit your application
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.DrawImage(originalImage, 0, 0, newImage.Width, newImage.Height);
return newImage;
}
}
return null;
}
}
}
}
和FileShellExtension.cs
using System;
using System.Diagnostics;
using Microsoft.Win32;
namespace SimpleContextMenu
{
/// <summary>
/// Register and unregister simple shell context menus.
/// </summary>
static class FileShellExtension
{
/// <summary>
/// Register a simple shell context menu.
/// </summary>
/// <param name="fileType">The file type to register.</param>
/// <param name="shellKeyName">Name that appears in the registry.</param>
/// <param name="menuText">Text that appears in the context menu.</param>
/// <param name="menuCommand">Command line that is executed.</param>
public static void Register(
string fileType, string shellKeyName,
string menuText, string menuCommand)
{
Debug.Assert(!string.IsNullOrEmpty(fileType) &&
!string.IsNullOrEmpty(shellKeyName) &&
!string.IsNullOrEmpty(menuText) &&
!string.IsNullOrEmpty(menuCommand));
// create full path to registry location
string regPath = string.Format(@"{0}\shell\{1}", fileType, shellKeyName);
// add context menu to the registry
using (RegistryKey key = Registry.ClassesRoot.CreateSubKey(regPath))
{
key.SetValue(null, menuText);
}
// add command that is invoked to the registry
using (RegistryKey key = Registry.ClassesRoot.CreateSubKey(
string.Format(@"{0}\command", regPath)))
{
key.SetValue(null, menuCommand);
}
}
/// <summary>
/// Unregister a simple shell context menu.
/// </summary>
/// <param name="fileType">The file type to unregister.</param>
/// <param name="shellKeyName">Name that was registered in the registry.</param>
public static void Unregister(string fileType, string shellKeyName)
{
Debug.Assert(!string.IsNullOrEmpty(fileType) &&
!string.IsNullOrEmpty(shellKeyName));
// full path to the registry location
string regPath = string.Format(@"{0}\shell\{1}", fileType, shellKeyName);
// remove context menu from the registry
Registry.ClassesRoot.DeleteSubKeyTree(regPath);
}
}
}
更新
這就是我現在嘗試過的。 在Program.cs中,我添加了Main方法:
else if (action == "Share")
{
// create full path to registry location under the key you created
string regSubPath = string.Format(@"{0}\shell\{1}\Share", FileType, KeyName2);
// add context menu to the registry
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.ClassesRoot.CreateSubKey(regSubPath))
{
key.SetValue(null, "Tapuz");
}
}
但是,當我單擊“共享媒體”時,它沒有顯示子菜單。最好在文件瀏覽器中執行操作,即在第二秒打開子菜單而不單擊它時將鼠標移到上下文菜單上。
例如:發送到有一個菜單發送到,當您將鼠標移到它上面時,向右帶有一個黑色的小箭頭,這將打開一個子上下文菜單。
查看此問題和官方文檔 (以及您的代碼),我認為您只需要在注冊表中“共享”菜單項下的路徑中創建菜單項即可。
換句話說,如果要打開regedit並瀏覽到相關分支(HKEY_CLASSES_ROOT.fileType \\ Shell \\ Share)並添加Tapuz,則會將子菜單添加到Windows資源管理器中。 為此的命令是(可能)是:
using (RegistryKey key = Registry.ClassesRoot.CreateSubKey(regPath))
{
key.SetValue(null, "Tapuz");
}
我假設您所討論的條件(如果action == share)是用於設置回調的。 換句話說,如果您單擊共享,將會運行什么。 由於share是子菜單的標題,所以我會說這不是必需的。
================================================== ======================
無論如何,請始終對照注冊表中的內容檢查程序輸出,因為它應該在注冊表中反映出來,並與已知的內容進行比較,例如open with ...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.