簡體   English   中英

如何使用Shell文件擴展名將子上下文菜單添加到注冊的上下文菜單?

[英]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是子菜單的標題,所以我會說這不是必需的。

================================================== ======================

  1. 打開regedit並瀏覽到相關位置。 查看您是否可以看到共享,tapuz,fb,復制到gs並調整大小作為鍵。
  2. 如果您看到其中的一些,請添加缺少的內容,然后查看資源管理器是否表現更好。
  3. 完成后,刪除密鑰,並嘗試使用FileShellExtension.cs:register從代碼中進行操作。
  4. 如果可行,則可以轉到SimpleContextMenu和函數回調。

無論如何,請始終對照注冊表中的內容檢查程序輸出,因為它應該在注冊表中反映出來,並與已知的內容進行比較,例如open with ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM