소스 검색

更新3.3版本

蓝点lilac 4 년 전
부모
커밋
0f5ab25c9e
73개의 변경된 파일1949개의 추가작업 그리고 1207개의 파일을 삭제
  1. 1 1
      ContextMenuManager/App.config
  2. 36 33
      ContextMenuManager/AppConfig.cs
  3. 0 37
      ContextMenuManager/AppDic.cs
  4. 5 0
      ContextMenuManager/AppImage.cs
  5. 26 17
      ContextMenuManager/AppString.cs
  6. 95 0
      ContextMenuManager/BluePointLilac.Controls/DownloadDialog.cs
  7. 4 3
      ContextMenuManager/BluePointLilac.Controls/MyListBox.cs
  8. 2 1
      ContextMenuManager/BluePointLilac.Controls/SelectDialog.cs
  9. 14 0
      ContextMenuManager/BluePointLilac.Methods/ComboBoxExtension.cs
  10. 14 17
      ContextMenuManager/BluePointLilac.Methods/ElevatedFileDroper.cs
  11. 3 4
      ContextMenuManager/BluePointLilac.Methods/ExternalProgram.cs
  12. 21 5
      ContextMenuManager/BluePointLilac.Methods/FileExtension.cs
  13. 5 5
      ContextMenuManager/BluePointLilac.Methods/RichTextBoxExtension.cs
  14. 41 14
      ContextMenuManager/BluePointLilac.Methods/SingleInstance.cs
  15. 0 4
      ContextMenuManager/BluePointLilac.Methods/WinXHasher.cs
  16. 13 4
      ContextMenuManager/ContextMenuManager.csproj
  17. 97 62
      ContextMenuManager/Controls/AboutApp.cs
  18. 98 0
      ContextMenuManager/Controls/DonateListDialog.cs
  19. 6 0
      ContextMenuManager/Controls/EnhanceMenusItem.cs
  20. 49 18
      ContextMenuManager/Controls/EnhanceMenusList.cs
  21. 2 1
      ContextMenuManager/Controls/FileExtensionDialog.cs
  22. 2 2
      ContextMenuManager/Controls/GuidBlockedItem.cs
  23. 2 2
      ContextMenuManager/Controls/GuidBlockedList.cs
  24. 1 1
      ContextMenuManager/Controls/IEItem.cs
  25. 1 1
      ContextMenuManager/Controls/Interfaces/IBtnDeleteItem.cs
  26. 18 9
      ContextMenuManager/Controls/Interfaces/IFoldGroupItem.cs
  27. 1 0
      ContextMenuManager/Controls/Interfaces/ITsiAdministratorItem.cs
  28. 1 1
      ContextMenuManager/Controls/Interfaces/ITsiCommandItem.cs
  29. 2 2
      ContextMenuManager/Controls/Interfaces/ITsiDeleteItem.cs
  30. 10 3
      ContextMenuManager/Controls/Interfaces/ITsiFilePathItem.cs
  31. 2 2
      ContextMenuManager/Controls/Interfaces/ITsiGuidItem.cs
  32. 2 2
      ContextMenuManager/Controls/Interfaces/ITsiTextItem.cs
  33. 2 2
      ContextMenuManager/Controls/NewIEDialog.cs
  34. 4 4
      ContextMenuManager/Controls/NewLnkFileDialog.cs
  35. 4 4
      ContextMenuManager/Controls/NewOpenWithDialog.cs
  36. 2 2
      ContextMenuManager/Controls/NewShellDialog.cs
  37. 1 1
      ContextMenuManager/Controls/OpenWithItem.cs
  38. 4 4
      ContextMenuManager/Controls/ShellExItem.cs
  39. 6 6
      ContextMenuManager/Controls/ShellItem.cs
  40. 223 111
      ContextMenuManager/Controls/ShellList.cs
  41. 15 8
      ContextMenuManager/Controls/ShellNewItem.cs
  42. 2 2
      ContextMenuManager/Controls/ShellNewList.cs
  43. 1 1
      ContextMenuManager/Controls/ShellStoreDialog.cs
  44. 9 13
      ContextMenuManager/Controls/ShellSubMenuDialog.cs
  45. 142 100
      ContextMenuManager/Controls/ThirdRulesList.cs
  46. 2 2
      ContextMenuManager/Controls/TranslateDialog.cs
  47. 22 10
      ContextMenuManager/Controls/UwpModeItem.cs
  48. 2 2
      ContextMenuManager/Controls/WinXGroupItem.cs
  49. 1 2
      ContextMenuManager/Controls/WinXItem.cs
  50. 1 1
      ContextMenuManager/Controls/WinXList.cs
  51. 19 6
      ContextMenuManager/GuidInfo.cs
  52. 7 2
      ContextMenuManager/MainForm.cs
  53. 3 6
      ContextMenuManager/Program.cs
  54. 2 2
      ContextMenuManager/Properties/AssemblyInfo.cs
  55. 19 12
      ContextMenuManager/Properties/Resources.Designer.cs
  56. 6 3
      ContextMenuManager/Properties/Resources.resx
  57. BIN
      ContextMenuManager/Properties/Resources/Images/User.png
  58. 59 49
      ContextMenuManager/Properties/Resources/Texts/AppLanguageDic.ini
  59. 68 3
      ContextMenuManager/Properties/Resources/Texts/EnhanceMenusDic.xml
  60. 395 372
      ContextMenuManager/Properties/Resources/Texts/GuidInfosDic.ini
  61. 28 16
      ContextMenuManager/Properties/Resources/Texts/ThirdRulesDic.xml
  62. 10 10
      ContextMenuManager/Properties/Resources/Texts/UwpModeItemsDic.xml
  63. 154 43
      ContextMenuManager/Updater.cs
  64. 59 47
      Donate.md
  65. 2 2
      README-en.md
  66. 3 8
      README.md
  67. 0 0
      Screenshot/AppImage.png
  68. 0 0
      Screenshot/Screenshot-en.png
  69. 0 0
      Screenshot/Screenshot.png
  70. 5 3
      Update.ini
  71. 23 31
      languages/en-US.ini
  72. 11 17
      languages/ja-JP.ini
  73. 59 49
      languages/zh-CN.ini

+ 1 - 1
ContextMenuManager/App.config

@@ -2,7 +2,7 @@
 <configuration>
   <startup>
     
-  <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>
+  <supportedRuntime version="v2.0.50727"/></startup>
   <runtime>
     <legacyCorruptedStateExceptionsPolicy enabled="true"/>
     <EnableWindowsFormsHighDpiAutoResizing enabled="true"/>

+ 36 - 33
ContextMenuManager/AppConfig.cs

@@ -2,7 +2,6 @@
 using System;
 using System.Globalization;
 using System.IO;
-using System.Runtime.InteropServices;
 using System.Windows.Forms;
 
 namespace ContextMenuManager
@@ -17,9 +16,6 @@ namespace ContextMenuManager
             }
         }
 
-        [DllImport("kernel32.dll")]
-        private static extern ushort GetUserDefaultUILanguage();
-
         public static readonly string AppConfigDir = $@"{Application.StartupPath}\Config";
         public static readonly string AppDataConfigDir = Environment.ExpandEnvironmentVariables(@"%AppData%\ContextMenuManager\Config");
         public static readonly string ConfigDir = Directory.Exists(AppConfigDir) ? AppConfigDir : AppDataConfigDir;
@@ -31,15 +27,17 @@ namespace ContextMenuManager
         public static string DicsDir = $@"{ConfigDir}\Dictionaries";
         public static string WebDicsDir = $@"{DicsDir}\Web";
         public static string UserDicsDir = $@"{DicsDir}\User";
+
         public static string WebGuidInfosDic = $@"{WebDicsDir}\{GUIDINFOSDICINI}";
-        public static string UserGuidInfosDic = $@"{UserDicsDir}\{GUIDINFOSDICINI}";
         public static string WebThirdRulesDic = $@"{WebDicsDir}\{THIRDRULESDICXML}";
-        public static string UserThirdRulesDic = $@"{UserDicsDir}\{THIRDRULESDICXML}";
         public static string WebEnhanceMenusDic = $@"{WebDicsDir}\{ENHANCEMENUSICXML}";
-        public static string UserEnhanceMenusDic = $@"{WebDicsDir}\{ENHANCEMENUSICXML}";
-        public static string WebUwpModeItemsDic = $@"{UserDicsDir}\{UWPMODEITEMSDICXML}";
+        public static string WebUwpModeItemsDic = $@"{WebDicsDir}\{UWPMODEITEMSDICXML}";
+
+        public static string UserGuidInfosDic = $@"{UserDicsDir}\{GUIDINFOSDICINI}";
+        public static string UserThirdRulesDic = $@"{UserDicsDir}\{THIRDRULESDICXML}";
+        public static string UserEnhanceMenusDic = $@"{UserDicsDir}\{ENHANCEMENUSICXML}";
         public static string UserUwpModeItemsDic = $@"{UserDicsDir}\{UWPMODEITEMSDICXML}";
-        public static string HashLnkExePath = $@"{ProgramsDir}\HashLnk.exe";
+
         public const string ZH_CNINI = "zh-CN.ini";
         public const string GUIDINFOSDICINI = "GuidInfosDic.ini";
         public const string THIRDRULESDICXML = "ThirdRulesDic.xml";
@@ -48,9 +46,10 @@ namespace ContextMenuManager
 
         public static readonly string[] EngineUrls =
         {
-            "https://www.baidu.com/s?wd=%s",          //百度搜索
             "https://www.bing.com/search?q=%s",       //必应搜索
+            "https://www.baidu.com/s?wd=%s",          //百度搜索
             "https://www.google.com/search?q=%s",     //谷歌搜索
+            "https://duckduckgo.com/?q=%s",           //DuckDuckGo
             "https://www.dogedoge.com/results?q=%s",  //多吉搜索
             "https://www.sogou.com/web?query=%s",     //搜狗搜索
             "https://www.so.com/s?q=%s",              //360搜索
@@ -68,7 +67,7 @@ namespace ContextMenuManager
                 string language = GetGeneralValue("Language");
                 if(language == string.Empty)
                 {
-                    language = new CultureInfo(GetUserDefaultUILanguage()).Name;
+                    language = CultureInfo.CurrentUICulture.Name;
                 }
                 if(!File.Exists($@"{LangsDir}\{language}.ini"))
                 {
@@ -97,14 +96,11 @@ namespace ContextMenuManager
                 }
                 catch
                 {
-                    //将上次检测更新时间推前到两个月前
-                    return DateTime.Today.AddMonths(-2);
+                    //返回文件上次修改时间
+                    return new FileInfo(Application.ExecutablePath).LastWriteTime;
                 }
             }
-            set
-            {
-                SetGeneralValue("LastCheckUpdateTime", value.ToBinary());
-            }
+            set => SetGeneralValue("LastCheckUpdateTime", value.ToBinary());
         }
 
         public static bool ProtectOpenItem
@@ -121,10 +117,7 @@ namespace ContextMenuManager
                 if(url.IsNullOrWhiteSpace()) url = EngineUrls[0];
                 return url;
             }
-            set
-            {
-                SetGeneralValue("EngineUrl", value);
-            }
+            set => SetGeneralValue("EngineUrl", value);
         }
 
         public static bool ShowFilePath
@@ -145,25 +138,35 @@ namespace ContextMenuManager
             set => SetGeneralValue("OpenMoreRegedit", value ? 1 : 0);
         }
 
-        public static Version Version
+        public static bool HideDisabledItems
+        {
+            get => GetGeneralValue("HideDisabledItems") == "1";
+            set => SetGeneralValue("HideDisabledItems", value ? 1 : 0);
+        }
+
+        public static bool RequestUseGithub
         {
             get
             {
-                Version version = new Version(0, 0, 0, 0);
-                try { version = new Version(GetGeneralValue("Version")); }
-                catch { }
-                return version;
-            }
-            set
-            {
-                SetGeneralValue("Version", value);
+                if(GetGeneralValue("RequestUseGithub") == "1") return true;
+                if(CultureInfo.CurrentCulture.Name == "zh-CN") return false;
+                return true;
             }
+            set => SetGeneralValue("RequestUseGithub", value ? 1 : 0);
         }
 
-        public static bool HideDisabledItems
+        public static int UpdateFrequency
         {
-            get => GetGeneralValue("HideDisabledItems") == "1";
-            set => SetGeneralValue("HideDisabledItems", value ? 1 : 0);
+            get
+            {
+                string value = GetGeneralValue("UpdateFrequency");
+                if(int.TryParse(value, out int day))
+                {
+                    if(day == -1 || day == 7 || day == 90) return day;
+                }
+                return 30;
+            }
+            set => SetGeneralValue("UpdateFrequency", value);
         }
     }
 }

+ 0 - 37
ContextMenuManager/AppDic.cs

@@ -1,37 +0,0 @@
-using BluePointLilac.Methods;
-using System.IO;
-using System.Xml;
-
-namespace ContextMenuManager
-{
-    static class AppDic
-    {
-        public static XmlDocument ReadXml(string webDicPath, string userDicPath, string appDic)
-        {
-            XmlDocument doc1 = new XmlDocument();
-            try
-            {
-                if(File.Exists(webDicPath))
-                {
-                    doc1.LoadXml(File.ReadAllText(webDicPath, EncodingType.GetType(webDicPath)));
-                }
-                else
-                {
-                    doc1.LoadXml(appDic);
-                }
-                if(File.Exists(userDicPath))
-                {
-                    XmlDocument doc2 = new XmlDocument();
-                    doc2.LoadXml(File.ReadAllText(userDicPath, EncodingType.GetType(userDicPath)));
-                    foreach(XmlNode xn in doc2.DocumentElement.ChildNodes)
-                    {
-                        XmlNode node = doc1.ImportNode(xn, true);
-                        doc1.DocumentElement.AppendChild(node);
-                    }
-                }
-            }
-            catch { }
-            return doc1;
-        }
-    }
-}

+ 5 - 0
ContextMenuManager/AppImage.cs

@@ -1,6 +1,7 @@
 using BluePointLilac.Methods;
 using ContextMenuManager.Properties;
 using System.Drawing;
+using System.Windows.Forms;
 
 namespace ContextMenuManager
 {
@@ -55,6 +56,10 @@ namespace ContextMenuManager
         public static readonly Image Jump = Resources.Jump.ResizeImage(Scale);
         ///<summary>Microsoft Store</summary>
         public static readonly Image MicrosoftStore = Resources.MicrosoftStore.ResizeImage(Scale);
+        ///<summary>用户</summary>
+        public static readonly Image User = Resources.User.ResizeImage(Scale);
+        ///<summary>程序图标</summary>
+        public static readonly Image App = Icon.ExtractAssociatedIcon(Application.ExecutablePath).ToBitmap();
         ///<summary>系统文件</summary>
         public static readonly Image SystemFile = GetIconImage("imageres.dll", -67);
         ///<summary>资源不存在</summary>

+ 26 - 17
ContextMenuManager/AppString.cs

@@ -1,5 +1,4 @@
 using BluePointLilac.Methods;
-using System;
 using System.Text;
 
 namespace ContextMenuManager
@@ -13,7 +12,7 @@ namespace ContextMenuManager
         {
             string value = UserLanguage.GetValue(section, key);
             if(string.IsNullOrEmpty(value)) value = DefaultLanguage.GetValue(section, key);
-            return value.Replace("\\n", Environment.NewLine);
+            return value.Replace("\\r\\n", "\r\n").Replace("\\n", "\n");
         }
 
         /// <summary>常规</summary>
@@ -69,6 +68,7 @@ namespace ContextMenuManager
             public static string CustomRegPath => GetValue("CustomRegPath");
             public static string IEMenu => GetValue("IEMenu");
             public static string AppSetting => GetValue("AppSetting");
+            public static string CheckUpdate => GetValue("CheckUpdate");
             public static string AboutApp => GetValue("AboutApp");
             public static string Dictionaries => GetValue("Dictionaries");
             public static string AppLanguage => GetValue("AppLanguage");
@@ -188,21 +188,28 @@ namespace ContextMenuManager
             public static string SelectExtension => GetValue("SelectExtension");
             public static string SelectPerceivedType => GetValue("SelectPerceivedType");
             public static string SelectDirectoryType => GetValue("SelectDirectoryType");
-            public static string SelectSubMenuMode => GetValue("SelectSubMenuMode");
             public static string SelectNewItemType => GetValue("SelectNewItemType");
             public static string RegistryFile => GetValue("RegistryFile");
             public static string SelectGroup => GetValue("SelectGroup");
             public static string SelectObjectType => GetValue("SelectObjectType");
+            public static string SelectDropEffect => GetValue("SelectDropEffect");
+            public static string DefaultDropEffect => GetValue("DefaultDropEffect");
+            public static string CopyDropEffect => GetValue("CopyDropEffect");
+            public static string MoveDropEffect => GetValue("MoveDropEffect");
+            public static string CreateLinkDropEffect => GetValue("CreateLinkDropEffect");
+            public static string DownloadLanguages => GetValue("DownloadLanguages");
             public static string TranslateTool => GetValue("TranslateTool");
             public static string DefaultText => GetValue("DefaultText");
             public static string OldTranslation => GetValue("OldTranslation");
             public static string NewTranslation => GetValue("NewTranslation");
+            public static string SelectSubMenuMode => GetValue("SelectSubMenuMode");
+            public static string DonateInfo => GetValue("DonateInfo");
         }
 
-        /// <summary>消息</summary>
-        public static class MessageBox
+        /// <summary>消息</summary>
+        public static class Message
         {
-            private static string GetValue(string key) => GetStringValue("MessageBox", key);
+            private static string GetValue(string key) => GetStringValue("Message", key);
             public static string TextCannotBeEmpty => GetValue("TextCannotBeEmpty");
             public static string CommandCannotBeEmpty => GetValue("CommandCannotBeEmpty");
             public static string StringParsingFailed => GetValue("StringParsingFailed");
@@ -225,10 +232,11 @@ namespace ContextMenuManager
             public static string PromptIsOpenItem => GetValue("PromptIsOpenItem");
             public static string SelectRegPath => GetValue("SelectRegPath");
             public static string RestartApp => GetValue("RestartApp");
-            public static string UpdateApp => GetValue("UpdateApp");
+            public static string UpdateInfo => GetValue("UpdateInfo");
+            public static string UpdateSucceeded => GetValue("UpdateSucceeded");
             public static string FileNotExists => GetValue("FileNotExists");
             public static string FolderNotExists => GetValue("FolderNotExists");
-            public static string NoUpdateDetected => GetValue("NoUpdateDetected");
+            public static string VersionIsLatest => GetValue("VersionIsLatest");
             public static string AuthorityProtection => GetValue("AuthorityProtection");
             public static string WinXSorted => GetValue("WinXSorted");
             public static string RestoreDefault => GetValue("RestoreDefault");
@@ -266,8 +274,10 @@ namespace ContextMenuManager
             public static string Separator => GetValue("Separator");
             public static string LockNewMenu => GetValue("LockNewMenu");
             public static string RestartExplorer => GetValue("RestartExplorer");
+            public static string UserDictionaries => GetValue("UserDictionaries");
             public static string DictionaryDescription => GetValue("DictionaryDescription");
             public static string GuidInfosDictionary => GetValue("GuidInfosDictionary");
+            public static string UWPMode => GetValue("UWPMode");
             public static string Translators => GetValue("Translators");
             public static string AboutApp => GetValue("AboutApp");
             public static string Dictionaries => GetValue("Dictionaries");
@@ -276,11 +286,14 @@ namespace ContextMenuManager
             public static string ConfigPath => GetValue("ConfigPath");
             public static string AppDataDir => GetValue("AppDataDir");
             public static string AppDir => GetValue("AppDir");
-            public static string OpenConfigDir => GetValue("OpenConfigDir");
             public static string AutoBackup => GetValue("AutoBackup");
-            public static string OpenBackupDir => GetValue("OpenBackupDir");
-            public static string CheckUpdate => GetValue("CheckUpdate");
-            public static string ImmediatelyCheckUpdate => GetValue("ImmediatelyCheckUpdate");
+            public static string SetUpdateFrequency => GetValue("SetUpdateFrequency");
+            public static string OnceAWeek => GetValue("OnceAWeek");
+            public static string OnceAMonth => GetValue("OnceAMonth");
+            public static string OnceASeason => GetValue("OnceASeason");
+            public static string NeverCheck => GetValue("NeverCheck");
+            public static string SetRequestRepo => GetValue("SetRequestRepo");
+            public static string ImmediatelyCheck => GetValue("ImmediatelyCheck");
             public static string ProtectOpenItem => GetValue("ProtectOpenItem");
             public static string WebSearchEngine => GetValue("WebSearchEngine");
             public static string CustomEngine => GetValue("CustomEngine");
@@ -290,6 +303,7 @@ namespace ContextMenuManager
             public static string OpenMoreRegedit => GetValue("OpenMoreRegedit");
             public static string HideDisabledItems => GetValue("HideDisabledItems");
             public static string SetPerceivedType => GetValue("SetPerceivedType");
+            public static string SetDefaultDropEffect => GetValue("SetDefaultDropEffect");
         }
 
         /// <summary>提示文本</summary>
@@ -307,11 +321,6 @@ namespace ContextMenuManager
             public static string AddFromParentMenu => GetValue("AddFromParentMenu");
             public static string DeleteGuidDic => GetValue("DeleteGuidDic");
             public static string LockNewMenu => GetValue("LockNewMenu");
-            public static string CheckUpdate => GetValue("CheckUpdate");
-            public static string LastCheckUpdateTime => GetValue("LastCheckUpdateTime");
-            public static string OpenLanguagesDir => GetValue("OpenLanguagesDir");
-            public static string OtherLanguages => GetValue("OtherLanguages");
-            public static string OpenDictionariesDir => GetValue("OpenDictionariesDir");
             public static string ConfigPath => GetValue("ConfigPath");
             public static string CommandFiles => GetValue("CommandFiles");
             public static string CreateGroup => GetValue("CreateGroup");

+ 95 - 0
ContextMenuManager/BluePointLilac.Controls/DownloadDialog.cs

@@ -0,0 +1,95 @@
+using BluePointLilac.Methods;
+using ContextMenuManager;
+using System;
+using System.Drawing;
+using System.IO;
+using System.Net;
+using System.Windows.Forms;
+
+namespace BluePointLilac.Controls
+{
+    sealed class DownloadDialog : CommonDialog
+    {
+        public string Url { get; set; }
+        public string FilePath { get; set; }
+        public override void Reset() { }
+
+        protected override bool RunDialog(IntPtr hwndOwner)
+        {
+            using(DownloadForm frm = new DownloadForm())
+            {
+                frm.Url = this.Url;
+                frm.FilePath = this.FilePath;
+                bool flag = frm.ShowDialog() == DialogResult.OK;
+                if(!flag) File.Delete(FilePath);
+                return flag;
+            }
+        }
+
+        sealed class DownloadForm : Form
+        {
+            public DownloadForm()
+            {
+                this.MinimizeBox = this.MaximizeBox = false;
+                this.FormBorderStyle = FormBorderStyle.FixedSingle;
+                this.StartPosition = FormStartPosition.CenterParent;
+                this.Font = new Font(SystemFonts.MessageBoxFont.FontFamily, 9F);
+                this.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
+                this.Controls.AddRange(new Control[] { pgbDownload, btnCancel });
+                pgbDownload.Left = pgbDownload.Top = btnCancel.Top = 20.DpiZoom();
+                pgbDownload.Height = btnCancel.Height;
+                pgbDownload.Width = 200.DpiZoom();
+                btnCancel.Left = pgbDownload.Right + 20.DpiZoom();
+                this.ClientSize = new Size(btnCancel.Right + 20.DpiZoom(), btnCancel.Bottom + 20.DpiZoom());
+                this.Load += (sender, e) => DownloadFile(Url, FilePath);
+            }
+
+            readonly ProgressBar pgbDownload = new ProgressBar();
+            readonly Button btnCancel = new Button
+            {
+                DialogResult = DialogResult.Cancel,
+                Text = AppString.Dialog.Cancel,
+                AutoSize = true
+            };
+
+            public string Url { get; set; }
+            public string FilePath { get; set; }
+
+            private void DownloadFile(string url, string filePath)
+            {
+                try
+                {
+                    this.Activate();
+                    using(WebResponse response = WebRequest.Create(url).GetResponse())
+                    using(Stream webStream = response.GetResponseStream())
+                    using(FileStream fileStream = new FileStream(filePath, FileMode.Create))
+                    {
+                        double fullSize = response.ContentLength;
+                        pgbDownload.Maximum = (int)fullSize;
+                        double downloadedSize = 0;
+                        int incrementSize;
+                        do
+                        {
+                            if(this.DialogResult == DialogResult.Cancel) return;
+                            byte[] by = new byte[1024];
+                            incrementSize = webStream.Read(by, 0, by.Length);
+                            downloadedSize += incrementSize;
+                            fileStream.Write(by, 0, incrementSize);
+                            pgbDownload.Value = (int)downloadedSize;
+
+                            double downloaded = Math.Round(downloadedSize / fullSize * 100, 2);
+                            this.Text = $"Downloading: {downloaded}%";
+                            Application.DoEvents();
+                        } while(incrementSize > 0);
+                        this.DialogResult = DialogResult.OK;
+                    }
+                }
+                catch(Exception e)
+                {
+                    MessageBoxEx.Show(e.Message);
+                    this.DialogResult = DialogResult.Cancel;
+                }
+            }
+        }
+    }
+}

+ 4 - 3
ContextMenuManager/BluePointLilac.Controls/MyListBox.cs

@@ -67,10 +67,11 @@ namespace BluePointLilac.Controls
         public void AddItem(MyListItem item)
         {
             item.Parent = this;
-            item.Width = Owner.Width - item.Margin.Horizontal;
-            Owner.Resize += (sender, e) => item.Width = Owner.Width - item.Margin.Horizontal;
-            this.MouseWheel += (sender, e) => item.ContextMenuStrip?.Close();
             item.MouseEnter += (sender, e) => HoveredItem = item;
+            this.MouseWheel += (sender, e) => item.ContextMenuStrip?.Close();
+            void ResizeItem() => item.Width = Owner.Width - item.Margin.Horizontal;
+            Owner.Resize += (sender, e) => ResizeItem();
+            ResizeItem();
         }
 
         public void AddItems(MyListItem[] items)

+ 2 - 1
ContextMenuManager/Controls/SelectDialog.cs → ContextMenuManager/BluePointLilac.Controls/SelectDialog.cs

@@ -1,9 +1,10 @@
 using BluePointLilac.Methods;
+using ContextMenuManager;
 using System;
 using System.Drawing;
 using System.Windows.Forms;
 
-namespace ContextMenuManager.Controls
+namespace BluePointLilac.Controls
 {
     class SelectDialog : CommonDialog
     {

+ 14 - 0
ContextMenuManager/BluePointLilac.Methods/ComboBoxExtension.cs

@@ -17,6 +17,20 @@ namespace BluePointLilac.Methods
                 maxWidth = Math.Max(maxWidth, box.Width);
                 box.DropDownWidth = maxWidth;
             };
+            //ToolTip toolTip = new ToolTip() { AutoPopDelay = 0, InitialDelay = 0, ReshowDelay = 0, ShowAlways = true, };
+            //box.DrawMode = DrawMode.OwnerDrawFixed;
+            //box.DrawItem += (s, e) =>
+            //{
+            //    e.DrawBackground();
+            //    string text = box.GetItemText(box.Items[e.Index]);
+            //    using(SolidBrush br = new SolidBrush(e.ForeColor))
+            //        e.Graphics.DrawString(text, e.Font, br, e.Bounds);
+            //    if((e.State & DrawItemState.Selected) == DrawItemState.Selected && box.DroppedDown)
+            //        toolTip.Show(text, box, e.Bounds.Right, e.Bounds.Bottom + 4);
+            //    e.DrawFocusRectangle();
+            //};
+            //box.DropDownClosed += (s, e) =>
+            //    toolTip.Hide(box);
         }
     }
 }

+ 14 - 17
ContextMenuManager/BluePointLilac.Methods/ElevatedFileDroper.cs

@@ -74,13 +74,12 @@ namespace BluePointLilac.Methods
         public string[] DropFilePaths { get; private set; }
         public Point DropPoint { get; private set; }
 
-        public ElevatedFileDroper(Control containerControl)
+        public ElevatedFileDroper(Control ctr)
         {
-            this.ContainerControl = containerControl ?? throw new ArgumentNullException();
-            if(containerControl.IsDisposed) throw new ObjectDisposedException(containerControl.Name);
-            containerControl.DragDrop += (sender, e) => DropFilePaths = (string[])e.Data.GetData(typeof(string[]));
-            containerControl.DragEnter += (sender, e) => e.Effect = DragDropEffects.All;
-            containerControl.Disposed += (sender, e) => Application.RemoveMessageFilter(this);
+            this.ContainerControl = ctr;
+            ctr.DragDrop += (sender, e) => DropFilePaths = (string[])e.Data.GetData(typeof(string[]));
+            ctr.DragEnter += (sender, e) => e.Effect = DragDropEffects.All;
+            ctr.Disposed += (sender, e) => Application.RemoveMessageFilter(this);
 
             Version ver = Environment.OSVersion.Version;
             bool isVistaOrHigher = ver >= new Version(6, 0);
@@ -93,7 +92,7 @@ namespace BluePointLilac.Methods
                     bool error = false;
                     if(isWin7OrHigher)
                     {
-                        error = !ChangeWindowMessageFilterEx(containerControl.Handle, msg, ChangeFilterAction.MSGFLT_ALLOW, in status);
+                        error = !ChangeWindowMessageFilterEx(ctr.Handle, msg, ChangeFilterAction.MSGFLT_ALLOW, in status);
                     }
                     else
                     {
@@ -102,38 +101,36 @@ namespace BluePointLilac.Methods
                     if(error) throw new Win32Exception(Marshal.GetLastWin32Error());
                 }
             }
-            DragAcceptFiles(containerControl.Handle, true);
+            DragAcceptFiles(ctr.Handle, true);
             Application.AddMessageFilter(this);
         }
 
         public bool PreFilterMessage(ref Message m)
         {
-            if(ContainerControl == null || ContainerControl.IsDisposed) return false;
+            if(m.Msg != WM_DROPFILES) return false;
             if(ContainerControl.AllowDrop)
             {
                 DropPoint = ContainerControl.PointToClient(Cursor.Position);
-                ContainerControl.AllowDrop = false;
-                return false;
             }
-            if(m.Msg == WM_DROPFILES)
+            else
             {
                 IntPtr handle = m.WParam;
                 uint fileCount = DragQueryFile(handle, uint.MaxValue, null, 0);
                 string[] fileNames = new string[fileCount];
-                StringBuilder sb = new StringBuilder(260);
-                int charLength = sb.Capacity;
                 for(uint i = 0; i < fileCount; i++)
                 {
-                    if(DragQueryFile(handle, i, sb, charLength) > 0) fileNames[i] = sb.ToString();
+                    StringBuilder sb = new StringBuilder(260);
+                    uint result = DragQueryFile(handle, i, sb, sb.Capacity);
+                    if(result > 0) fileNames[i] = sb.ToString();
                 }
                 DragQueryPoint(handle, out Point point);
                 DragFinish(handle);
                 DropPoint = point;
                 ContainerControl.AllowDrop = true;
                 ContainerControl.DoDragDrop(fileNames, DragDropEffects.All);
-                return true;
             }
-            return false;
+            ContainerControl.AllowDrop = false;
+            return true;
         }
     }
 }

+ 3 - 4
ContextMenuManager/BluePointLilac.Methods/ExternalProgram.cs

@@ -18,7 +18,6 @@ namespace BluePointLilac.Methods
             {
                 GetWindowThreadProcessId(hMain, out int id);
                 process = Process.GetProcessById(id);
-
             }
             else
             {
@@ -71,17 +70,17 @@ namespace BluePointLilac.Methods
             process.Dispose();
         }
 
-        public static void JumpExplorer(string filePath, bool moreOpen = false)
+        public static void JumpExplorer(string filePath)
         {
             using(Process process = new Process())
             {
-                if(File.Exists(filePath))
+                if(File.Exists(filePath) || filePath.StartsWith("shell:AppsFolder"))
                 {
                     process.StartInfo.FileName = "explorer.exe";
                     process.StartInfo.Arguments = $"/select, {filePath}";
                     process.Start();
                 }
-                else if(Directory.Exists(filePath))
+                if(Directory.Exists(filePath))
                 {
                     process.StartInfo.FileName = filePath;
                     process.Start();

+ 21 - 5
ContextMenuManager/BluePointLilac.Methods/FileExtension.cs

@@ -63,12 +63,28 @@ namespace BluePointLilac.Methods
 
         public static string GetOpenMode(string extension)
         {
-            string mode = null;
-            if(string.IsNullOrEmpty(extension)) return mode;
-            mode = Registry.GetValue($@"{FileExtsPath}\{extension}\UserChoice", "ProgId", null)?.ToString();
+            if(string.IsNullOrEmpty(extension)) return null;
+            string mode = Registry.GetValue($@"{FileExtsPath}\{extension}\UserChoice", "ProgId", null)?.ToString();
             if(!string.IsNullOrEmpty(mode)) return mode;
-            mode = Registry.GetValue($@"HKEY_CLASSES_ROOT\{extension}", "", null)?.ToString();
-            return mode;
+            using(RegistryKey root = Registry.ClassesRoot)
+            using(RegistryKey exKey = root.OpenSubKey(extension))
+            {
+                if(exKey == null) return null;
+                mode = exKey.GetValue("")?.ToString();
+                if(!mode.IsNullOrWhiteSpace()) return mode;
+                using(RegistryKey pkey = exKey.OpenSubKey("OpenWithProgids"))
+                {
+                    if(pkey == null) return null;
+                    foreach(string name in pkey.GetValueNames())
+                    {
+                        using(RegistryKey mKey = root.OpenSubKey(name))
+                        {
+                            if(mKey.GetValue("") != null) return name;
+                        }
+                    }
+                }
+            }
+            return null;
         }
     }
 }

+ 5 - 5
ContextMenuManager/BluePointLilac.Methods/RichTextBoxExtension.cs

@@ -34,7 +34,7 @@ namespace BluePointLilac.Methods
                 string token = machine.GetNextToken(xmlStr.Substring(location), out XmlTokenType ttype);
                 Color color = machine.GetTokenColor(ttype);
                 bool isBold = ttype == XmlTokenType.DocTypeName || ttype == XmlTokenType.NodeName;
-                box.AppendText(token, color, isBold);
+                box.AppendText(token, color, null, isBold);
                 location += token.Length;
                 tokenTryCount++;
 
@@ -65,7 +65,7 @@ namespace BluePointLilac.Methods
                     if(str.Contains("]"))
                     {
                         int index = str.IndexOf(']');
-                        box.AppendText(str.Substring(0, index + 1), Color.DarkCyan, true);
+                        box.AppendText(str.Substring(0, index + 1), Color.DarkCyan, null, true);
                         box.AppendText(str.Substring(index + 1), Color.SkyBlue);
                     }
                     else box.AppendText(str, Color.SkyBlue);
@@ -81,13 +81,13 @@ namespace BluePointLilac.Methods
             }
         }
 
-        public static void AppendText(this RichTextBox box, string text, Color color, bool isBold = false)
+        public static void AppendText(this RichTextBox box, string text, Color color = default, Font font = null, bool isBold = false)
         {
             FontStyle fontStyle = isBold ? FontStyle.Bold : FontStyle.Regular;
-            box.SelectionFont = new Font(box.Font, fontStyle);
+            box.SelectionFont = new Font(font ?? box.Font, fontStyle);
+            box.SelectionColor = color != default ? color : box.ForeColor;
             box.SelectionStart = box.TextLength;
             box.SelectionLength = 0;
-            box.SelectionColor = color;
             box.AppendText(text);
             box.SelectionColor = box.ForeColor;
         }

+ 41 - 14
ContextMenuManager/BluePointLilac.Methods/SingleInstance.cs

@@ -2,12 +2,20 @@
 using System.Diagnostics;
 using System.IO;
 using System.Runtime.InteropServices;
+using System.Text;
 using System.Windows.Forms;
 
 namespace BluePointLilac.Methods
 {
     public static class SingleInstance
     {
+        [DllImport("user32.dll")]
+        private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
+
+        [DllImport("user32.dll")]
+        private static extern bool SetForegroundWindow(IntPtr hWnd);
+
+        /// <summary>判断单实例程序是否正在运行</summary>
         public static bool IsRunning()
         {
             using(Process current = Process.GetCurrentProcess())
@@ -31,23 +39,42 @@ namespace BluePointLilac.Methods
             }
         }
 
-        public static void Restart(bool isElevated = false, string[] args = null)
+        /// <summary>重启单实例程序</summary>
+        /// <param name="args">重启程序时传入参数</param>
+        /// <param name="updatePath">用于更新程序的新版本文件路径,为null则不更新</param>
+        public static void Restart(string[] args = null, string updatePath = null)
         {
-            using(Process process = new Process())
+            using(Process pApp = Process.GetCurrentProcess())
             {
-                process.StartInfo.FileName = Application.ExecutablePath;
-                process.StartInfo.Arguments = "Restart";
-                if(args != null) process.StartInfo.Arguments += string.Join(" ", args);
-                if(isElevated) process.StartInfo.Verb = "Runas";
-                process.Start();
-            }
-            Application.Exit();
-        }
+                string command = Application.ExecutablePath;
+                if(args != null && args.Length > 0) command += "," + string.Join(" ", args);
+                string contents =
+                    "Dim wsh, fso\r\n" +
+                    "Set wsh = CreateObject(\"WScript.Shell\")\r\n" +
+                    "Set fso = CreateObject(\"Scripting.FileSystemObject\")\r\n" +
+                    "fso.DeleteFile(WScript.ScriptFullName)\r\n" +  //vbs自删命令
+                    $"wsh.Run \"taskkill /pid {pApp.Id} -f\",0\r\n" +
+                    "WScript.Sleep 1000\r\n";
 
-        [DllImport("user32.dll")]
-        private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
+                if(updatePath != null) contents +=
+                    $"fso.DeleteFile \"{Application.ExecutablePath}\"\r\n" +
+                    "WScript.Sleep 1000\r\n" +
+                    $"fso.MoveFile \"{updatePath}\",\"{Application.ExecutablePath}\"\r\n";
 
-        [DllImport("user32.dll")]
-        private static extern bool SetForegroundWindow(IntPtr hWnd);
+                contents +=
+                    $"wsh.Run \"{command}\"\r\n" +
+                    "Set wsh = Nothing\r\n" +
+                    "Set fso = Nothing\r\n";
+
+                string vbsPath = Path.GetTempPath() + "Restart.vbs";
+                File.WriteAllText(vbsPath, contents, Encoding.Unicode);
+                using(Process pVbs = new Process())
+                {
+                    pVbs.StartInfo.FileName = "wscript.exe";
+                    pVbs.StartInfo.Arguments = vbsPath;
+                    pVbs.Start();
+                }
+            }
+        }
     }
 }

+ 0 - 4
ContextMenuManager/BluePointLilac.Methods/WinXHasher.cs

@@ -23,9 +23,6 @@ namespace BluePointLilac.Methods
         private static extern uint SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string pszPath,
         IBindCtx pbc, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IShellItem ppv);
 
-        [DllImport("ole32.dll", PreserveSig = false)]
-        private extern static void PropVariantClear([In, Out] PropVariant pvar);
-
         [DllImport("propsys.dll", CharSet = CharSet.Unicode, SetLastError = true)]
         private static extern int PSGetPropertyKeyFromName([In][MarshalAs(UnmanagedType.LPWStr)] string pszCanonicalName, out PropertyKey propkey);
 
@@ -292,7 +289,6 @@ namespace BluePointLilac.Methods
 
             Marshal.ReleaseComObject(store);
             Marshal.ReleaseComObject(item);
-            PropVariantClear(pv);
         }
 
         private static readonly Dictionary<string, string> GeneralizePathDic = new Dictionary<string, string>

+ 13 - 4
ContextMenuManager/ContextMenuManager.csproj

@@ -8,7 +8,7 @@
     <OutputType>WinExe</OutputType>
     <RootNamespace>ContextMenuManager</RootNamespace>
     <AssemblyName>ContextMenuManager</AssemblyName>
-    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
     <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
     <Deterministic>true</Deterministic>
@@ -34,7 +34,7 @@
     <PlatformTarget>AnyCPU</PlatformTarget>
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
-    <Optimize>true</Optimize>
+    <Optimize>false</Optimize>
     <OutputPath>bin\Debug\</OutputPath>
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
@@ -118,13 +118,15 @@
     <Reference Include="System.Data.DataSetExtensions" />
     <Reference Include="System.Deployment" />
     <Reference Include="System.Drawing" />
+    <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="System.ServiceModel.Web" />
+    <Reference Include="System.Web" />
     <Reference Include="System.Windows.Forms" />
     <Reference Include="System.Xml" />
     <Reference Include="System.Xml.Linq" />
   </ItemGroup>
   <ItemGroup>
     <Compile Include="AppConfig.cs" />
-    <Compile Include="AppDic.cs" />
     <Compile Include="BluePointLilac.Controls\MyToolTip.cs" />
     <Compile Include="BluePointLilac.Controls\ReadOnlyTextBox.cs">
       <SubType>Component</SubType>
@@ -152,6 +154,12 @@
     <Compile Include="BluePointLilac.Methods\WindowsOsVersion.cs" />
     <Compile Include="BluePointLilac.Methods\ShellLink.cs" />
     <Compile Include="BluePointLilac.Methods\WinXHasher.cs" />
+    <Compile Include="BluePointLilac.Controls\DownloadDialog.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="Controls\DonateListDialog.cs">
+      <SubType>Component</SubType>
+    </Compile>
     <Compile Include="Controls\FileExtensionDialog.cs">
       <SubType>Component</SubType>
     </Compile>
@@ -188,7 +196,7 @@
     <Compile Include="Controls\NewLnkFileDialog.cs">
       <SubType>Component</SubType>
     </Compile>
-    <Compile Include="Controls\SelectDialog.cs">
+    <Compile Include="BluePointLilac.Controls\SelectDialog.cs">
       <SubType>Component</SubType>
     </Compile>
     <Compile Include="Controls\ShellExecuteDialog.cs">
@@ -361,6 +369,7 @@
     <Content Include="Properties\Resources\Images\DownLoad.png" />
     <Content Include="Properties\Resources\Images\Jump.png" />
     <Content Include="Properties\Resources\Images\Translate.png" />
+    <Content Include="Properties\Resources\Images\User.png" />
     <Content Include="Properties\Resources\Texts\UwpModeItemsDic.xml" />
     <None Include="Properties\Settings.settings">
       <Generator>SettingsSingleFileGenerator</Generator>

+ 97 - 62
ContextMenuManager/Controls/AboutApp.cs

@@ -11,8 +11,6 @@ namespace ContextMenuManager.Controls
 {
     sealed class DonateBox : Panel
     {
-        private const string DonateListUrl = "https://github.com/BluePointLilac/ContextMenuManager/blob/master/Donate.md";
-
         public DonateBox()
         {
             this.Dock = DockStyle.Fill;
@@ -20,7 +18,7 @@ namespace ContextMenuManager.Controls
             this.AutoScroll = true;
             this.Font = new Font(SystemFonts.MenuFont.FontFamily, 10F);
             this.Controls.AddRange(new Control[] { lblInfo, picQR, llbDonationList });
-            llbDonationList.LinkClicked += (sender, e) => ExternalProgram.OpenUrl(DonateListUrl);
+            llbDonationList.LinkClicked += (sender, e) => Updater.ShowDonateDialog();
         }
 
         readonly Label lblInfo = new Label
@@ -63,7 +61,7 @@ namespace ContextMenuManager.Controls
             this.Controls.AddRange(pages);
             this.Font = new Font(SystemFonts.MenuFont.FontFamily, 10F);
             cms.Items.AddRange(items);
-            for(int i = 0; i < 5; i++)
+            for(int i = 0; i < 6; i++)
             {
                 boxs[i] = new ReadOnlyRichTextBox { Parent = pages[i] };
                 if(i > 0) boxs[i].ContextMenuStrip = cms;
@@ -71,9 +69,11 @@ namespace ContextMenuManager.Controls
             items[0].Click += (sender, e) => ExternalProgram.OpenNotepadWithText(GetInitialText());
             items[2].Click += (sender, e) => SaveFile();
             boxs[0].Controls.Add(btnOpenDir);
+            boxs[0].Text = AppString.Other.Dictionaries;
             btnOpenDir.Top = boxs[0].Height - btnOpenDir.Height;
-            MyToolTip.SetToolTip(btnOpenDir, AppString.Tip.OpenDictionariesDir);
+            MyToolTip.SetToolTip(btnOpenDir, AppString.Menu.FileLocation);
             btnOpenDir.MouseDown += (sender, e) => ExternalProgram.JumpExplorer(AppConfig.DicsDir);
+            this.SelectedIndexChanged += (sender, e) => LoadText();
         }
 
         readonly TabPage[] pages = new TabPage[] {
@@ -81,9 +81,10 @@ namespace ContextMenuManager.Controls
             new TabPage(AppString.SideBar.AppLanguage),
             new TabPage(AppString.Other.GuidInfosDictionary),
             new TabPage(AppString.SideBar.ThirdRules),
-            new TabPage(AppString.SideBar.EnhanceMenu)
+            new TabPage(AppString.SideBar.EnhanceMenu),
+            new TabPage(AppString.Other.UWPMode)
         };
-        readonly ReadOnlyRichTextBox[] boxs = new ReadOnlyRichTextBox[5];
+        readonly ReadOnlyRichTextBox[] boxs = new ReadOnlyRichTextBox[6];
         readonly PictureButton btnOpenDir = new PictureButton(AppImage.Open)
         {
             Anchor = AnchorStyles.Left | AnchorStyles.Bottom,
@@ -116,6 +117,9 @@ namespace ContextMenuManager.Controls
                     case 4:
                         dlg.FileName = AppConfig.ENHANCEMENUSICXML;
                         break;
+                    case 5:
+                        dlg.FileName = AppConfig.UWPMODEITEMSDICXML;
+                        break;
                 }
                 dlg.Filter = $"{dlg.FileName}|*{Path.GetExtension(dlg.FileName)}";
                 Directory.CreateDirectory(dirPath);
@@ -131,6 +135,8 @@ namespace ContextMenuManager.Controls
         {
             switch(this.SelectedIndex)
             {
+                case 0:
+                    return AppString.Other.Dictionaries;
                 case 1:
                     return Properties.Resources.AppLanguageDic;
                 case 2:
@@ -139,39 +145,45 @@ namespace ContextMenuManager.Controls
                     return Properties.Resources.ThirdRulesDic;
                 case 4:
                     return Properties.Resources.EnhanceMenusDic;
+                case 5:
+                    return Properties.Resources.UwpModeItemsDic;
                 default:
                     return string.Empty;
             }
         }
 
-        bool hadLoaded = false;
-        public void LoadTexts()
+        private void LoadText()
         {
-            if(hadLoaded) return;
-            hadLoaded = true;
-            boxs[0].Text = AppString.Other.Dictionaries;
-            this.BeginInvoke(new Action<string>(boxs[1].LoadIni), new[] { Properties.Resources.AppLanguageDic });
-            this.BeginInvoke(new Action<string>(boxs[2].LoadIni), new[] { Properties.Resources.GuidInfosDic });
-            this.BeginInvoke(new Action<string>(boxs[3].LoadXml), new[] { Properties.Resources.ThirdRulesDic });
-            this.BeginInvoke(new Action<string>(boxs[4].LoadXml), new[] { Properties.Resources.EnhanceMenusDic });
+            int index = this.SelectedIndex;
+            if(boxs[index].Text.Length > 0) return;
+            Action<string> action = null;
+            switch(index)
+            {
+                case 1:
+                case 2:
+                    action = boxs[index].LoadIni; break;
+                case 3:
+                case 4:
+                case 5:
+                    action = boxs[index].LoadXml; break;
+            }
+            this.BeginInvoke(action, new[] { GetInitialText() });
         }
     }
 
     sealed class LanguagesBox : FlowLayoutPanel
     {
-        const string OtherLanguagesUrl = "https://github.com/BluePointLilac/ContextMenuManager/tree/master/languages";
-
         public LanguagesBox()
         {
             this.Dock = DockStyle.Fill;
             this.Font = new Font(SystemFonts.MenuFont.FontFamily, 10F);
             this.Controls.AddRange(new Control[] { cmbLanguages, btnOpenDir, btnDownLoad, btnTranslate, txtTranslators });
             cmbLanguages.SelectionChangeCommitted += (sender, e) => ChangeLanguage();
-            btnDownLoad.MouseDown += (sender, e) => ExternalProgram.OpenUrl(OtherLanguagesUrl);
+            btnDownLoad.MouseDown += (sender, e) => { if(Updater.ShowLanguageDialog()) LoadLanguages(); };
             btnOpenDir.MouseDown += (sender, e) => ExternalProgram.JumpExplorer(AppConfig.LangsDir);
             btnTranslate.MouseDown += (sender, e) => new TranslateDialog().ShowDialog();
-            MyToolTip.SetToolTip(btnOpenDir, AppString.Tip.OpenLanguagesDir);
-            MyToolTip.SetToolTip(btnDownLoad, AppString.Tip.OtherLanguages);
+            MyToolTip.SetToolTip(btnOpenDir, AppString.Menu.FileLocation);
+            MyToolTip.SetToolTip(btnDownLoad, AppString.Dialog.DownloadLanguages);
             MyToolTip.SetToolTip(btnTranslate, AppString.Dialog.TranslateTool);
             txtTranslators.SetAutoShowScroll(ScrollBars.Vertical);
             cmbLanguages.AutosizeDropDownWidth();
@@ -211,7 +223,7 @@ namespace ContextMenuManager.Controls
                 foreach(string fileName in Directory.GetFiles(AppConfig.LangsDir, "*.ini"))
                 {
                     string langName = Path.GetFileNameWithoutExtension(fileName);
-                    IniReader reader = new IniReader(fileName);
+                    IniWriter reader = new IniWriter(fileName);
                     string language = reader.GetValue("General", "Language");
                     if(language.IsNullOrWhiteSpace()) language = langName;
                     string translator = reader.GetValue("General", "Translator");
@@ -230,14 +242,14 @@ namespace ContextMenuManager.Controls
             int index = GetSelectIndex();
             if(cmbLanguages.SelectedIndex == index) return;
             if(cmbLanguages.SelectedIndex > 0) language = languages[cmbLanguages.SelectedIndex - 1];
-            if(MessageBoxEx.Show(AppString.MessageBox.RestartApp, MessageBoxButtons.OKCancel) != DialogResult.OK)
+            if(MessageBoxEx.Show(AppString.Message.RestartApp, MessageBoxButtons.OKCancel) != DialogResult.OK)
             {
                 cmbLanguages.SelectedIndex = index;
             }
             else
             {
                 AppConfig.Language = language;
-                SingleInstance.Restart(true);
+                SingleInstance.Restart();
             }
         }
 
@@ -254,15 +266,13 @@ namespace ContextMenuManager.Controls
 
     sealed class AppSettingBox : MyList
     {
-        private const string GithubUrl = "https://github.com/BluePointLilac/ContextMenuManager/releases";
-        private const string GiteeUrl = "https://gitee.com/BluePointLilac/ContextMenuManager/releases";
-
         public AppSettingBox()
         {
             this.Font = new Font(SystemFonts.MenuFont.FontFamily, 10F);
             mliConfigDir.AddCtrs(new Control[] { cmbConfigDir, btnConfigDir });
             mliBackup.AddCtrs(new Control[] { chkBackup, btnBackupDir });
-            mliUpdate.AddCtrs(new Control[] { lblGitee, lblGithub, lblUpdate });
+            mliUpdate.AddCtrs(new Control[] { cmbUpdate, lblUpdate });
+            mliRepo.AddCtr(cmbRepo);
             mliProtect.AddCtr(chkProtect);
             mliEngine.AddCtr(cmbEngine);
             mliWinXSortable.AddCtr(chkWinXSortable);
@@ -271,26 +281,27 @@ namespace ContextMenuManager.Controls
             mliHideDisabledItems.AddCtr(chkHideDisabledItems);
             cmbConfigDir.AutosizeDropDownWidth();
             cmbEngine.AutosizeDropDownWidth();
+            cmbRepo.AutosizeDropDownWidth();
             MyToolTip.SetToolTip(cmbConfigDir, AppString.Tip.ConfigPath);
-            MyToolTip.SetToolTip(btnConfigDir, AppString.Other.OpenConfigDir);
-            MyToolTip.SetToolTip(btnBackupDir, AppString.Other.OpenBackupDir);
-            MyToolTip.SetToolTip(mliUpdate, AppString.Tip.CheckUpdate + Environment.NewLine
-                + AppString.Tip.LastCheckUpdateTime + AppConfig.LastCheckUpdateTime.ToLongDateString());
+            MyToolTip.SetToolTip(btnConfigDir, AppString.Menu.FileLocation);
+            MyToolTip.SetToolTip(btnBackupDir, AppString.Menu.FileLocation);
+
+            cmbRepo.Items.AddRange(new[] { "Github", "Gitee" });
             cmbConfigDir.Items.AddRange(new[] { AppString.Other.AppDataDir, AppString.Other.AppDir });
-            cmbEngine.Items.AddRange(new[] { "Baidu", "Bing", "Google", "DogeDoge", "Sogou", "360", AppString.Other.CustomEngine });
+            cmbEngine.Items.AddRange(new[] { "Bing", "Baidu", "Google", "DuckDuckGo", "DogeDoge", "Sogou", "360", AppString.Other.CustomEngine });
+            cmbUpdate.Items.AddRange(new[] { AppString.Other.OnceAWeek, AppString.Other.OnceAMonth, AppString.Other.OnceASeason, AppString.Other.NeverCheck });
+
             btnConfigDir.MouseDown += (sender, e) => ExternalProgram.JumpExplorer(AppConfig.ConfigDir);
             btnBackupDir.MouseDown += (sender, e) => ExternalProgram.JumpExplorer(AppConfig.BackupDir);
-            lblGithub.Click += (sender, e) => ExternalProgram.OpenUrl(GithubUrl);
-            lblGitee.Click += (sender, e) => ExternalProgram.OpenUrl(GiteeUrl);
             lblUpdate.Click += (sender, e) =>
             {
-                if(!Updater.CheckUpdate()) MessageBoxEx.Show(AppString.MessageBox.NoUpdateDetected);
+                if(!Updater.Update()) MessageBoxEx.Show(AppString.Message.VersionIsLatest);
             };
             cmbConfigDir.SelectionChangeCommitted += (sender, e) =>
             {
                 string newPath = (cmbConfigDir.SelectedIndex == 0) ? AppConfig.AppDataConfigDir : AppConfig.AppConfigDir;
                 if(newPath == AppConfig.ConfigDir) return;
-                if(MessageBoxEx.Show(AppString.MessageBox.RestartApp, MessageBoxButtons.OKCancel) != DialogResult.OK)
+                if(MessageBoxEx.Show(AppString.Message.RestartApp, MessageBoxButtons.OKCancel) != DialogResult.OK)
                 {
                     cmbConfigDir.SelectedIndex = AppConfig.SaveToAppDir ? 1 : 0;
                 }
@@ -298,7 +309,7 @@ namespace ContextMenuManager.Controls
                 {
                     DirectoryEx.CopyTo(AppConfig.ConfigDir, newPath);
                     Directory.Delete(AppConfig.ConfigDir, true);
-                    SingleInstance.Restart(true);
+                    SingleInstance.Restart();
                 }
             };
             cmbEngine.SelectionChangeCommitted += (sender, e) =>
@@ -324,6 +335,22 @@ namespace ContextMenuManager.Controls
                     }
                 }
             };
+            cmbUpdate.SelectionChangeCommitted += (sender, e) =>
+            {
+                int day = 30;
+                switch(cmbUpdate.SelectedIndex)
+                {
+                    case 0:
+                        day = 7; break;
+                    case 2:
+                        day = 90; break;
+                    case 3:
+                        day = -1; break;
+                }
+                AppConfig.UpdateFrequency = day;
+            };
+            this.VisibleChanged += (sender, e) => this.Enabled = this.Visible;
+            cmbRepo.SelectionChangeCommitted += (sender, e) => AppConfig.RequestUseGithub = cmbRepo.SelectedIndex == 0;
             chkBackup.MouseDown += (sender, e) => AppConfig.AutoBackup = chkBackup.Checked = !chkBackup.Checked;
             chkProtect.MouseDown += (sender, e) => AppConfig.ProtectOpenItem = chkProtect.Checked = !chkProtect.Checked;
             chkWinXSortable.MouseDown += (sender, e) => AppConfig.WinXSortable = chkWinXSortable.Checked = !chkWinXSortable.Checked;
@@ -332,10 +359,10 @@ namespace ContextMenuManager.Controls
             chkShowFilePath.MouseDown += (sender, e) =>
             {
                 chkShowFilePath.Checked = !chkShowFilePath.Checked;
-                if(MessageBoxEx.Show(AppString.MessageBox.RestartApp, MessageBoxButtons.OKCancel) == DialogResult.OK)
+                if(MessageBoxEx.Show(AppString.Message.RestartApp, MessageBoxButtons.OKCancel) == DialogResult.OK)
                 {
                     AppConfig.ShowFilePath = chkShowFilePath.Checked;
-                    SingleInstance.Restart(true);
+                    SingleInstance.Restart();
                 }
                 else
                 {
@@ -355,6 +382,16 @@ namespace ContextMenuManager.Controls
         };
         readonly PictureButton btnConfigDir = new PictureButton(AppImage.Open);
 
+        readonly MyListItem mliRepo = new MyListItem
+        {
+            Text = AppString.Other.SetRequestRepo
+        };
+        readonly ComboBox cmbRepo = new ComboBox
+        {
+            DropDownStyle = ComboBoxStyle.DropDownList,
+            Width = 120.DpiZoom()
+        };
+
         readonly MyListItem mliBackup = new MyListItem
         {
             Text = AppString.Other.AutoBackup
@@ -364,25 +401,16 @@ namespace ContextMenuManager.Controls
 
         readonly MyListItem mliUpdate = new MyListItem
         {
-            Text = AppString.Other.CheckUpdate
+            Text = AppString.Other.SetUpdateFrequency
         };
-        readonly Label lblUpdate = new Label
+        readonly ComboBox cmbUpdate = new ComboBox
         {
-            Text = AppString.Other.ImmediatelyCheckUpdate,
-            BorderStyle = BorderStyle.FixedSingle,
-            Cursor = Cursors.Hand,
-            AutoSize = true
-        };
-        readonly Label lblGithub = new Label
-        {
-            Text = "Github",
-            BorderStyle = BorderStyle.FixedSingle,
-            Cursor = Cursors.Hand,
-            AutoSize = true
+            DropDownStyle = ComboBoxStyle.DropDownList,
+            Width = 120.DpiZoom()
         };
-        readonly Label lblGitee = new Label
+        readonly Label lblUpdate = new Label
         {
-            Text = "Gitee",
+            Text = AppString.Other.ImmediatelyCheck,
             BorderStyle = BorderStyle.FixedSingle,
             Cursor = Cursors.Hand,
             AutoSize = true
@@ -430,18 +458,13 @@ namespace ContextMenuManager.Controls
         };
         readonly MyCheckBox chkHideDisabledItems = new MyCheckBox();
 
-        protected override void OnVisibleChanged(EventArgs e)
-        {
-            base.OnVisibleChanged(e);
-            this.Enabled = this.Visible;
-        }
-
         public void LoadItems()
         {
-            this.AddItems(new[] { mliUpdate, mliConfigDir, mliEngine, mliBackup, mliProtect,
+            this.AddItems(new[] { mliUpdate, mliConfigDir, mliRepo, mliEngine, mliBackup, mliProtect,
                 mliWinXSortable, mliShowFilePath, mliOpenMoreRegedit, mliHideDisabledItems });
             foreach(MyListItem item in this.Controls) item.HasImage = false;
             cmbConfigDir.SelectedIndex = AppConfig.SaveToAppDir ? 1 : 0;
+            cmbRepo.SelectedIndex = AppConfig.RequestUseGithub ? 0 : 1;
             chkBackup.Checked = AppConfig.AutoBackup;
             chkProtect.Checked = AppConfig.ProtectOpenItem;
             chkWinXSortable.Checked = AppConfig.WinXSortable;
@@ -449,6 +472,18 @@ namespace ContextMenuManager.Controls
             chkOpenMoreRegedit.Checked = AppConfig.OpenMoreRegedit;
             chkHideDisabledItems.Checked = AppConfig.HideDisabledItems;
 
+            int index = 1;
+            switch(AppConfig.UpdateFrequency)
+            {
+                case 7:
+                    index = 0; break;
+                case 90:
+                    index = 2; break;
+                case -1:
+                    index = 3; break;
+            }
+            cmbUpdate.SelectedIndex = index;
+
             string url = AppConfig.EngineUrl;
             for(int i = 0; i <= AppConfig.EngineUrls.Length; i++)
             {

+ 98 - 0
ContextMenuManager/Controls/DonateListDialog.cs

@@ -0,0 +1,98 @@
+using BluePointLilac.Methods;
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace ContextMenuManager.Controls
+{
+    sealed class DonateListDialog : CommonDialog
+    {
+        public string DanateData { get; set; }
+
+        public override void Reset() { }
+
+        protected override bool RunDialog(IntPtr hwndOwner)
+        {
+            using(DonateListForm frm = new DonateListForm())
+            {
+                frm.ShowDonateList(DanateData);
+                frm.ShowDialog();
+            }
+            return true;
+        }
+
+        sealed class DonateListForm : Form
+        {
+            public DonateListForm()
+            {
+                this.Text = AppString.Other.DonationList;
+                this.SizeGripStyle = SizeGripStyle.Hide;
+                this.StartPosition = FormStartPosition.CenterParent;
+                this.MinimizeBox = this.MaximizeBox = this.ShowInTaskbar = false;
+                this.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
+                this.Font = new Font(SystemFonts.DialogFont.FontFamily, 9F);
+                this.ClientSize = new Size(520, 378).DpiZoom();
+                dgvDonate.ColumnHeadersDefaultCellStyle.Alignment
+                    = dgvDonate.RowsDefaultCellStyle.Alignment
+                    = DataGridViewContentAlignment.BottomCenter;
+                this.Controls.AddRange(new Control[] { lblDonate, dgvDonate });
+                lblDonate.Resize += (sender, e) => this.OnResize(null);
+            }
+
+            readonly DataGridView dgvDonate = new DataGridView
+            {
+                ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing,
+                AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells,
+                SelectionMode = DataGridViewSelectionMode.FullRowSelect,
+                BackgroundColor = SystemColors.Control,
+                BorderStyle = BorderStyle.None,
+                AllowUserToResizeRows = false,
+                AllowUserToAddRows = false,
+                RowHeadersVisible = false,
+                MultiSelect = false,
+                ReadOnly = true
+            };
+
+            readonly Label lblDonate = new Label { AutoSize = true };
+
+            protected override void OnResize(EventArgs e)
+            {
+                base.OnResize(e);
+                int a = 20.DpiZoom();
+                lblDonate.Location = new Point(a, a);
+                dgvDonate.Location = new Point(a, lblDonate.Bottom + a);
+                dgvDonate.Width = this.ClientSize.Width - 2 * a;
+                dgvDonate.Height = this.ClientSize.Height - 3 * a - lblDonate.Height;
+            }
+
+            public void ShowDonateList(string contents)
+            {
+                string[] lines = contents.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
+                int index = Array.FindIndex(lines, line => line == "|:--:|:--:|:--:|:--:|:--:");
+                string[] heads = lines[index - 1].Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
+                dgvDonate.ColumnCount = heads.Length;
+                for(int m = 0; m < heads.Length; m++)
+                {
+                    dgvDonate.Columns[m].HeaderText = heads[m];
+                }
+                for(int n = index + 1; n < lines.Length; n++)
+                {
+                    string[] values = lines[n].Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
+                    dgvDonate.Rows.Add(values);
+                }
+
+                DateTime date = new DateTime();
+                float money = 0;
+                foreach(DataGridViewRow row in dgvDonate.Rows)
+                {
+                    DateTime temp = Convert.ToDateTime(row.Cells[0].Value);
+                    if(temp > date) date = temp;
+                    money += Convert.ToSingle(row.Cells[3].Value);
+                }
+                dgvDonate.Columns[4].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
+                lblDonate.Text = AppString.Dialog.DonateInfo.Replace("%date", date.ToLongDateString())
+                    .Replace("%money", money.ToString()).Replace("%count", dgvDonate.RowCount.ToString());
+            }
+        }
+    }
+}

+ 6 - 0
ContextMenuManager/Controls/EnhanceMenusItem.cs

@@ -40,6 +40,7 @@ namespace ContextMenuManager.Controls
         {
             if(valueXN == null) return;
             XmlNode szXN = valueXN.SelectSingleNode("REG_SZ");
+            XmlNode binaryXN = valueXN.SelectSingleNode("REG_SZ");
             XmlNode dwordXN = valueXN.SelectSingleNode("REG_DWORD");
             XmlNode expand_szXN = valueXN.SelectSingleNode("REG_EXPAND_SZ");
             using(RegistryKey key = RegistryEx.GetRegistryKey(regPath, true, true))
@@ -50,6 +51,11 @@ namespace ContextMenuManager.Controls
                 if(expand_szXN != null)
                     foreach(XmlAttribute a in expand_szXN.Attributes)
                         key.SetValue(a.Name, a.Value, RegistryValueKind.ExpandString);
+                if(binaryXN != null)
+                {
+                    foreach(XmlAttribute a in binaryXN.Attributes)
+                        key.SetValue(a.Name, EnhanceMenusList.ConvertToBinary(a.Value), RegistryValueKind.Binary);
+                }
                 if(dwordXN != null)
                     foreach(XmlAttribute a in dwordXN.Attributes)
                     {

+ 49 - 18
ContextMenuManager/Controls/EnhanceMenusList.cs

@@ -4,6 +4,7 @@ using ContextMenuManager.Controls.Interfaces;
 using System;
 using System.Drawing;
 using System.IO;
+using System.Text;
 using System.Xml;
 
 namespace ContextMenuManager.Controls
@@ -12,28 +13,48 @@ namespace ContextMenuManager.Controls
     {
         public void LoadItems()
         {
-            try
+            string webPath = AppConfig.WebEnhanceMenusDic;
+            string userPath = AppConfig.UserEnhanceMenusDic;
+            string contents = Properties.Resources.EnhanceMenusDic;
+            if(!File.Exists(webPath)) File.WriteAllText(webPath, contents, Encoding.Unicode);
+            GroupPathItem webGroupItem = new GroupPathItem(webPath, ObjectPath.PathType.File);
+            GroupPathItem userGroupItem = new GroupPathItem(userPath, ObjectPath.PathType.File);
+            webGroupItem.Text = AppString.SideBar.Dictionaries;
+            userGroupItem.Text = AppString.Other.UserDictionaries;
+            webGroupItem.Image = AppImage.App;
+            userGroupItem.Image = AppImage.User;
+            LoadDocItems(webPath, webGroupItem);
+            LoadDocItems(userPath, userGroupItem);
+        }
+
+        private void LoadDocItems(string xmlPath, GroupPathItem groupItem)
+        {
+            if(!File.Exists(xmlPath)) return;
+            this.AddItem(groupItem);
+            XmlDocument doc = new XmlDocument();
+            try { doc.LoadXml(File.ReadAllText(xmlPath, EncodingType.GetType(xmlPath))); }
+            catch { return; }
+            foreach(XmlNode xn in doc.DocumentElement.ChildNodes)
             {
-                XmlDocument doc = AppDic.ReadXml(AppConfig.WebEnhanceMenusDic,
-                    AppConfig.UserEnhanceMenusDic, Properties.Resources.EnhanceMenusDic);
-                foreach(XmlNode xn in doc.DocumentElement.ChildNodes)
+                try
                 {
-
-                    GroupPathItem groupItem = GetGroupPathItem(xn);
-                    if(groupItem == null) continue;
-                    this.AddItem(groupItem);
+                    SubGroupItem subGroupItem = GetGroupPathItem(xn);
+                    if(subGroupItem == null) continue;
+                    this.AddItem(subGroupItem);
                     XmlElement shellXE = (XmlElement)xn.SelectSingleNode("Shell");
                     XmlElement shellExXE = (XmlElement)xn.SelectSingleNode("ShellEx");
-                    if(shellXE != null) LoadShellItems(shellXE, groupItem);
-                    if(shellExXE != null) LoadShellExItems(shellExXE, groupItem);
-                    groupItem.IsFold = true;
-                    groupItem.HideWhenNoSubItem();
+                    if(shellXE != null) LoadShellItems(shellXE, subGroupItem);
+                    if(shellExXE != null) LoadShellExItems(shellExXE, subGroupItem);
+                    subGroupItem.HideWhenNoSubItem();
+                    subGroupItem.FoldGroupItem = groupItem;
                 }
+                catch { continue; }
             }
-            catch { }
+            groupItem.IsFold = true;
+            groupItem.HideWhenNoSubItem();
         }
 
-        private GroupPathItem GetGroupPathItem(XmlNode xn)
+        private SubGroupItem GetGroupPathItem(XmlNode xn)
         {
             string path;
             string text;
@@ -99,11 +120,10 @@ namespace ContextMenuManager.Controls
                     }
                     break;
             }
-            GroupPathItem groupItem = new GroupPathItem(path, ObjectPath.PathType.Registry) { Image = image, Text = text };
-            return groupItem;
+            return new SubGroupItem(path, ObjectPath.PathType.Registry) { Image = image, Text = text };
         }
 
-        private void LoadShellItems(XmlElement shellXE, GroupPathItem groupItem)
+        private void LoadShellItems(XmlElement shellXE, SubGroupItem groupItem)
         {
             foreach(XmlElement itemXE in shellXE.SelectNodes("Item"))
             {
@@ -154,7 +174,7 @@ namespace ContextMenuManager.Controls
             }
         }
 
-        private void LoadShellExItems(XmlElement shellExXE, GroupPathItem groupItem)
+        private void LoadShellExItems(XmlElement shellExXE, SubGroupItem groupItem)
         {
             foreach(XmlElement itemXE in shellExXE.SelectNodes("Item"))
             {
@@ -220,5 +240,16 @@ namespace ContextMenuManager.Controls
             }
             return true;
         }
+
+        public static byte[] ConvertToBinary(string value)
+        {
+            string[] strs = value.Split(' ');
+            byte[] bs = new byte[strs.Length];
+            for(int i = 0; i < strs.Length; i++)
+            {
+                bs[i] = Convert.ToByte(strs[i], 16);
+            }
+            return bs;
+        }
     }
 }

+ 2 - 1
ContextMenuManager/Controls/FileExtensionDialog.cs

@@ -1,4 +1,5 @@
-using BluePointLilac.Methods;
+using BluePointLilac.Controls;
+using BluePointLilac.Methods;
 using System;
 using System.Collections.Generic;
 

+ 2 - 2
ContextMenuManager/Controls/GuidBlockedItem.cs

@@ -42,7 +42,7 @@ namespace ContextMenuManager.Controls
                 }
                 else
                 {
-                    text = AppString.MessageBox.MalformedGuid;
+                    text = AppString.Message.MalformedGuid;
                 }
                 text += "\n" + Value;
                 return text;
@@ -81,7 +81,7 @@ namespace ContextMenuManager.Controls
             MyToolTip.SetToolTip(BtnDelete, AppString.Menu.Delete);
             TsiDelete.Click += (sender, e) =>
             {
-                if(MessageBoxEx.Show(AppString.MessageBox.ConfirmDelete, MessageBoxButtons.YesNo) == DialogResult.Yes) DeleteMe();
+                if(MessageBoxEx.Show(AppString.Message.ConfirmDelete, MessageBoxButtons.YesNo) == DialogResult.Yes) DeleteMe();
             };
         }
 

+ 2 - 2
ContextMenuManager/Controls/GuidBlockedList.cs

@@ -56,14 +56,14 @@ namespace ContextMenuManager.Controls
                         {
                             if(((GuidBlockedItem)Controls[i]).Guid.Equals(guid))
                             {
-                                MessageBoxEx.Show(AppString.MessageBox.HasBeenAdded);
+                                MessageBoxEx.Show(AppString.Message.HasBeenAdded);
                                 return;
                             }
                         }
                         this.InsertItem(new GuidBlockedItem(value), 1);
                         ExplorerRestarter.Show();
                     }
-                    else MessageBoxEx.Show(AppString.MessageBox.MalformedGuid);
+                    else MessageBoxEx.Show(AppString.Message.MalformedGuid);
                 }
             };
         }

+ 1 - 1
ContextMenuManager/Controls/IEItem.cs

@@ -45,7 +45,7 @@ namespace ContextMenuManager.Controls
                 string defaultValue = Registry.GetValue(newPath, "", null)?.ToString();
                 if(!defaultValue.IsNullOrWhiteSpace())
                 {
-                    MessageBoxEx.Show(AppString.MessageBox.HasBeenAdded);
+                    MessageBoxEx.Show(AppString.Message.HasBeenAdded);
                 }
                 else
                 {

+ 1 - 1
ContextMenuManager/Controls/Interfaces/IBtnDeleteItem.cs

@@ -17,7 +17,7 @@ namespace ContextMenuManager.Controls.Interfaces
             ((MyListItem)item).AddCtr(this);
             this.MouseDown += (sender, e) =>
             {
-                if(MessageBoxEx.Show(AppString.MessageBox.ConfirmDelete,
+                if(MessageBoxEx.Show(AppString.Message.ConfirmDelete,
                 MessageBoxButtons.YesNo) == DialogResult.Yes)
                     item.DeleteMe();
             };

+ 18 - 9
ContextMenuManager/Controls/Interfaces/IFoldGroupItem.cs

@@ -35,7 +35,8 @@ namespace ContextMenuManager.Controls.Interfaces
                 list.SuspendLayout();
                 foreach(Control ctr in list.Controls)
                 {
-                    if(ctr is IFoldSubItem item && item.FoldGroupItem == FoldGroup) ctr.Visible = !value;
+                    if(ctr is IFoldSubItem item1 && item1.FoldGroupItem == FoldGroup) ctr.Visible = !value;
+                    else if(ctr is SubGroupItem item2 && item2.FoldGroupItem == FoldGroup) { item2.IsFold = true; item2.Visible = !value; }
                 }
                 list.ResumeLayout();
             }
@@ -62,13 +63,19 @@ namespace ContextMenuManager.Controls.Interfaces
         public bool IsFold
         {
             get => BtnFold.IsFold;
-            set => BtnFold.IsFold = value;
+            set
+            {
+                if(BtnFold.IsFold == value) return;
+                BtnFold.IsFold = value;
+                IsFoldChanegd?.Invoke(null, null);
+            }
         }
+
+        public event EventHandler IsFoldChanegd;
         public string TargetPath { get; set; }
         public PathType PathType { get; set; }
         public ObjectPathButton BtnOpenPath { get; set; }
         public FoldButton BtnFold { get; set; }
-
         public GroupPathItem(string targetPath, PathType pathType)
         {
             BtnFold = new FoldButton(this);
@@ -100,6 +107,7 @@ namespace ContextMenuManager.Controls.Interfaces
             MyToolTip.SetToolTip(BtnOpenPath, tip);
             this.ImageDoubleClick += (sender, e) => this.OnDoubleClick(null);
             this.TextDoubleClick += (sender, e) => this.OnDoubleClick(null);
+            this.DoubleClick += (sender, e) => this.IsFold = !this.IsFold;
         }
 
         public void HideWhenNoSubItem()
@@ -107,15 +115,16 @@ namespace ContextMenuManager.Controls.Interfaces
             int count = 0;
             foreach(var ctr in this.Parent.Controls)
             {
-                if(ctr is IFoldSubItem item && item.FoldGroupItem == this) count++;
+                if(ctr is IFoldSubItem item1 && item1.FoldGroupItem == this) count++;
+                else if(ctr is SubGroupItem item2 && item2.FoldGroupItem == this) count++;
             }
             if(count == 0) this.Visible = false;
         }
+    }
 
-        protected override void OnDoubleClick(EventArgs e)
-        {
-            base.OnDoubleClick(e);
-            IsFold = !IsFold;
-        }
+    class SubGroupItem : GroupPathItem
+    {
+        public SubGroupItem(string targetPath, PathType pathType) : base(targetPath, pathType) { }
+        public GroupPathItem FoldGroupItem { get; set; }
     }
 }

+ 1 - 0
ContextMenuManager/Controls/Interfaces/ITsiAdministratorItem.cs

@@ -41,6 +41,7 @@ namespace ContextMenuManager.Controls.Interfaces
             {
                 item.ShellLink.RunAsAdministrator = !this.Checked;
                 item.ShellLink.Save();
+                if(item is WinXItem) ExplorerRestarter.Show();
             };
         }
     }

+ 1 - 1
ContextMenuManager/Controls/Interfaces/ITsiCommandItem.cs

@@ -30,7 +30,7 @@ namespace ContextMenuManager.Controls.Interfaces
                 if(dlg.ShowDialog() != DialogResult.OK) return null;
                 if(!CommandCanBeEmpty && string.IsNullOrEmpty(dlg.Text))
                 {
-                    MessageBoxEx.Show(AppString.MessageBox.CommandCannotBeEmpty);
+                    MessageBoxEx.Show(AppString.Message.CommandCannotBeEmpty);
                     return ChangeCommand(command);
                 }
                 else return dlg.Text;

+ 2 - 2
ContextMenuManager/Controls/Interfaces/ITsiDeleteItem.cs

@@ -25,7 +25,7 @@ namespace ContextMenuManager.Controls.Interfaces
             {
                 if(item is ITsiRegDeleteItem regItem && AppConfig.AutoBackup)
                 {
-                    if(MessageBoxEx.Show(AppString.MessageBox.DeleteButCanRestore,
+                    if(MessageBoxEx.Show(AppString.Message.DeleteButCanRestore,
                      MessageBoxButtons.YesNo) != DialogResult.Yes) return;
                     string date = DateTime.Today.ToString("yyyy-MM-dd");
                     string time = DateTime.Now.ToString("HH.mm.ss");
@@ -33,7 +33,7 @@ namespace ContextMenuManager.Controls.Interfaces
                     Directory.CreateDirectory(Path.GetDirectoryName(filePath));
                     RegistryEx.Export(regItem.RegPath, filePath);
                 }
-                else if(MessageBoxEx.Show(AppString.MessageBox.ConfirmDeletePermanently,
+                else if(MessageBoxEx.Show(AppString.Message.ConfirmDeletePermanently,
                      MessageBoxButtons.YesNo) != DialogResult.Yes) return;
                 item.DeleteMe();
             };

+ 10 - 3
ContextMenuManager/Controls/Interfaces/ITsiFilePathItem.cs

@@ -17,7 +17,11 @@ namespace ContextMenuManager.Controls.Interfaces
         public FileLocationMenuItem(ITsiFilePathItem item) : base(AppString.Menu.FileLocation)
         {
             item.ContextMenuStrip.Opening += (sender, e) =>
-                this.Visible = File.Exists(item.ItemFilePath) || Directory.Exists(item.ItemFilePath);
+            {
+                string path = item.ItemFilePath;
+                this.Visible = path != null && (Directory.Exists(path)
+                    || File.Exists(path) || path.StartsWith("shell:AppsFolder"));
+            };
             this.Click += (sender, e) => ExternalProgram.JumpExplorer(item.ItemFilePath);
         }
     }
@@ -26,8 +30,11 @@ namespace ContextMenuManager.Controls.Interfaces
     {
         public FilePropertiesMenuItem(ITsiFilePathItem item) : base(AppString.Menu.FileProperties)
         {
-            item.ContextMenuStrip.Opening += (sender, e)
-                => this.Visible = File.Exists(item.ItemFilePath) || Directory.Exists(item.ItemFilePath);
+            item.ContextMenuStrip.Opening += (sender, e) =>
+            {
+                string path = item.ItemFilePath;
+                this.Visible = Directory.Exists(path) || File.Exists(path);
+            };
             this.Click += (sender, e) => ExternalProgram.ShowPropertiesDialog(item.ItemFilePath);
         }
     }

+ 2 - 2
ContextMenuManager/Controls/Interfaces/ITsiGuidItem.cs

@@ -55,7 +55,7 @@ namespace ContextMenuManager.Controls.Interfaces
         private void CopyGuid()
         {
             Clipboard.SetText(Item.Guid.ToString());
-            MessageBoxEx.Show($"{AppString.MessageBox.CopiedToClipboard}\n{Item.Guid}",
+            MessageBoxEx.Show($"{AppString.Message.CopiedToClipboard}\n{Item.Guid}",
                 MessageBoxButtons.OK, MessageBoxIcon.Information);
         }
 
@@ -120,7 +120,7 @@ namespace ContextMenuManager.Controls.Interfaces
                 }
                 else
                 {
-                    MessageBoxEx.Show(AppString.MessageBox.StringParsingFailed);
+                    MessageBoxEx.Show(AppString.Message.StringParsingFailed);
                     return;
                 }
                 if(dlg.ItemIconLocation != null)

+ 2 - 2
ContextMenuManager/Controls/Interfaces/ITsiTextItem.cs

@@ -36,12 +36,12 @@ namespace ContextMenuManager.Controls.Interfaces
                 if(dlg.ShowDialog() != DialogResult.OK) return null;
                 if(dlg.Text.Length == 0)
                 {
-                    MessageBoxEx.Show(AppString.MessageBox.TextCannotBeEmpty);
+                    MessageBoxEx.Show(AppString.Message.TextCannotBeEmpty);
                     return ChangeText(text);
                 }
                 else if(ResourceString.GetDirectString(dlg.Text).Length == 0)
                 {
-                    MessageBoxEx.Show(AppString.MessageBox.StringParsingFailed);
+                    MessageBoxEx.Show(AppString.Message.StringParsingFailed);
                     return ChangeText(text);
                 }
                 else return dlg.Text;

+ 2 - 2
ContextMenuManager/Controls/NewIEDialog.cs

@@ -31,12 +31,12 @@ namespace ContextMenuManager.Controls
                 {
                     if(ItemText.IsNullOrWhiteSpace())
                     {
-                        MessageBoxEx.Show(AppString.MessageBox.TextCannotBeEmpty);
+                        MessageBoxEx.Show(AppString.Message.TextCannotBeEmpty);
                         return;
                     }
                     if(ItemCommand.IsNullOrWhiteSpace())
                     {
-                        MessageBoxEx.Show(AppString.MessageBox.CommandCannotBeEmpty);
+                        MessageBoxEx.Show(AppString.Message.CommandCannotBeEmpty);
                         return;
                     }
                     AddNewItem();

+ 4 - 4
ContextMenuManager/Controls/NewLnkFileDialog.cs

@@ -63,19 +63,19 @@ namespace ContextMenuManager.Controls
                 {
                     if(ItemText.IsNullOrWhiteSpace())
                     {
-                        MessageBoxEx.Show(AppString.MessageBox.TextCannotBeEmpty);
+                        MessageBoxEx.Show(AppString.Message.TextCannotBeEmpty);
                     }
                     else if(ItemFilePath.IsNullOrWhiteSpace())
                     {
-                        MessageBoxEx.Show(AppString.MessageBox.CommandCannotBeEmpty);
+                        MessageBoxEx.Show(AppString.Message.CommandCannotBeEmpty);
                     }
                     else if(rdoFile.Checked && !ObjectPath.GetFullFilePath(ItemFilePath, out _))
                     {
-                        MessageBoxEx.Show(AppString.MessageBox.FileNotExists);
+                        MessageBoxEx.Show(AppString.Message.FileNotExists);
                     }
                     else if(rdoFolder.Checked && !Directory.Exists(ItemFilePath))
                     {
-                        MessageBoxEx.Show(AppString.MessageBox.FolderNotExists);
+                        MessageBoxEx.Show(AppString.Message.FolderNotExists);
                     }
                     else DialogResult = DialogResult.OK;
                 };

+ 4 - 4
ContextMenuManager/Controls/NewOpenWithDialog.cs

@@ -38,12 +38,12 @@ namespace ContextMenuManager.Controls
                 {
                     if(string.IsNullOrEmpty(ItemText))
                     {
-                        MessageBoxEx.Show(AppString.MessageBox.TextCannotBeEmpty);
+                        MessageBoxEx.Show(AppString.Message.TextCannotBeEmpty);
                         return;
                     }
                     if(ItemCommand.IsNullOrWhiteSpace())
                     {
-                        MessageBoxEx.Show(AppString.MessageBox.CommandCannotBeEmpty);
+                        MessageBoxEx.Show(AppString.Message.CommandCannotBeEmpty);
                         return;
                     }
                     FilePath = ObjectPath.ExtractFilePath(base.ItemFilePath);
@@ -53,12 +53,12 @@ namespace ContextMenuManager.Controls
                         string name = Path.GetFileName(path);
                         if(FilePath != null && FilePath.Equals(path, StringComparison.OrdinalIgnoreCase))
                         {
-                            MessageBoxEx.Show(AppString.MessageBox.HasBeenAdded);
+                            MessageBoxEx.Show(AppString.Message.HasBeenAdded);
                             return;
                         }
                         if(FileName == null || FileName.Equals(name, StringComparison.OrdinalIgnoreCase))
                         {
-                            MessageBoxEx.Show(AppString.MessageBox.UnsupportedFilename);
+                            MessageBoxEx.Show(AppString.Message.UnsupportedFilename);
                             return;
                         }
                     }

+ 2 - 2
ContextMenuManager/Controls/NewShellDialog.cs

@@ -78,7 +78,7 @@ namespace ContextMenuManager.Controls
                         chkSE.Checked = false;
                         if(WindowsOsVersion.IsEqualVista)
                         {
-                            MessageBoxEx.Show(AppString.MessageBox.VistaUnsupportedMulti);
+                            MessageBoxEx.Show(AppString.Message.VistaUnsupportedMulti);
                             rdoSingle.Checked = true;
                             return;
                         }
@@ -93,7 +93,7 @@ namespace ContextMenuManager.Controls
                 {
                     if(txtText.Text.IsNullOrWhiteSpace())
                     {
-                        MessageBoxEx.Show(AppString.MessageBox.TextCannotBeEmpty);
+                        MessageBoxEx.Show(AppString.Message.TextCannotBeEmpty);
                     }
                     else
                     {

+ 1 - 1
ContextMenuManager/Controls/OpenWithItem.cs

@@ -67,7 +67,7 @@ namespace ContextMenuManager.Controls
             {
                 if(ObjectPath.ExtractFilePath(value) != ItemFilePath)
                 {
-                    MessageBoxEx.Show(AppString.MessageBox.CannotChangePath);
+                    MessageBoxEx.Show(AppString.Message.CannotChangePath);
                 }
                 else Registry.SetValue(RegPath, "", value);
             }

+ 4 - 4
ContextMenuManager/Controls/ShellExItem.cs

@@ -63,8 +63,8 @@ namespace ContextMenuManager.Controls
             }
         }
 
-        public string ValueName => null;
         public Guid Guid { get; set; }
+        public string ValueName => null;
         public string SearchText => Text;
         public string ItemFilePath => GuidInfo.GetFilePath(Guid);
         private string KeyName => RegistryEx.GetKeyName(RegPath);
@@ -101,7 +101,7 @@ namespace ContextMenuManager.Controls
                 }
                 catch
                 {
-                    MessageBoxEx.Show(AppString.MessageBox.AuthorityProtection);
+                    MessageBoxEx.Show(AppString.Message.AuthorityProtection);
                     return;
                 }
                 RegPath = BackupPath;
@@ -146,7 +146,7 @@ namespace ContextMenuManager.Controls
         {
             if(!IsOpenLnkItem) return false;
             if(!AppConfig.ProtectOpenItem) return false;
-            return MessageBoxEx.Show(AppString.MessageBox.PromptIsOpenItem, MessageBoxButtons.YesNo) != DialogResult.Yes;
+            return MessageBoxEx.Show(AppString.Message.PromptIsOpenItem, MessageBoxButtons.YesNo) != DialogResult.Yes;
         }
 
         public void DeleteMe()
@@ -158,7 +158,7 @@ namespace ContextMenuManager.Controls
             }
             catch
             {
-                MessageBoxEx.Show(AppString.MessageBox.AuthorityProtection);
+                MessageBoxEx.Show(AppString.Message.AuthorityProtection);
                 return;
             }
             this.Dispose();

+ 6 - 6
ContextMenuManager/Controls/ShellItem.cs

@@ -282,7 +282,7 @@ namespace ContextMenuManager.Controls
                         {
                             if(IsSubItem)
                             {
-                                MessageBoxEx.Show(AppString.MessageBox.CannotHideSubItem);
+                                MessageBoxEx.Show(AppString.Message.CannotHideSubItem);
                                 return;
                             }
                         }
@@ -301,7 +301,7 @@ namespace ContextMenuManager.Controls
                 }
                 catch
                 {
-                    MessageBoxEx.Show(AppString.MessageBox.AuthorityProtection);
+                    MessageBoxEx.Show(AppString.Message.AuthorityProtection);
                 }
             }
         }
@@ -328,7 +328,7 @@ namespace ContextMenuManager.Controls
                 //MUIVerb长度不可超过80,超过80系统会隐藏该菜单项目
                 if(ResourceString.GetDirectString(value).Length >= 80)
                 {
-                    MessageBoxEx.Show(AppString.MessageBox.TextLengthCannotExceed80);
+                    MessageBoxEx.Show(AppString.Message.TextLengthCannotExceed80);
                 }
                 else
                 {
@@ -576,7 +576,7 @@ namespace ContextMenuManager.Controls
         {
             if(WindowsOsVersion.IsEqualVista)
             {
-                MessageBoxEx.Show(AppString.MessageBox.VistaUnsupportedMulti);
+                MessageBoxEx.Show(AppString.Message.VistaUnsupportedMulti);
                 return;
             }
             using(ShellSubMenuDialog dlg = new ShellSubMenuDialog())
@@ -591,7 +591,7 @@ namespace ContextMenuManager.Controls
         {
             if(!IsOpenItem) return false;
             if(!AppConfig.ProtectOpenItem) return false;
-            return MessageBoxEx.Show(AppString.MessageBox.PromptIsOpenItem, MessageBoxButtons.YesNo) != DialogResult.Yes;
+            return MessageBoxEx.Show(AppString.Message.PromptIsOpenItem, MessageBoxButtons.YesNo) != DialogResult.Yes;
         }
 
         public virtual void DeleteMe()
@@ -602,7 +602,7 @@ namespace ContextMenuManager.Controls
             }
             catch
             {
-                MessageBoxEx.Show(AppString.MessageBox.AuthorityProtection);
+                MessageBoxEx.Show(AppString.Message.AuthorityProtection);
                 return;
             }
             this.Dispose();

+ 223 - 111
ContextMenuManager/Controls/ShellList.cs

@@ -8,6 +8,7 @@ using System.Diagnostics;
 using System.Drawing;
 using System.IO;
 using System.Linq;
+using System.Text;
 using System.Windows.Forms;
 using System.Xml;
 
@@ -36,22 +37,33 @@ namespace ContextMenuManager.Controls
         {
             File, Folder, Directory, Background, Desktop, Drive, AllObjects, Computer, RecycleBin, Library,
             LnkFile, UwpLnk, ExeFile, UnknownType, CustomExtension, PerceivedType, DirectoryType,
-            CommandStore, DragDrop, CustomRegPath, MenuAnalysis
+            CommandStore, DragDrop, CustomRegPath, MenuAnalysis, CustomExtensionPerceivedType
         }
 
-        private static readonly string[] DirectoryTypes = { "Document", "Image", "Video", "Audio" };
-        private static readonly string[] PerceivedTypes = { null, "Text", "Document", "Image", "Video", "Audio", "Compressed", "System" };
-        private static readonly string[] FileObjectTypes = { AppString.SideBar.File, AppString.SideBar.Directory };
-        private static readonly string[] DirectoryTypeNames =
+        private static readonly string[] DirectoryTypes =
         {
-            AppString.Dialog.DocumentDirectory, AppString.Dialog.ImageDirectory,
-            AppString.Dialog.VideoDirectory, AppString.Dialog.AudioDirectory
+            "Document", "Image", "Video", "Audio"
+        };
+        private static readonly string[] PerceivedTypes =
+        {
+            null, "Text", "Document", "Image",
+            "Video", "Audio", "Compressed", "System"
+        };
+        private static readonly string[] FileObjectTypes =
+        {
+            AppString.SideBar.File,
+            AppString.SideBar.Directory
         };
         private static readonly string[] PerceivedTypeNames =
         {
             AppString.Dialog.NoPerceivedType, AppString.Dialog.TextFile, AppString.Dialog.DocumentFile, AppString.Dialog.ImageFile,
             AppString.Dialog.VideoFile, AppString.Dialog.AudioFile, AppString.Dialog.CompressedFile, AppString.Dialog.SystemFile
         };
+        private static readonly string[] DirectoryTypeNames =
+        {
+            AppString.Dialog.DocumentDirectory, AppString.Dialog.ImageDirectory,
+            AppString.Dialog.VideoDirectory, AppString.Dialog.AudioDirectory
+        };
 
         private static string GetDirectoryTypeName(string directoryType)
         {
@@ -81,24 +93,101 @@ namespace ContextMenuManager.Controls
             return PerceivedTypeNames[index];
         }
 
+        private static readonly string[] DropEffectPaths =
+        {
+            MENUPATH_FILE, MENUPATH_ALLOBJECTS,
+            MENUPATH_FOLDER, MENUPATH_DIRECTORY
+        };
+        private static readonly string[] DropEffectNames =
+        {
+            AppString.Dialog.DefaultDropEffect, AppString.Dialog.CopyDropEffect,
+            AppString.Dialog.MoveDropEffect, AppString.Dialog.CreateLinkDropEffect
+        };
+
+        private enum DropEffect { Default = 0, Copy = 1, Move = 2, CreateLink = 4 }
+
+        private static DropEffect DefaultDropEffect
+        {
+            get
+            {
+                foreach(string path in DropEffectPaths)
+                {
+                    object value = Registry.GetValue(path, "DefaultDropEffect", null);
+                    if(value != null)
+                    {
+                        switch(value)
+                        {
+                            case 1:
+                                return DropEffect.Copy;
+                            case 2:
+                                return DropEffect.Move;
+                            case 4:
+                                return DropEffect.CreateLink;
+                        }
+                    }
+                }
+                return DropEffect.Default;
+            }
+            set
+            {
+                object data;
+                switch(value)
+                {
+                    case DropEffect.Copy:
+                        data = 1; break;
+                    case DropEffect.Move:
+                        data = 2; break;
+                    case DropEffect.CreateLink:
+                        data = 4; break;
+                    default:
+                        data = 0; break;
+                }
+                foreach(string path in DropEffectPaths)
+                {
+                    Registry.SetValue(path, "DefaultDropEffect", data, RegistryValueKind.DWord);
+                }
+            }
+        }
+
+        private static string GetDropEffectName()
+        {
+            switch(DefaultDropEffect)
+            {
+                case DropEffect.Copy:
+                    return DropEffectNames[1];
+                case DropEffect.Move:
+                    return DropEffectNames[2];
+                case DropEffect.CreateLink:
+                    return DropEffectNames[3];
+                default:
+                    return DropEffectNames[0];
+            }
+        }
+
         private static string CurrentExtension = null;
         private static string CurrentDirectoryType = null;
         private static string CurrentPerceivedType = null;
         public static string CurrentCustomRegPath = null;
         public static string CurrentFileObjectPath = null;
 
+        private static string CurrentExtensionPerceivedType
+        {
+            get => Registry.GetValue(CurrentExtensionPath, "PerceivedType", null)?.ToString();
+            set
+            {
+                if(value == null) RegistryEx.DeleteValue(CurrentExtensionPath, "PerceivedType");
+                else Registry.SetValue(CurrentExtensionPath, "PerceivedType", value, RegistryValueKind.String);
+            }
+        }
+
         private static string GetShellPath(string scenePath) => $@"{scenePath}\shell";
         private static string GetShellExPath(string scenePath) => $@"{scenePath}\ShellEx";
         private static string GetSysAssExtPath(string typeName) => typeName != null ? $@"{SYSFILEASSPATH}\{typeName}" : null;
         private static string GetOpenModePath(string extension) => extension != null ? $@"{RegistryEx.CLASSESROOT}\{FileExtension.GetOpenMode(extension)}" : null;
+        private static string CurrentExtensionPath => $@"{RegistryEx.CLASSESROOT}\{CurrentExtension}";
 
         public Scenes Scene { get; set; }
 
-        public ShellList()
-        {
-            SelectItem.SelectedChanged += (sender, e) => { this.ClearItems(); this.LoadItems(); };
-        }
-
         public void LoadItems()
         {
             string scenePath = null;
@@ -161,6 +250,7 @@ namespace ContextMenuManager.Controls
                     this.LoadStoreItems();
                     return;
                 case Scenes.DragDrop:
+                    this.AddItem(new SelectItem(Scene));
                     this.AddNewItem(MENUPATH_FOLDER);
                     this.LoadShellExItems(GetShellExPath(MENUPATH_FOLDER));
                     this.LoadShellExItems(GetShellExPath(MENUPATH_DIRECTORY));
@@ -170,7 +260,15 @@ namespace ContextMenuManager.Controls
             }
             this.AddNewItem(scenePath);
             this.LoadItems(scenePath);
-            if(WindowsOsVersion.ISAfterOrEqual10) this.AddUwpModeItem();
+            if(WindowsOsVersion.ISAfterOrEqual10)
+            {
+                string webPath = AppConfig.WebUwpModeItemsDic;
+                string userPath = AppConfig.UserUwpModeItemsDic;
+                string contents = Properties.Resources.UwpModeItemsDic;
+                if(!File.Exists(webPath)) File.WriteAllText(webPath, contents, Encoding.Unicode);
+                this.LoadUwpModeItem(webPath);
+                this.LoadUwpModeItem(userPath);
+            }
             switch(Scene)
             {
                 case Scenes.Background:
@@ -194,10 +292,10 @@ namespace ContextMenuManager.Controls
                 case Scenes.DirectoryType:
                 case Scenes.CustomRegPath:
                     this.InsertItem(new SelectItem(Scene), 0);
-                    if(Scene == Scenes.CustomExtension)
+                    if(Scene == Scenes.CustomExtension && CurrentExtension != null)
                     {
                         this.LoadItems(GetOpenModePath(CurrentExtension));
-                        if(CurrentExtension != null) this.InsertItem(new PerceivedTypeItem(), 1);
+                        this.InsertItem(new SelectItem(Scenes.CustomExtensionPerceivedType), 1);
                     }
                     break;
             }
@@ -360,7 +458,7 @@ namespace ContextMenuManager.Controls
                     string shellExPath = GetShellExPath(scenePath);
                     if(ShellExItem.GetPathAndGuids(shellExPath, isDragDrop).Values.Contains(guid))
                     {
-                        MessageBoxEx.Show(AppString.MessageBox.HasBeenAdded);
+                        MessageBoxEx.Show(AppString.Message.HasBeenAdded);
                     }
                     else
                     {
@@ -396,7 +494,7 @@ namespace ContextMenuManager.Controls
                 }
                 else
                 {
-                    MessageBoxEx.Show(AppString.MessageBox.MalformedGuid);
+                    MessageBoxEx.Show(AppString.Message.MalformedGuid);
                 }
             }
         }
@@ -411,11 +509,11 @@ namespace ContextMenuManager.Controls
             }
         }
 
-        private void AddUwpModeItem()
+        private void LoadUwpModeItem(string xmlPath)
         {
-            XmlDocument doc = AppDic.ReadXml(AppConfig.WebUwpModeItemsDic,
-                AppConfig.UserUwpModeItemsDic, Properties.Resources.UwpModeItemsDic);
-            List<Guid> guids = new List<Guid>();
+            XmlDocument doc = new XmlDocument();
+            try { doc.LoadXml(File.ReadAllText(xmlPath, EncodingType.GetType(xmlPath))); }
+            catch { return; }
             foreach(XmlElement sceneXE in doc.DocumentElement.ChildNodes)
             {
                 if(sceneXE.Name == Scene.ToString())
@@ -424,12 +522,16 @@ namespace ContextMenuManager.Controls
                     {
                         if(GuidEx.TryParse(itemXE.GetAttribute("Guid"), out Guid guid))
                         {
-                            if(guids.Contains(guid)) continue;
+                            bool isAdded = false;
+                            foreach(Control ctr in this.Controls)
+                            {
+                                if(ctr is UwpModeItem item && item.Guid == guid) { isAdded = true; break; }
+                            }
+                            if(isAdded) continue;
                             string uwpName = GuidInfo.GetUwpName(guid);
                             if(!string.IsNullOrEmpty(uwpName))
                             {
                                 this.AddItem(new UwpModeItem(uwpName, guid));
-                                guids.Add(guid);
                             }
                         }
                     }
@@ -443,16 +545,18 @@ namespace ContextMenuManager.Controls
 
             void AddFileItems(string filePath)
             {
-                string extension = Path.GetExtension(filePath);
+                string extension = Path.GetExtension(filePath).ToLower();
                 if(extension == string.Empty) extension = ".";
                 string perceivedType = Registry.GetValue($@"{RegistryEx.CLASSESROOT}\{extension}", "PerceivedType", null)?.ToString();
                 string perceivedTypeName = GetPerceivedTypeName(perceivedType);
                 string openMode = FileExtension.GetOpenMode(extension);
+                JumpItem.TargetPath = filePath;
                 JumpItem.Extension = extension;
                 JumpItem.PerceivedType = perceivedType;
                 this.AddItem(new JumpItem(Scenes.File));
                 this.AddItem(new JumpItem(Scenes.AllObjects));
-                this.AddItem(new JumpItem(Scenes.CustomExtension));
+                if(extension == ".exe") this.AddItem(new JumpItem(Scenes.ExeFile));
+                else this.AddItem(new JumpItem(Scenes.CustomExtension));
                 if(openMode == null) this.AddItem(new JumpItem(Scenes.UnknownType));
                 if(perceivedType != null) this.AddItem(new JumpItem(Scenes.PerceivedType));
             }
@@ -504,34 +608,21 @@ namespace ContextMenuManager.Controls
 
         public sealed class SelectItem : MyListItem
         {
-            static string selected;
-            public static string Selected
-            {
-                get => selected;
-                set
-                {
-                    selected = value;
-                    SelectedChanged?.Invoke(null, null);
-                }
-            }
-
-            public static event EventHandler SelectedChanged;
-
-            readonly PictureButton BtnSelect = new PictureButton(AppImage.Select);
-
-            public Scenes Scene { get; private set; }
-
             public SelectItem(Scenes scene)
             {
                 this.Scene = scene;
                 this.AddCtr(BtnSelect);
                 this.SetTextAndTip();
-                this.Image = AppImage.Custom;
+                this.SetImage();
                 BtnSelect.MouseDown += (sender, e) => ShowSelectDialog();
                 this.ImageDoubleClick += (sender, e) => ShowSelectDialog();
                 this.TextDoubleClick += (sender, e) => ShowSelectDialog();
             }
 
+            readonly PictureButton BtnSelect = new PictureButton(AppImage.Select);
+
+            public Scenes Scene { get; private set; }
+
             private void SetTextAndTip()
             {
                 string tip = "";
@@ -563,12 +654,32 @@ namespace ContextMenuManager.Controls
                         if(CurrentFileObjectPath == null) text = tip;
                         else text = AppString.Other.CurrentFilePath + "\n" + CurrentFileObjectPath;
                         break;
-
+                    case Scenes.DragDrop:
+                        tip = AppString.Dialog.SelectDropEffect;
+                        text = AppString.Other.SetDefaultDropEffect + " " + GetDropEffectName();
+                        break;
+                    case Scenes.CustomExtensionPerceivedType:
+                        tip = AppString.Dialog.SelectPerceivedType;
+                        text = AppString.Other.SetPerceivedType.Replace("%s", CurrentExtension)
+                            + " " + GetPerceivedTypeName(CurrentExtensionPerceivedType);
+                        break;
                 }
                 MyToolTip.SetToolTip(BtnSelect, tip);
                 this.Text = text;
             }
 
+            private void SetImage()
+            {
+                switch(Scene)
+                {
+                    case Scenes.CustomExtensionPerceivedType:
+                        using(Icon icon = ResourceIcon.GetExtensionIcon(CurrentExtension))
+                            this.Image = icon?.ToBitmap();
+                        break;
+                }
+                if(this.Image == null) this.Image = AppImage.Custom;
+            }
+
             private void ShowSelectDialog()
             {
                 SelectDialog dlg = null;
@@ -596,6 +707,22 @@ namespace ContextMenuManager.Controls
                             Selected = GetDirectoryTypeName(CurrentDirectoryType)
                         };
                         break;
+                    case Scenes.CustomExtensionPerceivedType:
+                        dlg = new SelectDialog
+                        {
+                            Items = PerceivedTypeNames,
+                            Title = AppString.Dialog.SelectPerceivedType,
+                            Selected = GetPerceivedTypeName(CurrentExtensionPerceivedType)
+                        };
+                        break;
+                    case Scenes.DragDrop:
+                        dlg = new SelectDialog
+                        {
+                            Items = DropEffectNames,
+                            Title = AppString.Dialog.SelectDropEffect,
+                            Selected = GetDropEffectName()
+                        };
+                        break;
                     case Scenes.MenuAnalysis:
                         dlg = new SelectDialog
                         {
@@ -604,10 +731,10 @@ namespace ContextMenuManager.Controls
                         };
                         break;
                     case Scenes.CustomRegPath:
-                        if(MessageBoxEx.Show(AppString.MessageBox.SelectRegPath,
+                        if(MessageBoxEx.Show(AppString.Message.SelectRegPath,
                             MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) return;
                         Form frm = this.FindForm();
-                        frm.Opacity = 0;
+                        frm.Hide();
                         using(Process process = Process.Start("regedit.exe", "-m"))
                         {
                             process.WaitForExit();
@@ -616,9 +743,10 @@ namespace ContextMenuManager.Controls
                         int index = path.IndexOf('\\');
                         if(index == -1) return;
                         path = path.Substring(index + 1);
-                        Selected = CurrentCustomRegPath = path;
+                        CurrentCustomRegPath = path;
+                        this.RefreshList();
+                        frm.Show();
                         frm.Activate();
-                        frm.Opacity = 1;
                         break;
                 }
                 switch(Scene)
@@ -627,41 +755,70 @@ namespace ContextMenuManager.Controls
                     case Scenes.PerceivedType:
                     case Scenes.DirectoryType:
                     case Scenes.MenuAnalysis:
+                    case Scenes.DragDrop:
+                    case Scenes.CustomExtensionPerceivedType:
                         if(dlg.ShowDialog() != DialogResult.OK) return;
                         break;
                 }
                 switch(Scene)
                 {
                     case Scenes.CustomExtension:
-                        Selected = CurrentExtension = dlg.Selected;
+                        CurrentExtension = dlg.Selected;
+                        this.RefreshList();
                         break;
                     case Scenes.PerceivedType:
-                        Selected = CurrentPerceivedType = PerceivedTypes[dlg.SelectedIndex];
+                        CurrentPerceivedType = PerceivedTypes[dlg.SelectedIndex];
+                        this.RefreshList();
                         break;
                     case Scenes.DirectoryType:
-                        Selected = CurrentDirectoryType = DirectoryTypes[dlg.SelectedIndex];
+                        CurrentDirectoryType = DirectoryTypes[dlg.SelectedIndex];
+                        this.RefreshList();
+                        break;
+                    case Scenes.CustomExtensionPerceivedType:
+                        string selected = PerceivedTypes[dlg.SelectedIndex];
+                        CurrentExtensionPerceivedType = selected;
+                        this.Text = AppString.Other.SetPerceivedType.Replace("%s", CurrentExtension)
+                            + " " + GetPerceivedTypeName(selected);
+                        break;
+                    case Scenes.DragDrop:
+                        switch(dlg.SelectedIndex)
+                        {
+                            case 0: DefaultDropEffect = DropEffect.Default; break;
+                            case 1: DefaultDropEffect = DropEffect.Copy; break;
+                            case 2: DefaultDropEffect = DropEffect.Move; break;
+                            case 3: DefaultDropEffect = DropEffect.CreateLink; break;
+                        }
+                        this.Text = AppString.Other.SetDefaultDropEffect + " " + GetDropEffectName();
                         break;
                     case Scenes.MenuAnalysis:
                         if(dlg.SelectedIndex == 0)
                         {
-                            using(var dialog = new System.Windows.Forms.OpenFileDialog())
+                            using(var dlg1 = new System.Windows.Forms.OpenFileDialog())
                             {
-                                dialog.DereferenceLinks = false;
-                                if(dialog.ShowDialog() != DialogResult.OK) return;
-                                Selected = CurrentFileObjectPath = dialog.FileName;
+                                dlg1.DereferenceLinks = false;
+                                if(dlg1.ShowDialog() != DialogResult.OK) return;
+                                CurrentFileObjectPath = dlg1.FileName;
                             }
                         }
                         else
                         {
-                            using(var dialog = new FolderBrowserDialog())
+                            using(var dlg2 = new FolderBrowserDialog())
                             {
-                                if(dialog.ShowDialog() != DialogResult.OK) return;
-                                Selected = CurrentFileObjectPath = dialog.SelectedPath;
+                                if(dlg2.ShowDialog() != DialogResult.OK) return;
+                                CurrentFileObjectPath = dlg2.SelectedPath;
                             }
                         }
+                        this.RefreshList();
                         break;
                 }
             }
+
+            private void RefreshList()
+            {
+                ShellList list = (ShellList)this.Parent;
+                list.ClearItems();
+                list.LoadItems();
+            }
         }
 
         sealed class JumpItem : MyListItem
@@ -704,6 +861,12 @@ namespace ContextMenuManager.Controls
                         image = AppImage.LnkFile;
                         index1 = 1;
                         break;
+                    case Scenes.ExeFile:
+                        text = $"[ {AppString.ToolBar.Type} ]  ▶  [ {AppString.SideBar.ExeFile} ]";
+                        using(Icon icon = ResourceIcon.GetExtensionIcon(TargetPath)) image = icon.ToBitmap();
+                        index1 = 1;
+                        index2 = 2;
+                        break;
                     case Scenes.UnknownType:
                         text = $"[ {AppString.ToolBar.Type} ]  ▶  [ {AppString.SideBar.UnknownType} ]";
                         image = AppImage.NotFound;
@@ -712,10 +875,7 @@ namespace ContextMenuManager.Controls
                         break;
                     case Scenes.CustomExtension:
                         text = $"[ {AppString.ToolBar.Type} ]  ▶  [ {AppString.SideBar.CustomExtension} ]  ▶  [ {Extension} ]";
-                        using(Icon icon = ResourceIcon.GetExtensionIcon(Extension))
-                        {
-                            image = icon.ToBitmap();
-                        }
+                        using(Icon icon = ResourceIcon.GetExtensionIcon(Extension)) image = icon.ToBitmap();
                         index1 = 1;
                         index2 = 4;
                         break;
@@ -754,55 +914,7 @@ namespace ContextMenuManager.Controls
 
             public static string Extension = null;
             public static string PerceivedType = null;
-        }
-
-        sealed class PerceivedTypeItem : MyListItem, ITsiRegPathItem
-        {
-            public PerceivedTypeItem()
-            {
-                this.AddCtr(btnSelect);
-                this.ContextMenuStrip = new ContextMenuStrip();
-                TsiRegLocation = new RegLocationMenuItem(this);
-                this.ContextMenuStrip.Items.Add(TsiRegLocation);
-                this.Text = $@"{Tip} {GetPerceivedTypeName(PerceivedType)}";
-                using(Icon icon = ResourceIcon.GetExtensionIcon(CurrentExtension))
-                {
-                    this.Image = icon.ToBitmap();
-                }
-                MyToolTip.SetToolTip(btnSelect, Tip);
-                btnSelect.MouseDown += (sender, e) => ShowSelectDialog();
-                this.TextDoubleClick += (sender, e) => ShowSelectDialog();
-                this.ImageDoubleClick += (sender, e) => ShowSelectDialog();
-            }
-
-            public string ValueName => "PerceivedType";
-            public string RegPath => $@"{RegistryEx.CLASSESROOT}\{CurrentExtension}";
-            private string Tip => AppString.Other.SetPerceivedType.Replace("%s", CurrentExtension);
-            public string PerceivedType
-            {
-                get => Registry.GetValue(RegPath, ValueName, null)?.ToString();
-                set
-                {
-                    if(value == null) RegistryEx.DeleteValue(RegPath, ValueName);
-                    else Registry.SetValue(RegPath, ValueName, value, RegistryValueKind.String);
-                }
-            }
-
-            readonly PictureButton btnSelect = new PictureButton(AppImage.Select);
-            public RegLocationMenuItem TsiRegLocation { get; set; }
-
-            private void ShowSelectDialog()
-            {
-                using(SelectDialog dlg = new SelectDialog())
-                {
-                    dlg.Items = PerceivedTypeNames;
-                    dlg.Title = AppString.Dialog.SelectPerceivedType;
-                    dlg.Selected = GetPerceivedTypeName(PerceivedType);
-                    if(dlg.ShowDialog() != DialogResult.OK) return;
-                    this.Text = $@"{Tip} {dlg.Selected}";
-                    PerceivedType = PerceivedTypes[dlg.SelectedIndex];
-                }
-            }
+            public static string TargetPath = null;
         }
     }
 }

+ 15 - 8
ContextMenuManager/Controls/ShellNewItem.cs

@@ -57,7 +57,6 @@ namespace ContextMenuManager.Controls
         private string DefaultOpenMode => Registry.GetValue($@"{RegistryEx.CLASSESROOT}\{Extension}", "", null)?.ToString();//默认关联打开方式
         private string DefaultOpenModePath => $@"{RegistryEx.CLASSESROOT}\{DefaultOpenMode}";//默认关联打开方式注册表路径
         private string ConfigPath => $@"{RegPath}\Config";
-
         public bool CanSort => !UnableSortExtensions.Contains(Extension, StringComparer.OrdinalIgnoreCase);//能够排序的
         private bool CanEditData => UnableEditDataValues.All(value => Registry.GetValue(RegPath, value, null) == null);//能够编辑初始数据的
         private bool CanChangeCommand => UnableChangeCommandValues.All(value => Registry.GetValue(RegPath, value, null) == null);//能够更改菜单命令的
@@ -69,16 +68,24 @@ namespace ContextMenuManager.Controls
             {
                 string filePath = FileExtension.GetExecutablePath(Extension);
                 if(File.Exists(filePath)) return filePath;
-                using(RegistryKey key = RegistryEx.GetRegistryKey($@"{OpenModePath}\CLSID"))
+                using(RegistryKey oKey = RegistryEx.GetRegistryKey(OpenModePath))
                 {
-                    string value = key?.GetValue("")?.ToString();
-                    if(GuidEx.TryParse(value, out Guid guid))
+                    using(RegistryKey aKey = oKey.OpenSubKey("Application"))
+                    {
+                        string uwp = aKey?.GetValue("AppUserModelID")?.ToString();
+                        if(uwp != null) return "shell:AppsFolder\\" + uwp;
+                    }
+                    using(RegistryKey cKey = oKey.OpenSubKey("CLSID"))
                     {
-                        filePath = GuidInfo.GetFilePath(guid);
-                        if(filePath != null) return filePath;
+                        string value = cKey?.GetValue("")?.ToString();
+                        if(GuidEx.TryParse(value, out Guid guid))
+                        {
+                            filePath = GuidInfo.GetFilePath(guid);
+                            if(filePath != null) return filePath;
+                        }
                     }
                 }
-                return filePath;
+                return null;
             }
         }
 
@@ -258,7 +265,7 @@ namespace ContextMenuManager.Controls
 
         private void EditInitialData()
         {
-            if(MessageBoxEx.Show(AppString.MessageBox.EditInitialData,
+            if(MessageBoxEx.Show(AppString.Message.EditInitialData,
                 MessageBoxButtons.YesNo) != DialogResult.Yes) return;
             using(InputDialog dlg = new InputDialog
             {

+ 2 - 2
ContextMenuManager/Controls/ShellNewList.cs

@@ -144,7 +144,7 @@ namespace ContextMenuManager.Controls
                     string openMode = FileExtension.GetOpenMode(extension);
                     if(string.IsNullOrEmpty(openMode))
                     {
-                        MessageBoxEx.Show(AppString.MessageBox.NoOpenModeExtension);
+                        MessageBoxEx.Show(AppString.Message.NoOpenModeExtension);
                         ExternalProgram.ShowOpenWithDialog(extension);
                         return;
                     }
@@ -154,7 +154,7 @@ namespace ContextMenuManager.Controls
                         {
                             if(item.Extension.Equals(extension, StringComparison.OrdinalIgnoreCase))
                             {
-                                MessageBoxEx.Show(AppString.MessageBox.HasBeenAdded);
+                                MessageBoxEx.Show(AppString.Message.HasBeenAdded);
                                 return;
                             }
                         }

+ 1 - 1
ContextMenuManager/Controls/ShellStoreDialog.cs

@@ -132,7 +132,7 @@ namespace ContextMenuManager.Controls
 
         public override void DeleteMe()
         {
-            if(IsPublic && MessageBoxEx.Show(AppString.MessageBox.ConfirmDeleteReferenced,
+            if(IsPublic && MessageBoxEx.Show(AppString.Message.ConfirmDeleteReferenced,
                 MessageBoxButtons.YesNo) != DialogResult.Yes) return;
             base.DeleteMe();
         }

+ 9 - 13
ContextMenuManager/Controls/ShellSubMenuDialog.cs

@@ -113,21 +113,20 @@ namespace ContextMenuManager.Controls
                     this.FormBorderStyle = FormBorderStyle.FixedSingle;
                     this.StartPosition = FormStartPosition.CenterParent;
                     this.Font = new Font(SystemFonts.MessageBoxFont.FontFamily, 9F);
-                    this.Controls.AddRange(new Control[] { pnlTop, btnPrivate, btnPublic });
-                    pnlTop.Controls.Add(lblInfo);
+                    this.Controls.AddRange(new Control[] { pnlInfo, btnPrivate, btnPublic });
+                    pnlInfo.Controls.Add(lblInfo);
                     int a = 20.DpiZoom();
                     this.ClientSize = new Size(lblInfo.Width + 2 * a, lblInfo.Height + btnPrivate.Height + 3 * a);
                     lblInfo.Location = new Point(a, a);
-                    pnlTop.Height = lblInfo.Bottom + a;
-                    btnPrivate.Top = btnPublic.Top = pnlTop.Bottom + a / 2;
-                    btnPublic.Left = pnlTop.Width - btnPublic.Width - a;
+                    pnlInfo.Height = lblInfo.Bottom + a;
+                    btnPrivate.Top = btnPublic.Top = pnlInfo.Bottom + a / 2;
+                    btnPublic.Left = pnlInfo.Width - btnPublic.Width - a;
                     btnPrivate.Left = btnPublic.Left - btnPrivate.Width - a;
                     btnPrivate.Click += (sender, e) => Mode = SubMode.Private;
                     btnPublic.Click += (sender, e) => Mode = SubMode.Public;
                 }
 
                 public enum SubMode { Public, Private, None }
-
                 public SubMode Mode { get; private set; } = SubMode.None;
 
                 readonly Label lblInfo = new Label
@@ -135,20 +134,17 @@ namespace ContextMenuManager.Controls
                     Text = AppString.Dialog.SelectSubMenuMode,
                     AutoSize = true
                 };
-
-                readonly Panel pnlTop = new Panel
+                readonly Panel pnlInfo = new Panel
                 {
                     BackColor = Color.White,
                     Dock = DockStyle.Top
                 };
-
                 readonly Button btnPrivate = new Button
                 {
                     Text = AppString.Dialog.Private,
                     DialogResult = DialogResult.OK,
                     AutoSize = true
                 };
-
                 readonly Button btnPublic = new Button
                 {
                     Text = AppString.Dialog.Public,
@@ -297,7 +293,7 @@ namespace ContextMenuManager.Controls
 
                     private void DeleteReference()
                     {
-                        if(MessageBoxEx.Show(AppString.MessageBox.ConfirmDeleteReference,
+                        if(MessageBoxEx.Show(AppString.Message.ConfirmDeleteReference,
                             MessageBoxButtons.YesNo) == DialogResult.Yes)
                         {
                             Owner.DeleteItem(this);
@@ -380,7 +376,7 @@ namespace ContextMenuManager.Controls
                     string sckValue = GetValue(parentPath, "ExtendedSubCommandsKey", null)?.ToString();
                     if(!sckValue.IsNullOrWhiteSpace())
                     {
-                        this.ShellPath = $@"{RegistryEx.CLASSESROOT}\{sckValue}";
+                        this.ShellPath = $@"{RegistryEx.CLASSESROOT}\{sckValue}\shell";
                     }
                     else
                     {
@@ -596,7 +592,7 @@ namespace ContextMenuManager.Controls
                         if(item.GetType().BaseType == typeof(SubShellTypeItem)) count++;
                     }
                     bool flag = count < 16;
-                    if(!flag) MessageBoxEx.Show(AppString.MessageBox.CannotAddNewItem);
+                    if(!flag) MessageBoxEx.Show(AppString.Message.CannotAddNewItem);
                     return flag;
                 }
             }

+ 142 - 100
ContextMenuManager/Controls/ThirdRulesList.cs

@@ -4,6 +4,7 @@ using ContextMenuManager.Controls.Interfaces;
 using Microsoft.Win32;
 using System;
 using System.IO;
+using System.Text;
 using System.Xml;
 
 namespace ContextMenuManager.Controls
@@ -12,11 +13,30 @@ namespace ContextMenuManager.Controls
     {
         public void LoadItems()
         {
-            try
+            string webPath = AppConfig.WebThirdRulesDic;
+            string userPath = AppConfig.UserThirdRulesDic;
+            string contents = Properties.Resources.ThirdRulesDic;
+            if(!File.Exists(webPath)) File.WriteAllText(webPath, contents, Encoding.Unicode);
+            GroupPathItem webGroupItem = new GroupPathItem(webPath, ObjectPath.PathType.File);
+            GroupPathItem userGroupItem = new GroupPathItem(userPath, ObjectPath.PathType.File);
+            webGroupItem.Text = AppString.SideBar.Dictionaries;
+            userGroupItem.Text = AppString.Other.UserDictionaries;
+            webGroupItem.Image = AppImage.App;
+            userGroupItem.Image = AppImage.User;
+            LoadDocItems(webPath, webGroupItem);
+            LoadDocItems(userPath, userGroupItem);
+        }
+
+        private void LoadDocItems(string xmlPath, GroupPathItem groupItem)
+        {
+            if(!File.Exists(xmlPath)) return;
+            this.AddItem(groupItem);
+            XmlDocument doc = new XmlDocument();
+            try { doc.LoadXml(File.ReadAllText(xmlPath, EncodingType.GetType(xmlPath))); }
+            catch { return; }
+            foreach(XmlElement groupXE in doc.DocumentElement.ChildNodes)
             {
-                XmlDocument doc = AppDic.ReadXml(AppConfig.WebThirdRulesDic,
-                    AppConfig.UserThirdRulesDic, Properties.Resources.ThirdRulesDic);
-                foreach(XmlElement groupXE in doc.DocumentElement.ChildNodes)
+                try
                 {
                     Guid guid = Guid.Empty;
                     if(groupXE.HasAttribute("Guid"))
@@ -28,141 +48,163 @@ namespace ContextMenuManager.Controls
                         else continue;
                     }
 
-                    GroupPathItem groupItem;
+                    SubGroupItem subGroupItem;
                     bool isIniGroup = groupXE.HasAttribute("IsIniGroup");
                     string attribute = isIniGroup ? "FilePath" : "RegPath";
                     ObjectPath.PathType pathType = isIniGroup ? ObjectPath.PathType.File : ObjectPath.PathType.Registry;
-                    groupItem = new GroupPathItem(groupXE.GetAttribute(attribute), pathType)
+                    subGroupItem = new SubGroupItem(groupXE.GetAttribute(attribute), pathType)
                     {
                         Text = groupXE.GetAttribute("Text"),
                         Image = GuidInfo.GetImage(guid)
                     };
-                    if(groupItem.Text.IsNullOrWhiteSpace()) groupItem.Text = GuidInfo.GetText(guid);
-                    this.AddItem(groupItem);
+                    if(subGroupItem.Text.IsNullOrWhiteSpace()) subGroupItem.Text = GuidInfo.GetText(guid);
+                    this.AddItem(subGroupItem);
 
                     string GetRuleFullRegPath(string regPath)
                     {
-                        if(string.IsNullOrEmpty(regPath)) regPath = groupItem.TargetPath;
-                        else if(regPath.StartsWith("\\")) regPath = groupItem.TargetPath + regPath;
+                        if(string.IsNullOrEmpty(regPath)) regPath = subGroupItem.TargetPath;
+                        else if(regPath.StartsWith("\\")) regPath = subGroupItem.TargetPath + regPath;
                         return regPath;
                     };
 
                     foreach(XmlElement itemXE in groupXE.ChildNodes)
                     {
-                        if(!EnhanceMenusList.JudgeOSVersion(itemXE)) continue;
-                        RuleItem ruleItem;
-                        ItemInfo info = new ItemInfo
-                        {
-                            Text = itemXE.GetAttribute("Text"),
-                            Tip = itemXE.GetAttribute("Tip"),
-                            RestartExplorer = itemXE.HasAttribute("RestartExplorer"),
-                        };
-                        int defaultValue = 0, maxValue = 0, minValue = 0;
-                        if(itemXE.HasAttribute("IsNumberItem"))
-                        {
-                            XmlElement ruleXE = (XmlElement)itemXE.SelectSingleNode("Rule");
-                            defaultValue = ruleXE.HasAttribute("Default") ? Convert.ToInt32(ruleXE.GetAttribute("Default")) : 0;
-                            maxValue = ruleXE.HasAttribute("Max") ? Convert.ToInt32(ruleXE.GetAttribute("Max")) : int.MaxValue;
-                            minValue = ruleXE.HasAttribute("Min") ? Convert.ToInt32(ruleXE.GetAttribute("Min")) : int.MinValue;
-                        }
-
-                        if(isIniGroup)
+                        try
                         {
-                            XmlElement ruleXE = (XmlElement)itemXE.SelectSingleNode("Rule");
-                            string iniPath = ruleXE.GetAttribute("FilePath");
-                            if(iniPath.IsNullOrWhiteSpace()) iniPath = groupItem.TargetPath;
-                            string section = ruleXE.GetAttribute("Section");
-                            string keyName = ruleXE.GetAttribute("KeyName");
-                            if(itemXE.HasAttribute("IsNumberItem"))
-                            {
-                                var rule = new NumberIniRuleItem.IniRule
-                                {
-                                    IniPath = iniPath,
-                                    Section = section,
-                                    KeyName = keyName,
-                                    DefaultValue = defaultValue,
-                                    MaxValue = maxValue,
-                                    MinValue = maxValue
-                                };
-                                ruleItem = new NumberIniRuleItem(rule, info);
-                            }
-                            else if(itemXE.HasAttribute("IsStringItem"))
+                            if(!EnhanceMenusList.JudgeOSVersion(itemXE)) continue;
+                            RuleItem ruleItem;
+                            ItemInfo info = new ItemInfo
                             {
-                                var rule = new StringIniRuleItem.IniRule
-                                {
-                                    IniPath = iniPath,
-                                    Secation = section,
-                                    KeyName = keyName
-                                };
-                                ruleItem = new StringIniRuleItem(rule, info);
-                            }
-                            else
-                            {
-                                var rule = new VisbleIniRuleItem.IniRule
-                                {
-                                    IniPath = iniPath,
-                                    Section = section,
-                                    KeyName = keyName,
-                                    TurnOnValue = ruleXE.HasAttribute("On") ? ruleXE.GetAttribute("On") : null,
-                                    TurnOffValue = ruleXE.HasAttribute("Off") ? ruleXE.GetAttribute("Off") : null,
-                                };
-                                ruleItem = new VisbleIniRuleItem(rule, info);
-                            }
-                        }
-
-                        else
-                        {
+                                Text = itemXE.GetAttribute("Text"),
+                                Tip = itemXE.GetAttribute("Tip"),
+                                RestartExplorer = itemXE.HasAttribute("RestartExplorer"),
+                            };
+                            int defaultValue = 0, maxValue = 0, minValue = 0;
                             if(itemXE.HasAttribute("IsNumberItem"))
                             {
                                 XmlElement ruleXE = (XmlElement)itemXE.SelectSingleNode("Rule");
-                                var rule = new NumberRegRuleItem.RegRule
-                                {
-                                    RegPath = GetRuleFullRegPath(ruleXE.GetAttribute("RegPath")),
-                                    ValueName = ruleXE.GetAttribute("ValueName"),
-                                    ValueKind = GetValueKind(ruleXE.GetAttribute("ValueKind")),
-                                    DefaultValue = defaultValue,
-                                    MaxValue = maxValue,
-                                    MinValue = minValue
-                                };
-                                ruleItem = new NumberRegRuleItem(rule, info);
+                                defaultValue = ruleXE.HasAttribute("Default") ? Convert.ToInt32(ruleXE.GetAttribute("Default")) : 0;
+                                maxValue = ruleXE.HasAttribute("Max") ? Convert.ToInt32(ruleXE.GetAttribute("Max")) : int.MaxValue;
+                                minValue = ruleXE.HasAttribute("Min") ? Convert.ToInt32(ruleXE.GetAttribute("Min")) : int.MinValue;
                             }
-                            else if(itemXE.HasAttribute("IsStringItem"))
+
+                            if(isIniGroup)
                             {
                                 XmlElement ruleXE = (XmlElement)itemXE.SelectSingleNode("Rule");
-                                var rule = new StringRegRuleItem.RegRule
+                                string iniPath = ruleXE.GetAttribute("FilePath");
+                                if(iniPath.IsNullOrWhiteSpace()) iniPath = subGroupItem.TargetPath;
+                                string section = ruleXE.GetAttribute("Section");
+                                string keyName = ruleXE.GetAttribute("KeyName");
+                                if(itemXE.HasAttribute("IsNumberItem"))
+                                {
+                                    var rule = new NumberIniRuleItem.IniRule
+                                    {
+                                        IniPath = iniPath,
+                                        Section = section,
+                                        KeyName = keyName,
+                                        DefaultValue = defaultValue,
+                                        MaxValue = maxValue,
+                                        MinValue = maxValue
+                                    };
+                                    ruleItem = new NumberIniRuleItem(rule, info);
+                                }
+                                else if(itemXE.HasAttribute("IsStringItem"))
+                                {
+                                    var rule = new StringIniRuleItem.IniRule
+                                    {
+                                        IniPath = iniPath,
+                                        Secation = section,
+                                        KeyName = keyName
+                                    };
+                                    ruleItem = new StringIniRuleItem(rule, info);
+                                }
+                                else
                                 {
-                                    RegPath = GetRuleFullRegPath(ruleXE.GetAttribute("RegPath")),
-                                    ValueName = ruleXE.GetAttribute("ValueName"),
-                                };
-                                ruleItem = new StringRegRuleItem(rule, info);
+                                    var rule = new VisbleIniRuleItem.IniRule
+                                    {
+                                        IniPath = iniPath,
+                                        Section = section,
+                                        KeyName = keyName,
+                                        TurnOnValue = ruleXE.HasAttribute("On") ? ruleXE.GetAttribute("On") : null,
+                                        TurnOffValue = ruleXE.HasAttribute("Off") ? ruleXE.GetAttribute("Off") : null,
+                                    };
+                                    ruleItem = new VisbleIniRuleItem(rule, info);
+                                }
                             }
                             else
                             {
-                                XmlNodeList ruleXNList = itemXE.SelectNodes("Rule");
-                                var rules = new VisibleRegRuleItem.RegRule[ruleXNList.Count];
-                                for(int i = 0; i < ruleXNList.Count; i++)
+                                if(itemXE.HasAttribute("IsNumberItem"))
                                 {
-                                    XmlElement ruleXE = (XmlElement)ruleXNList[i];
-                                    rules[i] = new VisibleRegRuleItem.RegRule
+                                    XmlElement ruleXE = (XmlElement)itemXE.SelectSingleNode("Rule");
+                                    var rule = new NumberRegRuleItem.RegRule
                                     {
                                         RegPath = GetRuleFullRegPath(ruleXE.GetAttribute("RegPath")),
                                         ValueName = ruleXE.GetAttribute("ValueName"),
                                         ValueKind = GetValueKind(ruleXE.GetAttribute("ValueKind")),
-                                        TurnOnValue = ruleXE.HasAttribute("On") ? ruleXE.GetAttribute("On") : null,
-                                        TurnOffValue = ruleXE.HasAttribute("Off") ? ruleXE.GetAttribute("Off") : null,
+                                        DefaultValue = defaultValue,
+                                        MaxValue = maxValue,
+                                        MinValue = minValue
                                     };
+                                    ruleItem = new NumberRegRuleItem(rule, info);
+                                }
+                                else if(itemXE.HasAttribute("IsStringItem"))
+                                {
+                                    XmlElement ruleXE = (XmlElement)itemXE.SelectSingleNode("Rule");
+                                    var rule = new StringRegRuleItem.RegRule
+                                    {
+                                        RegPath = GetRuleFullRegPath(ruleXE.GetAttribute("RegPath")),
+                                        ValueName = ruleXE.GetAttribute("ValueName"),
+                                    };
+                                    ruleItem = new StringRegRuleItem(rule, info);
+                                }
+                                else
+                                {
+                                    XmlNodeList ruleXNList = itemXE.SelectNodes("Rule");
+                                    var rules = new VisibleRegRuleItem.RegRule[ruleXNList.Count];
+                                    for(int i = 0; i < ruleXNList.Count; i++)
+                                    {
+                                        XmlElement ruleXE = (XmlElement)ruleXNList[i];
+                                        rules[i] = new VisibleRegRuleItem.RegRule
+                                        {
+                                            RegPath = GetRuleFullRegPath(ruleXE.GetAttribute("RegPath")),
+                                            ValueName = ruleXE.GetAttribute("ValueName"),
+                                            ValueKind = GetValueKind(ruleXE.GetAttribute("ValueKind"))
+                                        };
+                                        string turnOn = ruleXE.HasAttribute("On") ? ruleXE.GetAttribute("On") : null;
+                                        string turnOff = ruleXE.HasAttribute("Off") ? ruleXE.GetAttribute("Off") : null;
+                                        switch(rules[i].ValueKind)
+                                        {
+                                            case RegistryValueKind.Binary:
+                                                rules[i].TurnOnValue = turnOn != null ? EnhanceMenusList.ConvertToBinary(turnOn) : null;
+                                                rules[i].TurnOffValue = turnOff != null ? EnhanceMenusList.ConvertToBinary(turnOff) : null;
+                                                break;
+                                            case RegistryValueKind.DWord:
+                                                if(turnOn == null) rules[i].TurnOnValue = null;
+                                                else rules[i].TurnOnValue = Convert.ToInt32(turnOn);
+                                                if(turnOff == null) rules[i].TurnOffValue = null;
+                                                else rules[i].TurnOffValue = Convert.ToInt32(turnOff);
+                                                break;
+                                            default:
+                                                rules[i].TurnOnValue = turnOn;
+                                                rules[i].TurnOffValue = turnOff;
+                                                break;
+                                        }
+                                    }
+                                    ruleItem = new VisibleRegRuleItem(rules, info);
                                 }
-                                ruleItem = new VisibleRegRuleItem(rules, info);
                             }
+                            this.AddItem(ruleItem);
+                            ruleItem.FoldGroupItem = subGroupItem;
                         }
-                        this.AddItem(ruleItem);
-                        ruleItem.FoldGroupItem = groupItem;
+                        catch { continue; }
                     }
-                    groupItem.IsFold = true;
-                    groupItem.HideWhenNoSubItem();
+                    subGroupItem.HideWhenNoSubItem();
+                    subGroupItem.FoldGroupItem = groupItem;
                 }
+                catch { continue; }
             }
-            catch { }
+            groupItem.IsFold = true;
+            groupItem.HideWhenNoSubItem();
         }
 
         private static RegistryValueKind GetValueKind(string data)

+ 2 - 2
ContextMenuManager/Controls/TranslateDialog.cs

@@ -163,8 +163,8 @@ namespace ContextMenuManager.Controls
                         = this.ClientSize.Width - (w + 3 * a);
 
                     btnCancel.Left = this.ClientSize.Width - btnCancel.Width - a;
-                    btnSave.Left = btnCancel.Left - btnSave.Width - 2 * a;
-                    btnBrowse.Left = btnSave.Left - btnBrowse.Width - 2 * a;
+                    btnSave.Left = btnCancel.Left - btnSave.Width - a;
+                    btnBrowse.Left = btnSave.Left - btnBrowse.Width - a;
                 };
                 this.ClientSize = new Size(w + 23 * a, h + 3 * 4 * a + 7 * a);
                 this.MinimumSize = this.Size;

+ 22 - 10
ContextMenuManager/Controls/UwpModeItem.cs

@@ -11,9 +11,8 @@ namespace ContextMenuManager.Controls
     sealed class UwpModeItem : MyListItem, IChkVisibleItem, ITsiRegPathItem, ITsiFilePathItem,
         IBtnShowMenuItem, ITsiWebSearchItem, ITsiRegExportItem, ITsiRegDeleteItem, ITsiGuidItem
     {
-        private const string PackagePath = @"HKEY_CLASSES_ROOT\PackagedCom\Package";
-        private const string AppXPath = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Appx";
-        private static readonly string WindowAppsDir = Registry.GetValue(AppXPath, "PackageRoot", null)?.ToString();
+        private const string PackageRegPath = @"HKEY_CLASSES_ROOT\PackagedCom\Package";
+        private const string PackagesRegPath = @"HKEY_CLASSES_ROOT\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\PackageRepository\Packages";
 
         public UwpModeItem(string uwpName, Guid guid)
         {
@@ -21,7 +20,7 @@ namespace ContextMenuManager.Controls
             this.UwpName = uwpName;
             this.InitializeComponents();
             ChkVisible.Checked = ItemVisible;
-            this.Visible = File.Exists(ItemFilePath);
+            this.Visible = GetPackageName(uwpName) != null;
             this.Image = GuidInfo.GetImage(guid);
             this.Text = this.ItemText;
         }
@@ -66,7 +65,7 @@ namespace ContextMenuManager.Controls
 
         public static string GetPackageName(string uwpName)
         {
-            using(RegistryKey packageKey = RegistryEx.GetRegistryKey(PackagePath))
+            using(RegistryKey packageKey = RegistryEx.GetRegistryKey(PackageRegPath))
             {
                 if(packageKey == null) return null;
                 foreach(string packageName in packageKey.GetSubKeyNames())
@@ -84,17 +83,30 @@ namespace ContextMenuManager.Controls
         {
             string packageName = GetPackageName(uwpName);
             if(packageName == null) return null;
-            else return $@"{PackagePath}\{packageName}\Class\{guid:B}";
+            else return $@"{PackageRegPath}\{packageName}\Class\{guid:B}";
         }
 
         public static string GetFilePath(string uwpName, Guid guid)
         {
             string regPath = GetGuidRegPath(uwpName, guid);
             if(regPath == null) return null;
-            string dirPath = $@"{WindowAppsDir}\{GetPackageName(uwpName)}";
-            string path = Registry.GetValue(regPath, "DllPath", null)?.ToString();
-            if(path.IsNullOrWhiteSpace()) return dirPath;
-            else return $@"{dirPath}\{path}";
+            string packageName = GetPackageName(uwpName);
+            using(RegistryKey pKey = RegistryEx.GetRegistryKey($@"{PackagesRegPath}\{packageName}"))
+            {
+                if(pKey == null) return null;
+                string dirPath = pKey.GetValue("Path")?.ToString();
+                string dllPath = Registry.GetValue(regPath, "DllPath", null)?.ToString();
+                string filePath = $@"{dirPath}\{dllPath}";
+                if(File.Exists(filePath)) return filePath;
+                string[] names = pKey.GetSubKeyNames();
+                if(names.Length == 1)
+                {
+                    filePath = "shell:AppsFolder\\" + names[0];
+                    return filePath;
+                }
+                if(Directory.Exists(dirPath)) return dirPath;
+                return null;
+            }
         }
 
         public string SearchText => Text;

+ 2 - 2
ContextMenuManager/Controls/WinXGroupItem.cs

@@ -72,7 +72,7 @@ namespace ContextMenuManager.Controls
 
         private void RestoreDefault()
         {
-            if(MessageBoxEx.Show(AppString.MessageBox.RestoreDefault, MessageBoxButtons.OKCancel) == DialogResult.OK)
+            if(MessageBoxEx.Show(AppString.Message.RestoreDefault, MessageBoxButtons.OKCancel) == DialogResult.OK)
             {
                 File.SetAttributes(TargetPath, File.GetAttributes(DefaultGroupPath));
                 string[] paths = Directory.GetFiles(TargetPath);
@@ -95,7 +95,7 @@ namespace ContextMenuManager.Controls
         public void DeleteMe()
         {
             bool flag = Directory.GetFiles(TargetPath, "*.lnk").Length > 0;
-            if(flag && MessageBoxEx.Show(AppString.MessageBox.DeleteGroup, MessageBoxButtons.OKCancel) != DialogResult.OK) return;
+            if(flag && MessageBoxEx.Show(AppString.Message.DeleteGroup, MessageBoxButtons.OKCancel) != DialogResult.OK) return;
             File.SetAttributes(TargetPath, FileAttributes.Normal);
             Directory.Delete(TargetPath, true);
             if(flag)

+ 1 - 2
ContextMenuManager/Controls/WinXItem.cs

@@ -110,8 +110,6 @@ namespace ContextMenuManager.Controls
 
         readonly ToolStripMenuItem TsiDetails = new ToolStripMenuItem(AppString.Menu.Details);
         readonly ToolStripMenuItem TsiChangeGroup = new ToolStripMenuItem(AppString.Menu.ChangeGroup);
-
-
         private void InitializeComponents()
         {
             BtnShowMenu = new MenuButton(this);
@@ -142,6 +140,7 @@ namespace ContextMenuManager.Controls
                 {
                     Image = ItemIcon.ToBitmap();
                     WinXHasher.HashLnk(FilePath);
+                    ExplorerRestarter.Show();
                 }
             };
         }

+ 1 - 1
ContextMenuManager/Controls/WinXList.cs

@@ -54,7 +54,7 @@ namespace ContextMenuManager.Controls
             if(sorted)
             {
                 ExplorerRestarter.Show();
-                MessageBoxEx.Show(AppString.MessageBox.WinXSorted);
+                MessageBoxEx.Show(AppString.Message.WinXSorted);
             }
         }
 

+ 19 - 6
ContextMenuManager/GuidInfo.cs

@@ -5,6 +5,7 @@ using System;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Drawing;
+using System.Globalization;
 using System.IO;
 using System.Text;
 
@@ -24,9 +25,9 @@ namespace ContextMenuManager
             public int IconIndex { get; set; }
         }
 
-        private static readonly IniReader AppDic = new IniReader(new StringBuilder(Properties.Resources.GuidInfosDic));
+        private static readonly IniReader WebDic = new IniReader(AppConfig.WebGuidInfosDic);
         public static readonly IniReader UserDic = new IniReader(AppConfig.UserGuidInfosDic);
-        public static readonly IniReader WebDic = new IniReader(AppConfig.WebGuidInfosDic);
+        private static readonly IniReader AppDic = new IniReader(new StringBuilder(Properties.Resources.GuidInfosDic));
         public static readonly Dictionary<Guid, IconLocation> IconLocationDic = new Dictionary<Guid, IconLocation>();
         private static readonly Dictionary<Guid, string> FilePathDic = new Dictionary<Guid, string>();
         public static readonly Dictionary<Guid, string> ItemTextDic = new Dictionary<Guid, string>();
@@ -36,10 +37,12 @@ namespace ContextMenuManager
         private static bool TryGetValue(Guid guid, string key, out string value)
         {
             //用户自定义字典优先
+            value = string.Empty;
             string section = guid.ToString();
-            if(UserDic.TryGetValue(section, key, out value)) return true;
-            if(WebDic.TryGetValue(section, key, out value)) return true;
-            if(AppDic.TryGetValue(section, key, out value)) return true;
+            foreach(IniReader reader in new[] { UserDic, WebDic, AppDic })
+            {
+                if(reader.TryGetValue(section, key, out value)) return true;
+            }
             return false;
         }
 
@@ -96,12 +99,22 @@ namespace ContextMenuManager
             if(ItemTextDic.ContainsKey(guid)) itemText = ItemTextDic[guid];
             else
             {
-                if(TryGetValue(guid, "Text", out itemText))
+                if(TryGetValue(guid, "ResText", out itemText))
                 {
                     itemText = GetAbsStr(guid, itemText, true);
                     itemText = ResourceString.GetDirectString(itemText);
                 }
                 if(itemText.IsNullOrWhiteSpace())
+                {
+                    string uiText = CultureInfo.CurrentUICulture.Name + "-Text";
+                    TryGetValue(guid, uiText, out itemText);
+                    if(itemText.IsNullOrWhiteSpace())
+                    {
+                        TryGetValue(guid, "Text", out itemText);
+                        itemText = ResourceString.GetDirectString(itemText);
+                    }
+                }
+                if(itemText.IsNullOrWhiteSpace())
                 {
                     foreach(string clsidPath in ClsidPaths)
                     {

+ 7 - 2
ContextMenuManager/MainForm.cs

@@ -248,7 +248,13 @@ namespace ContextMenuManager
                     if(item is ITsiFilePathItem pathItem)
                     {
                         string path = pathItem.ItemFilePath;
-                        if(File.Exists(path)) { StatusBar.Text = path; return; }
+                        if(path != null)
+                        {
+                            if(File.Exists(path) || path.StartsWith("shell:AppsFolder"))
+                            {
+                                StatusBar.Text = path; return;
+                            }
+                        }
                     }
                     if(item is GuidBlockedItem guidItem)
                     {
@@ -335,7 +341,6 @@ namespace ContextMenuManager
                     languagesBox.Visible = true;
                     break;
                 case 2:
-                    dictionariesBox.LoadTexts();
                     dictionariesBox.Visible = true;
                     break;
                 case 3:

+ 3 - 6
ContextMenuManager/Program.cs

@@ -13,15 +13,12 @@ namespace ContextMenuManager
     static class Program
     {
         [STAThread]
-        static void Main(string[] args)
+        static void Main()
         {
+            if(SingleInstance.IsRunning()) return;
             Application.EnableVisualStyles();
             Application.SetCompatibleTextRenderingDefault(false);
-
-            bool isRestart = args.Length > 0 && args[0] == "Restart";
-            if(!isRestart && SingleInstance.IsRunning()) return;
-
-            Updater.PeriodicUpdate();
+            new Action(Updater.PeriodicUpdate).BeginInvoke(null, null);
             Application.Run(new MainForm());
         }
     }

+ 2 - 2
ContextMenuManager/Properties/AssemblyInfo.cs

@@ -11,5 +11,5 @@ using System.Runtime.InteropServices;
 [assembly: AssemblyCulture("")]
 [assembly: ComVisible(false)]
 [assembly: Guid("35190ec1-2515-488d-a2e9-825d6ff67aa2")]
-[assembly: AssemblyVersion("3.2.0.0")]
-[assembly: AssemblyFileVersion("3.2.0.0")]
+[assembly: AssemblyVersion("3.3.0.0")]
+[assembly: AssemblyFileVersion("3.3.0.0")]

+ 19 - 12
ContextMenuManager/Properties/Resources.Designer.cs

@@ -177,7 +177,7 @@ namespace ContextMenuManager.Properties {
         /// <summary>
         ///   查找类似 &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
         ///&lt;!--此文件为常用右键菜单字典,
-        ///Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开始, 子元素Value表示该项的注册表键值,目前仅支持REG_SZ、REG_DWORD、REG_EXPAND_SZ的键值类型,
+        ///Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开始, 子元素Value表示该项的注册表键值,目前仅支持REG_SZ、REG_DWORD、REG_EXPAND_SZ、REG_BINARY的键值类型,
         ///子元素SubKey的所有子元素是该项的子项,项名即为元素名; 每一Item项和SubKey的所有子元素的属性Default为该注册表项默认值,不放在Value\REG_SZ元素里面是为了防止与可能存在的键名为Default的键产生冲突
         ///由于Shell项太过复杂,程序只根据注册表项名判断存在即启用,故同一场景下不允许有相同KeyName属性的Shell项目,ShellEx项只要Guid符合则为启用--&gt;
         ///&lt;Data&gt;
@@ -185,7 +185,7 @@ namespace ContextMenuManager.Properties {
         ///    &lt;Shell&gt;
         ///      &lt;Item KeyName=&apos;CopyContent&apos; Tip=&apos;不需打开文件直接复制文件文本内容&amp;#x000A;非UTF-16 LE(或带BOM)编码会乱码&apos;&gt;
         ///        &lt;Value&gt;
-        ///          &lt;REG_ [字符串的其余部分被截断]&quot;; 的本地化字符串。
+        ///     [字符串的其余部分被截断]&quot;; 的本地化字符串。
         /// </summary>
         internal static string EnhanceMenusDic {
             get {
@@ -200,21 +200,18 @@ namespace ContextMenuManager.Properties {
         ///;&lt;GUID&gt;可通过右键程序内ShellEx项目&quot;复制guid&quot;获取
         ///;不带括号的&lt;GUID&gt;为字典索引
         ///
-        ///;&lt;Text&gt;:
-        ///;Text为菜单项目名称
-        ///;可以赋值为引用资源文件字符串资源的本地化字符串,
+        ///;&lt;Text&gt;、&lt;ResText&gt;、&lt;[地区文化代码]-Text&gt;
+        ///;菜单项目名称
+        ///;优先级为 &lt;ResText&gt;,&lt;[地区文化代码]-Text&gt;,&lt;Text&gt;
+        ///;&lt;ResText&gt;为引用资源文件字符串资源的本地化字符串,
         ///;格式为&quot;@&lt;资源文件路径&gt;,-&lt;字符串资源索引&gt;&quot;,如赋值为&quot;@shell32.dll,-3576&quot;
-        ///;也可以赋值为直接显示名称,如赋值为&quot;使用XXX打开&quot;
+        ///;[地区文化代码]-Text为系统UI语言直接显示文本,比如zh-CN为中国简体中文,en-US为美国英语
+        ///;Text默认为中国简体中文显示文本
         ///
         ///;&lt;Icon&gt;:
         ///;Icon为菜单项目图标资源位置
         ///;格式为&quot;&lt;资源文件路径&gt;,&lt;图标序号&gt;&quot;,如赋值为&quot;C:Windows\System32\imageres.dll,203&quot;
-        ///;&lt;图标序号&gt;为负数则为图标资源索引,为非负数则为图标资源顺序序号
-        ///;Icon为空时默认提取文件第一个图标,没有图标则使用dll文件默认图标
-        ///
-        ///;&lt;资源文件路径&gt;:
-        ///;&lt;Text&gt;和&lt;Icon&gt;中的&lt;资源文件路径&gt;一般使用相对路径
-        ///;如果资源文件所在 [字符串的其余部分被截断]&quot;; 的本地化字符串。
+        ///;&lt;图标序号&gt;为负数则为图标资源索引, [字符串的其余部分被截断]&quot;; 的本地化字符串。
         /// </summary>
         internal static string GuidInfosDic {
             get {
@@ -397,6 +394,16 @@ namespace ContextMenuManager.Properties {
             }
         }
         
+        /// <summary>
+        ///   查找 System.Drawing.Bitmap 类型的本地化资源。
+        /// </summary>
+        internal static System.Drawing.Bitmap User {
+            get {
+                object obj = ResourceManager.GetObject("User", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
         /// <summary>
         ///   查找类似 &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
         ///&lt;!-- 微软在Win10右键菜单中新增的UWP模块, 非Shell、ShellEx类型,

+ 6 - 3
ContextMenuManager/Properties/Resources.resx

@@ -112,12 +112,12 @@
     <value>2.0</value>
   </resheader>
   <resheader name="reader">
-    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
   <resheader name="writer">
-    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
-  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
   <data name="About" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>resources\images\about.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
@@ -202,6 +202,9 @@
   <data name="Up" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>resources\images\up.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
+  <data name="User" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>resources\images\user.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
   <data name="UwpModeItemsDic" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>resources\texts\uwpmodeitemsdic.xml;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
   </data>

BIN
ContextMenuManager/Properties/Resources/Images/User.png


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 59 - 49
ContextMenuManager/Properties/Resources/Texts/AppLanguageDic.ini


+ 68 - 3
ContextMenuManager/Properties/Resources/Texts/EnhanceMenusDic.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--此文件为常用右键菜单字典,
-Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开始, 子元素Value表示该项的注册表键值,目前仅支持REG_SZ、REG_DWORD、REG_EXPAND_SZ的键值类型,
+Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开始, 子元素Value表示该项的注册表键值,目前仅支持REG_SZ、REG_DWORD、REG_EXPAND_SZ、REG_BINARY的键值类型,
 子元素SubKey的所有子元素是该项的子项,项名即为元素名; 每一Item项和SubKey的所有子元素的属性Default为该注册表项默认值,不放在Value\REG_SZ元素里面是为了防止与可能存在的键名为Default的键产生冲突
 由于Shell项太过复杂,程序只根据注册表项名判断存在即启用,故同一场景下不允许有相同KeyName属性的Shell项目,ShellEx项只要Guid符合则为启用-->
 <Data>
@@ -42,7 +42,8 @@ Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开
     <Shell>
       <Item KeyName='TakeOwnerShip'>
         <Value>
-          <REG_SZ MUIVerb='管理员取得所有权限' HasLUAShield='' NoWorkingDirectory=''/>
+          <REG_SZ MUIVerb='管理员取得所有权限' HasLUAShield='' NoWorkingDirectory=''
+                  AppliesTo='System.ParsingName:&lt;>"::{645FF040-5081-101B-9F08-00AA002F954E}"'/>
         </Value>
         <SubKey>
           <Command>
@@ -697,7 +698,7 @@ Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开
       </Item>
       <Item KeyName='CreateDesktopShortcut'>
         <Value>
-          <REG_SZ MUIVerb='创建桌面快捷方式' Icon='imageres.dll,-110'/>
+          <REG_SZ MUIVerb='创建桌面快捷方式' Icon='imageres.dll,-110' Position='bottom'/>
         </Value>
         <SubKey>
           <Command>
@@ -918,6 +919,70 @@ Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开
     </Shell>
   </Image>
 
+  <EXE Text='EXE程序' Icon='imageres.dll,-15' RegPath='HKEY_CLASSES_ROOT\SystemFileAssociations\.exe'>
+    <Shell>
+      <Item KeyName='FirewallRules'>
+        <Value>
+          <REG_SZ MUIVerb='防火墙规则' Icon='FirewallControlPanel.dll,0' SubCommands=''/>
+        </Value>
+        <SubKey>
+          <Shell>
+            <SubKey>
+              <Item0>
+                <Value>
+                  <REG_SZ MUIVerb='禁止入站' Icon='imageres.dll,-105'/>
+                </Value>
+                <SubKey>
+                  <Command>
+                    <ShellExecute Verb='runas' WindowStyle='0'/>
+                    <FileName>netsh.exe</FileName>
+                    <Arguments>advfirewall firewall add rule name = "%1" dir = in program = "%1" action = block</Arguments>
+                  </Command>
+                </SubKey>
+              </Item0>
+              <Item1>
+                <Value>
+                  <REG_SZ MUIVerb='禁止出站' Icon='imageres.dll,-105'/>
+                </Value>
+                <SubKey>
+                  <Command>
+                    <ShellExecute Verb='runas' WindowStyle='0'/>
+                    <FileName>netsh.exe</FileName>
+                    <Arguments>advfirewall firewall add rule name = "%1" dir = out program = "%1" action = block</Arguments>
+                  </Command>
+                </SubKey>
+              </Item1>
+              <Item2>
+                <Value>
+                  <REG_SZ MUIVerb='允许入站' Icon='imageres.dll,-106'/>
+                </Value>
+                <SubKey>
+                  <Command>
+                    <ShellExecute Verb='runas' WindowStyle='0'/>
+                    <FileName>netsh.exe</FileName>
+                    <Arguments>advfirewall firewall delete rule name = "%1" dir = in program = "%1"</Arguments>
+                  </Command>
+                </SubKey>
+              </Item2>
+              <Item3>
+                <Value>
+                  <REG_SZ MUIVerb='允许出站' Icon='imageres.dll,-106'/>
+                </Value>
+                <SubKey>
+                  <Command>
+                    <ShellExecute Verb='runas' WindowStyle='0'/>
+                    <FileName>netsh.exe</FileName>
+                    <Arguments>advfirewall firewall delete rule name = "%1" dir = out program = "%1"</Arguments>
+                  </Command>
+                </SubKey>
+              </Item3>
+            </SubKey>
+          </Shell>
+        </SubKey>
+      </Item>
+    </Shell>
+  </EXE>
+
   <DLL Text='DLL文件' Icon='imageres.dll,-67' RegPath='HKEY_CLASSES_ROOT\SystemFileAssociations\.dll'>
     <Shell>
       <Item KeyName='Register'>

+ 395 - 372
ContextMenuManager/Properties/Resources/Texts/GuidInfosDic.ini

@@ -4,11 +4,13 @@
 ;<GUID>可通过右键程序内ShellEx项目"复制guid"获取
 ;不带括号的<GUID>为字典索引
 
-;<Text>:
-;Text为菜单项目名称
-;可以赋值为引用资源文件字符串资源的本地化字符串,
+;<Text>、<ResText>、<[地区文化代码]-Text>
+;菜单项目名称
+;优先级为 <ResText>,<[地区文化代码]-Text>,<Text>
+;<ResText>为引用资源文件字符串资源的本地化字符串,
 ;格式为"@<资源文件路径>,-<字符串资源索引>",如赋值为"@shell32.dll,-3576"
-;也可以赋值为直接显示名称,如赋值为"使用XXX打开"
+;[地区文化代码]-Text为系统UI语言直接显示文本,比如zh-CN为中国简体中文,en-US为美国英语
+;Text默认为中国简体中文显示文本
 
 ;<Icon>:
 ;Icon为菜单项目图标资源位置
@@ -17,7 +19,7 @@
 ;Icon为空时默认提取文件第一个图标,没有图标则使用dll文件默认图标
 
 ;<资源文件路径>:
-;<Text>和<Icon>中的<资源文件路径>一般使用相对路径
+;<ResText>和<Icon>中的<资源文件路径>一般使用相对路径
 ;如果资源文件所在目录是"%SystemRoot%"或者"%SystemRoot%\System32"
 ;可省略目录路径仅写文件名(含扩展名),如"imageres.dll"
 
@@ -34,593 +36,614 @@
 ;----------------系统------------------
 ;打开(快捷方式)
 [00021401-0000-0000-c000-000000000046]
-Text=打开(&O)
-Icon=shell32.dll,-16769
-;打开文件所在的位置(&I)
+Text = 打开(&O)
+en-US-Text = &Open
+Icon = shell32.dll,-16769
 [37ea3a21-7493-4208-a011-7f9ea79ce9f5]
-Text=@*,-1033
-Icon=explorer.exe
-;兼容性疑难解答(&Y)
+ResText = @*,-1033
+Text = 打开文件所在的位置(&I)
+Icon = explorer.exe
 [1d27f844-3a1f-4410-85ac-14651078412d]
-Text=@*,-2022
-Icon=msdt.exe
-;播放到设备
+ResText = @*,-2022
+Text = 兼容性疑难解答(&Y)
+Icon = msdt.exe
 [7ad84985-87b4-4a16-be58-8b72a5b390f7]
[email protected],-101
+ResText = @playtomenu.dll,-101
+Text = 播放到设备
 [ffe2a43c-56b9-4bf5-9a79-cc6d4285608a]
-Text=向左、向右旋转
-;设置为桌面背景
+Text = 向左、向右旋转
 [ff609cc7-d34d-4049-a1aa-2293517ffcc6]
-Icon=imageres.dll,-5346
-;固定到任务栏(&K)
+ResText = @stobject.dll,-417
+Text = 设置为桌面背景(&B)
+Icon = imageres.dll,-5346
 [90aa3a4e-1cba-4233-b8bb-535773d48449]
-Text=@*,-5386
-Icon=imageres.dll,-5354
-;打开方式(&H)
+ResText = @*,-5386
+Text = 固定到任务栏(&K)
+Icon = imageres.dll,-5354
 [09799afb-ad67-11d1-abcd-00c04fc30936]
-Text=@*,-5376
-Icon=imageres.dll,-5340
-;复制为路径(&A)
+ResText = @*,-5376
+Text = 打开方式(&H)
+Icon = imageres.dll,-5340
 [f3d06e7c-1e45-4a26-847e-f9fcdee59be0]
-Text=@*,-30328
-Icon=imageres.dll,-5302
+ResText = @*,-30328
+Text = 复制为路径(&A)
+Icon = imageres.dll,-5302
 [3dad6c5d-2167-4cae-9914-f99e41c12cfa]
-Text=包含到库中(&I)
-Icon=imageres.dll,-1001
-;固定到"开始"屏幕(&P)
+Text = 包含到库中(&I)
+Icon = imageres.dll,-1001
 [470c0ebd-5d73-4d58-9ced-e91e22e23282]
[email protected],-51201
-Icon=imageres.dll,-5376
+ResText = @shell32.dll,-51201
+Text = 固定到"开始"屏幕(&P)
+Icon = imageres.dll,-5376
 [a2a9545d-a0c2-42b4-9708-a0b2badd77c8]
-Text=附到「开始」菜单(&U)
-Icon=imageres.dll,-80
-;发送到(&N)
+Text = 附到「开始」菜单(&U)
+Icon = imageres.dll,-80
 [7ba4c740-9e81-11cf-99d3-00aa004ae837]
-Text=@*,-30312
-Icon=imageres.dll,-185
-;下一个桌面背景(&N)
+ResText = @*,-30312
+Text = 发送到(&N)
+Icon = imageres.dll,-185
 [0bf754aa-c967-445c-ab3d-d8fda9bae7ef]
-Text=@*,-416
-Icon=imageres.dll,-5346
-;新建(&W)
+ResText = @*,-416
+Text = 下一个桌面背景(&N)
+Icon = imageres.dll,-5346
 [d969a300-e7ff-11d0-a93b-00a0c90f2719]
-Text=@*,-95851
-Icon=imageres.dll,-5307
+ResText = @*,-95851
+Text = 新建(&W)
+Icon = imageres.dll,-5307
 [6b9228da-9c15-419e-856c-19e768a13bdc]
-Text=Windows 小工具
+Text = Windows 小工具
 [a470f8cf-a1e8-4f65-8335-227475aa5c46]
-Text=加密(&Y)
-Icon=imageres.dll,-59
-;共享
+Text = 加密(&Y)
+Icon = imageres.dll,-59
 [e2bf9676-5f8f-435c-97eb-11607a5bedf7]
-Text=@*,-107
-Icon=ntshrui.dll,-123
-;工作文件夹
+ResText = @*,-107
+Text = 共享
+Icon = ntshrui.dll,-123
 [e61bf828-5e63-4287-bef1-60b1a4fde0e3]
[email protected],-1
-Icon=WorkFolders.exe
-;授予访问权限(&G)
+ResText = @WorkfoldersControl.dll,-1
+Text = 工作文件夹
+Icon = WorkFolders.exe
 [f81e9010-6ea4-11ce-a7ff-00aa003ca9f6]
-Text=@*,-103
-;始终脱机可用(&F)
+ResText = @*,-103
+Text = 授予访问权限(&G)
 [474c98ee-cf3d-41f5-80e3-4aab0ab04301]
-Text=@*,-38
-;增强的存储设备
+ResText = @*,-38
+Text = 始终脱机可用(&F)
 [2854f705-3548-414c-a113-93e27c808c85]
-Text=@*,-101
-;刻录到光盘(&T)
+ResText = @*,-101
+Text = 增强的存储设备
 [fbeb8a05-beee-4442-804e-409d6c4515e9]
-Text=@*,-12560
-Icon=imageres.dll,-30
+ResText = @*,-12560
+Text = 刻录到光盘(&T)
+Icon = imageres.dll,-30
 [59099400-57ff-11ce-bd94-0020af85b590]
-Text=复制磁盘(&Y)...
-;便携设备菜单
+Text = 复制磁盘(&Y)...
 [d6791a63-e7e2-4fee-bf52-5ded8e86e9b8]
-Text=@*,-511
+ResText = @*,-511
+Text = 便携设备菜单
 [0af96ede-aebf-41ed-a1c8-cf7a685505b6]
-Text=不在导航窗格中显示
-Icon=imageres.dll,-5359
-;还原以前的版本(&V)
+Text = 不在导航窗格中显示
+Icon = imageres.dll,-5359
 [596ab062-b4d2-4215-9f74-e9109b0a8153]
-Text=@*,-1037
-;公文包
+ResText = @*,-1037
+Text = 还原以前的版本(&V)
 [85bbd920-42a0-1069-a2e4-08002b30309d]
[email protected],-22978
+ResText = @shell32.dll,-22978
+Text = 公文包
 [645ff040-5081-101b-9f08-00aa002f954e]
-Text=清空回收站(&B)
-Icon=shell32.dll,-254
-;全部解压缩(&T)...
+Text = 清空回收站(&B)
+Icon = shell32.dll,-254
 [b8cdcb65-b1bf-4b42-9428-1dfdb7ee92af]
[email protected],-37514
+ResText = @shell32.dll,-37514
+Text = 全部解压缩(&T)...
 [bd472f60-27fa-11cf-b8b4-444553540000]
-Text=提取(&E)...
-;复制到文件夹(&F)...
+Text = 提取(&E)...
 [c2fbb630-2971-11d1-a18c-00c04fd75d13]
-Text=@*,-30304
-Icon=imageres.dll,-5304
-;移动到文件夹(&V)...
+ResText = @*,-30304
+Text = 复制到文件夹(&F)...
+Icon = imageres.dll,-5304
 [c2fbb631-2971-11d1-a18c-00c04fd75d13]
-Text=@*,-30305
-Icon=imageres.dll,-5303
-;窗口转换程序
+ResText = @*,-30305
+Text = 移动到文件夹(&V)...
+Icon = imageres.dll,-5303
 [3080f90e-d7ad-11d9-bd98-0000947b0257]
[email protected],-12715
-Icon=imageres.dll
+ResText = @shell32.dll,-12715
+Text = 窗口转换程序
+Icon = imageres.dll
 [5635493f-7d77-4372-a839-8ad89f5b3726]
-Text=卸载(&U)
+Text = 卸载(&U)
 
 ;----------------显卡------------------
 [a929c4ce-fd36-4270-b4f5-34ecac5bd63c]
-Text=用图形处理器运行
-Icon=nvcpl.dll
+ResText = @nv3dappshextr.dll,-103
+Text = 用图形处理器运行
+Icon = nvcpl.dll
 [e97dec16-a50d-49bb-ae24-cf682282e08d]
-Text=更改 OpenGL 渲染 GPU...
-Icon=nvcpl.dll
+ResText = @nv3dappshextr.dll,-109
+Text = 更改 OpenGL 渲染 GPU...
+Icon = nvcpl.dll
 [3d1975af-48c6-4f8e-a182-be0e08fa86a9]
-Text=NVIDIA 控制面板
-Icon=nvcpl.dll
+ResText = @nvsvcr.dll,-4530
+Text = NVIDIA 控制面板
+Icon = nvcpl.dll
 [9b5f5829-a529-4b12-814a-e81bcb8d93fc]
-Text=英特尔® 显卡设置
-Icon=.\igfxTray.exe
+Text = 英特尔® 显卡设置
+en-US-Text = Intel® Graphics
+Icon = .\igfxTray.exe
 [3ab1675a-ccff-11d2-8b20-00a0c93cb1f4]
-Text=Intel 显卡
+Text = Intel® Graphics
 [5e2121ee-0300-11d4-8d3b-444553540000]
-Text=AMD 显卡
-Icon=.\RadeonSettings.exe
+Text = AMD 显卡
+en-US-Text = AMD Graphics
+Icon = .\RadeonSettings.exe
 
 ;----------------压缩------------------
 [5b69a6b4-393b-459c-8ebb-214237a9e7ac]
-Text=Bandizip
-Icon=.\Bandizip.exe
+Text = Bandizip
+Icon = .\Bandizip.exe
 [9179176e-b763-3200-8500-bb1b90b3d5de]
-Text=360zip
-Icon=.\360zip.exe
+Text = 360zip
+Icon = .\360zip.exe
 [b41db860-64e4-11d2-9906-e49fadc173ca]
-Text=WinRAR 64bit
+Text = WinRAR 64bit
 [b41db860-8ee4-11d2-9906-e49fadc173ca]
-Text=WinRAR 32bit
+Text = WinRAR 32bit
 [23170f69-40c1-278a-1000-000100020000]
-Text=7-zip
-Icon=.\7zG.exe
+Text = 7-zip
+Icon = .\7zG.exe
 [b1832224-9f22-4965-a6e8-e6a6e3c4fdf7]
-Text=52好压
-Icon=.\kzip_main.exe
+Text = 52好压
+Icon = .\kzip_main.exe
 [5fed836a-c96c-4d88-a91e-f63f07726585]
-Text=2345好压
-Icon=.\HaoZip.exe
+Text = 2345好压
+Icon = .\HaoZip.exe
 [6adf19e3-77a3-4395-adb4-9fd7d351eb3e]
-Text=快压
+Text = 快压
 [903d855a-d671-4a8e-a592-9168755917db]
-Text=快压
+Text = 快压
 [6adf19e3-77a3-4395-adb4-9fd7d351eb3e]
-Text=快压
+Text = 快压
 [903d855a-d671-4a8e-a592-9168755917db]
-Text=快压
+Text = 快压
 [e0d79304-84be-11ce-9641-444553540000]
-Text=WinZip
-Icon=.\WzPreloader.exe
+Text = WinZip
+Icon = .\WzPreloader.exe
 [acf03765-1658-485f-9615-fe03c372fb8c]
-Text=微压
+Text = 微压
 [dd847e93-86df-4d75-a421-46d29228f6da]
-Text=极光压缩
-Icon=.\plFM.exe
+Text = 极光压缩
+Icon = .\plFM.exe
 [5e3b6ea4-de96-464f-bb86-5587969f4c62]
-Text=万能压缩
+Text = 万能压缩
 [9175e343-1c41-4490-b178-14f36504f07e]
-Text=160压缩
-Icon=.\160zip.exe
+Text = 160压缩
+Icon = .\160zip.exe
 [5e3ca55c-d9f3-4d1c-8b94-ad192b0f7c16]
-Text=速压
-Icon=.\Suzip.exe
+Text = 速压
+Icon = .\Suzip.exe
 [02e77c8d-2798-441e-8e6d-0c2ed9fe206e]
-Text=简压缩
-Icon=.\SimpleZip.exe
+Text = 简压缩
+Icon = .\SimpleZip.exe
 [5c551008-a347-4db3-af48-014076fd2b46]
-Text=极速压缩
-Icon=.\JsZip.exe
+Text = 极速压缩
+Icon = .\JsZip.exe
 [0a4861a5-448a-48b4-812a-cf71a07a674f]
-Text=6789压缩
+Text = 6789压缩
 [7522b611-f22b-4f24-9ce4-3ecbba85c126]
-Text=CoffeeZip
+Text = CoffeeZip
 [aa7f8063-f898-44d0-b147-8a6e9891e32e]
-Text=布丁压缩
-Icon=.\PDZip.exe
+Text = 布丁压缩
+Icon = .\PDZip.exe
 [9b8dff9d-0cb2-4100-8f21-c6dd6ce01141]
-Text=布丁压缩
-Icon=.\PDZip.exe
+Text = 布丁压缩
+Icon = .\PDZip.exe
 [d81a0ed9-6c47-417b-b298-4ebd813cabd0]
-Text=极客压缩
-Icon=.\GeekZip.exe
+Text = 极客压缩
+Icon = .\GeekZip.exe
 [e677c7ad-2b66-4539-aa29-3771a1cfeda9]
-Text=jZip
-Icon=.\jZip.exe
+Text = jZip
+Icon = .\jZip.exe
 [a6630968-27dc-8db8-9bce-e12b3198a9b1]
-Text=WinArchiver
-Icon=.\WinArchiver.exe
+Text = WinArchiver
+Icon = .\WinArchiver.exe
 [1532b32d-3a75-4a4d-9b38-5a6000ea7045]
-Text=FreeArc
-Icon=..\FreeArc.exe
+Text = FreeArc
+Icon = ..\FreeArc.exe
 [ad392e40-428c-459f-961e-9b147782d099]
-Text=UltraISO
-Icon=.\UltraISO.exe
+Text = UltraISO
+Icon = .\UltraISO.exe
 [be86f80b-eb1a-45b4-b4b6-4b12d302b6bc]
-Text=AntZip
+Text = AntZip
 
 ;----------------杀软------------------
 [09a47860-11b0-4da5-afa5-26d86198a780]
-Text=Microsoft Defender
-Icon=.\EppManifest.dll
+Text = Microsoft Defender
+Icon = .\EppManifest.dll
 [18a3e590-f219-4105-9079-93dafa51b9d6]
-Text=使用火绒安全进行杀毒
+ResText = @*,-103
+Text = 使用火绒安全进行杀毒
+en-US-Text = Scan with Huorong Internet Security
 [9f012318-caa5-402c-9bf6-28eb36f61496]
-Text=使用火绒安全粉碎文件
+ResText = @*,-102
+Text = 使用火绒安全粉碎文件
+en-US-Text = Shred with Huorong Internet Security
 [63332668-8ce1-445d-a5ee-25929176714e]
-Text=扫描病毒(电脑管家)
+Text = 扫描病毒(电脑管家)
 [754df2ce-51e8-4895-b53c-6381418b84ae]
-Text=文件粉碎(电脑管家)
+Text = 文件粉碎(电脑管家)
 [cbdecef7-7a29-4cbf-a009-2673d82c7bf9]
-Text=强力卸载(电脑管家)
-Icon=.\QQPCSoftMgr.exe
+Text = 强力卸载(电脑管家)
+Icon = .\QQPCSoftMgr.exe
 [c5617f6a-39bb-436d-91cf-61c1b45dd688]
-Text=深度加速(管家小火箭)
+Text = 深度加速(管家小火箭)
 [b7667919-3765-4815-a66d-98a09be662d6]
-Text=清理垃圾(电脑管家)
+Text = 清理垃圾(电脑管家)
 [086f171d-5ed1-4ed2-b736-cff3ad6a128e]
-Text=使用 360杀毒 扫描
-Icon=.\msdev.exe
+Text = 使用 360杀毒 扫描
+Icon = .\msdev.exe
 [7c0f6d57-e799-4c8a-a319-8e2b4d724cf0]
-Text=360安全卫士
-Icon=..\360Safe.exe
+Text = 360安全卫士
+Icon = ..\360Safe.exe
 [5e19c0ce-c02c-46c2-98c3-a2e12ede0e17]
-Text=360强力卸载 && 桌面助手
-Icon=.\SoftMgr.exe
+Text = 360强力卸载 && 桌面助手
+Icon = .\SoftMgr.exe
 [c4f75db1-b9f4-425a-9f5b-778911bcf176]
-Text=2345扫描病毒 && 强力删除
-Icon=.\2345MPCSafe.exe
+Text = 2345扫描病毒 && 强力删除
+Icon = .\2345MPCSafe.exe
 [6b3ba4a8-ec7e-4714-9ecf-eb33995b3384]
-Text=使用2345软件管家卸载软件
-Icon=..\..\2345SoftMgr.exe
+Text = 使用2345软件管家卸载软件
+Icon = ..\..\2345SoftMgr.exe
 [ddea5705-1bb0-4c03-ac1e-8ff9716a0d51]
-Text=金山毒霸(64位)
-Icon=.\kismain.exe
+Text = 金山毒霸(64位)
+Icon = .\kismain.exe
 [d21d88e8-4123-48ba-b0b1-3fdbe4ae5fa4]
-Text=金山毒霸(32位)
-Icon=.\kismain.exe
+Text = 金山毒霸(32位)
+Icon = .\kismain.exe
 [367f6ae2-6809-4bed-b09b-228893fb33dd]
-Text=金山毒霸
-Icon=.\kismain.exe
+Text = 金山毒霸
+Icon = .\kismain.exe
 [758c684b-4d10-4bc1-90da-6bebf0b4e0b4]
-Text=使用联想电脑管家进行扫描
+Text = 使用联想电脑管家进行扫描
+[c97c3e31-2af4-4651-9e93-ede827605a23]
+Text = 强力卸载此软件(联想电脑管家)
 [c49499ac-dc25-478b-b903-e005012b3dd1]
-Text=使用智量扫描
-Icon=.\WiseVector.exe
+Text = 使用智量扫描
+Icon = .\WiseVector.exe
 [cca9efd3-29ed-430a-ba6d-e6bbff0a60c2]
-Text=McAfee
-Icon=.\McInstru.exe
+Text = McAfee
+Icon = .\McInstru.exe
 [472083b0-c522-11cf-8763-00608cc02f24]
-Text=Avast
-Icon=..\AvastUI.exe
+Text = Avast
+Icon = ..\AvastUI.exe
 [45ac2688-0253-4ed8-97de-b5370fa7d48a]
-Text=使用 Avira 扫描所选文件
-Icon=..\Launcher\Avira.Systray.exe
+Text = 使用 Avira 扫描所选文件
+Icon = ..\Launcher\Avira.Systray.exe
 [9b9f6e01-a5cf-4269-b245-cff66a7daebd]
-Text=卡巴斯基
+Text = 卡巴斯基
 [57ce581a-0cb6-4266-9ca0-19364c90a0b3]
-Text=Malwarebytes
+Text = Malwarebytes
 [f7caa2a1-67a2-44bb-b20f-202fd8eb1dab]
-Text=Norton 360
-Icon=.\uiStub.exe
+Text = Norton 360
+Icon = .\uiStub.exe
 [fad61b3d-699d-49b2-be16-7f82cb4c59ca]
-Text=Norton文件智能分析
-Icon=.\uiStub.exe
+Text = Norton文件智能分析
+Icon = .\uiStub.exe
 [e8215bea-3290-4c73-964b-75502b9b41b2]
-Text=Norton File Shredder
+Text = Norton File Shredder
 [1c7593cb-c1cc-4ba7-be52-8eea47f9cb1d]
-Text=使用瑞星杀毒
+Text = 使用瑞星杀毒
 [0bb81440-5f42-4480-a5f7-770a6f439fc8]
-Text=IObit Malware Fighter
-Icon=*,3
+Text = IObit Malware Fighter
+Icon = *,3
 [b089fe88-fb52-11d3-bdf1-0050da34150d]
-Text=ESET Endpoint Antivirus
+Text = ESET Endpoint Antivirus
 
 ;----------------传输------------------
 [53d2405c-48ab-4c8a-8f59-ce0610f13bbc]
-Text=通过QQ发送到
+Text = 通过QQ发送到
 [cb3d0f55-bc2c-4c1a-85ed-23ed75b5106b]
-Text=OneDrive
-Icon=..\..\OneDrive.exe
+Text = OneDrive
+Icon = ..\..\OneDrive.exe
 [6d85624f-305a-491d-8848-c1927aa0d790]
-Text=上传到百度网盘
-Icon=.\BaiduNetdisk.exe
+Text = 上传到百度网盘
+Icon = .\BaiduNetdisk.exe
 [2008caf4-a5c1-4037-99a8-699e4d01456d]
-Text=天翼云盘
-Icon=.\eCloud.exe
+Text = 天翼云盘
+Icon = .\eCloud.exe
 [1d39a523-4df5-4562-8fff-08c740632f4f]
-Text=360云盘
-Icon=.\360WangPan.exe
+Text = 360云盘
+Icon = .\360WangPan.exe
 [eee949eb-c9ed-4967-98b0-ed4e543befa5]
-Text=115网盘
-Icon=..\115chrome.exe
+Text = 115网盘
+Icon = ..\115chrome.exe
 [171b6b53-17b1-40b7-afb2-a415b2b40401]
-Text=上传到腾讯微云
-Icon=..\..\..\..\..\..\..\WeiyunApp.exe
+Text = 上传到腾讯微云
+Icon = ..\..\..\..\..\..\..\WeiyunApp.exe
 [5d652b62-b702-496a-92bc-92c308251fea]
-Text=坚果云
-Icon=*,3
+Text = 坚果云
+Icon = *,3
 [67f4d210-bfc2-4add-9a2a-c9b9e1f42c4f]
-Text=上传到 “WPS云文档”
+Text = 上传到 “WPS云文档”
+Icon = ..\..\ksolaunch.exe
 [aa147ffb-0b1f-4bb1-9b1e-8d062b35c145]
-Text=自动同步文件夹到 “WPS云文档”
+Text = 自动同步文件夹到 “WPS云文档”
 [970a26b5-2b84-4b60-8067-1440c229672d]
-Text=钉盘
-Icon=..\DingtalkLauncher.exe
+Text = 钉盘
+Icon = ..\DingtalkLauncher.exe
 [0229e5e7-09e9-45cf-9228-0228ec7d5f17]
-Text=MEGA
-Icon=.\MEGAsync.exe
+Text = MEGA
+Icon = .\MEGAsync.exe
 [ecd97de5-3c8f-4acb-aeee-ccab78f7711c]
-Text=Dropbox
+Text = Dropbox
 [30351349-7b7d-4fcc-81b4-1e394ca267eb]
-Text=TortoiseSVN
-Icon=.\TortoiseIDiff.exe
+Text = TortoiseSVN
+Icon = .\TortoiseIDiff.exe
 [10a0fdd2-b0c0-4cd4-a7ae-e594ce3b91c8]
-Text=TortoiseGit
-Icon=.\TortoiseGitProc.exe
+Text = TortoiseGit
+Icon = .\TortoiseGitProc.exe
 [2a535b11-6cfc-4e85-a75f-0e397b1584cf]
-Text=通过网易邮箱大师发送
-Icon=..\mailmaster.exe
+Text = 通过网易邮箱大师发送
+Icon = ..\mailmaster.exe
 [9557f42f-bd61-4e26-9752-33a8a20fc9f9]
-Text=分享文件(华为电脑管家)
-Icon=.\PCManager.exe
+Text = 分享文件(华为电脑管家)
+Icon = .\PCManager.exe
 [c3db4192-4c22-428f-8c12-cf9cfabbdd17]
-Text=通过AirDroid发送到我的设备
+Text = 通过AirDroid发送到我的设备
 [0b488c12-e68e-44d7-9259-fb8e5df8bb27]
-Text=内网通
-Icon=.\ShiYeLine.exe
+Text = 内网通
+Icon = .\ShiYeLine.exe
 [256ef94c-697d-4986-b99b-9d3b15d79b49]
-Text=Infinit
+Text = Infinit
 [a97a01b0-3b66-4336-bc9b-168e64bfb296]
-Text=广讯通发送文件
-Icon=.\GXT.exe
+Text = 广讯通发送文件
+Icon = .\GXT.exe
 [41b3b91f-d6b3-3430-bb86-a143f85353ca]
-Text=Huawei Share
+Text = Huawei Share
 [1bca9901-05c3-4d01-8ad4-78da2eac9b3f]
-Text=使用小米互传发送
-Icon=.\FixServiceTool.exe
+Text = 使用小米互传发送
+Icon = .\FixServiceTool.exe
 
 ;----------------PDF------------------
 [9c5397bb-07be-4e38-98ba-395f94045091]
-Text=福昕PDF编辑器
-Icon=..\FoxitPhantom.exe
+Text = 福昕PDF编辑器
+Icon = ..\FoxitPhantom.exe
 [27be7b9d-935f-325c-9a05-63557d69f4f9]
-Text=万兴PDF专家
-Icon=..\PDFExpert.exe
+Text = 万兴PDF专家
+Icon = ..\PDFExpert.exe
 [a6595cd1-bf77-430a-a452-18696685f7c7]
-Text=Adobe Acrobat
-Icon=..\Acrobat\Acrobat.exe
+Text = Adobe Acrobat
+Icon = ..\Acrobat\Acrobat.exe
 [d25b2cab-8a9a-4517-a9b2-cb5f68a5a802]
-Text=转换为Adobe PDF(&B)
+Text = 转换为Adobe PDF(&B)
 [1ecda7bf-4dfa-41d8-9380-1a27b26cfc41]
-Text=使用WPS PDF编辑
-Icon=..\..\wpspdf.exe
+Text = 使用WPS PDF编辑
+Icon = ..\..\wpspdf.exe
 [e3ed4700-22d4-41b6-8144-e3f5f1ac5153]
-Text=使用WPS PDF编辑
-Icon=..\..\wpspdf.exe
+Text = 使用WPS PDF编辑
+Icon = ..\..\wpspdf.exe
 [af1d7d2f-6ae8-4baa-abfa-738201f4871c]
-Text=WPS Office PDF
-Icon=.\wpspdf.exe
+Text = WPS Office PDF
+Icon = .\wpspdf.exe
 [b4e15cd0-f916-4c8e-830a-15e3e9d01a1b]
-Text=迅读PDF大师 合并、拆分、转换
-Icon=.\MasterPDF.exe
+Text = 迅读PDF大师 合并、拆分、转换
+Icon = .\MasterPDF.exe
 [19a73c67-f0b8-4a28-8c33-9d4eddd6fcbc]
-Text=云上PDF
-Icon=.\iPDF.exe
+Text = 云上PDF
+Icon = .\iPDF.exe
 [29424e92-60a1-40c0-bf79-1b8472dde706]
-Text=使用PDF猫编辑器打开
-Icon=.\M_pdfEdit.exe
+Text = 使用PDF猫编辑器打开
+Icon = .\M_pdfEdit.exe
 [29424e91-60a1-40c0-bf79-1b8472dde606]
-Text=使用转转大师PDF编辑器打开
-Icon=.\ZPDFEdit.exe
+Text = 使用转转大师PDF编辑器打开
+Icon = .\ZPDFEdit.exe
 [098a124a-aa1c-38c8-a65e-d1199a14516a]
-Text=Convert to...(万兴PDF专家)
+Text = Convert to...(万兴PDF专家)
 [fb074836-8286-4089-84dc-f504e9ef621c]
-Text=ABBYY FineReader
-Icon=..\FineUpdate.exe
+Text = ABBYY FineReader
+Icon = ..\FineUpdate.exe
 [d16adfe3-66c5-4df5-9978-87de0c687e85]
-Text=嗨格式PDF转换器
-Icon=.\HiPdfConvert.exe
+Text = 嗨格式PDF转换器
+Icon = .\HiPdfConvert.exe
 [2acd35ab-f74a-4c20-aa9b-2de80081626d]
-Text=PDF-XChange Editor
-Icon=..\PDF Editor\PDFXEdit.exe
+Text = PDF-XChange Editor
+Icon = ..\PDF Editor\PDFXEdit.exe
+[6c405cec-8624-4fef-b3ba-9d4e5a8f58b5]
+Text = 迅捷PDF转换器
+Icon = .\pdfconverter.exe
 
 ;--------------影音图像----------------
 [8a734961-c4aa-4741-ac1e-791acebf5b39]
-Text=联机购买音乐
+Text = 联机购买音乐
 [f1b9284f-e9dc-4e68-9d7e-42362a59f0fd]
-Text=添加到“Windows Media Player”列表(&W)
+Text = 添加到“Windows Media Player”列表(&W)
 [ce3fb1d1-02ae-4a5f-a6e9-d9f1b4073e6c]
-Text=使用“Windows Media Player”播放(&P)
+Text = 使用“Windows Media Player”播放(&P)
 [7d4734e6-047e-41e2-aeaa-e763b4739dc4]
-Text=使用 Media Player 播放(&P)
+Text = 使用 Media Player 播放(&P)
 [e598560b-28d5-46aa-a14a-8a3bea34b576]
-Text=幻灯片放映
+Text = 幻灯片放映
 [9b6d38f3-8ef4-48a5-ad30-ffffffffffff]
-Text=Honeyview
-Icon=.\Honeyview.exe
+Text = Honeyview
+Icon = .\Honeyview.exe
 [c2396f1e-4ba2-4b7d-857a-f764761c012b]
-Text=ACD看图
-Icon=.\AcdKantu.exe
+Text = ACD看图
+Icon = .\AcdKantu.exe
 [83a97a48-f5d7-4d12-8ba3-5263a016d936]
-Text=使用光影4.0编辑
+Text = 使用光影4.0编辑
 [8f556da3-987d-47b0-aa88-eb8d52fe1b9a]
-Text=迅雷播放组件
-Icon=..\Program\XMP\XMP.exe
+Text = 迅雷播放组件
+Icon = ..\Program\XMP\XMP.exe
 [5cd76c57-6893-478a-b776-47e7c82504be]
-Text=爱奇艺万能联播
-Icon=.\GeePlayer.exe
+Text = 爱奇艺万能联播
+Icon = .\GeePlayer.exe
 [a3888921-cfd3-4a6b-89bf-08e6b95716e8]
-Text=图片工厂(&F)
+Text = 图片工厂(&F)
 [51b4d7e5-7568-4234-b4bb-47fb3c016a69]
-Text=调整图片大小(PowerToys)
+ResText = @*,-101
+Text = 调整图片大小(PowerToys)
 [5c6a637c-9780-4d0f-a379-4732edcce7c3]
-Text=网易云音乐
+Text = 网易云音乐
 [1f77b17b-f531-44db-aca4-76abb5010a28]
-Text=AIMP
-Icon=..\AIMP.exe
+Text = AIMP
+Icon = ..\AIMP.exe
 [8e7861bb-3a13-40a1-af25-633458757201]
-Text=QQ影音
+Text = QQ影音
 [7a1884a3-f647-49be-b93c-8ffaf4a1f1bf]
-Text=使用PP视频播放
+Text = 使用PP视频播放
 [8f556da3-987d-47b0-aa88-eb8d52fe1b99]
-Text=迅雷影音
-Icon=..\..\Program\APlayer.exe
+Text = 迅雷影音
+Icon = ..\..\Program\APlayer.exe
 [4d2fba8d-621b-4447-af6d-5794f479c4a5]
-Text=爱奇艺看图
-Icon=..\QyImg.exe
+Text = 爱奇艺看图
+Icon = ..\QyImg.exe
 
 ;----------------美化------------------
 [cf444751-60fc-48b8-ac0f-363063eb2a9e]
-Text=开启桌面整理(电脑管家)
+Text = 开启桌面整理(电脑管家)
 [b3a2f1a4-10a2-410c-9c19-622b621c61d0]
-Text=换壁纸(小鸟壁纸)
+Text = 换壁纸(小鸟壁纸)
 [3b7162fb-4389-40c8-83a5-da10d491ec66]
-Text=映射此文件夹到桌面(小智桌面)
-Icon=.\XZDesktop.exe
+Text = 映射此文件夹到桌面(小智桌面)
+Icon = .\XZDesktop.exe
 [96babf4f-7c38-4885-b407-3800f461669b]
-Text=打开火萤视频桌面
-Icon=..\..\HYVideoDesktop.exe
+Text = 打开火萤视频桌面
+Icon = ..\..\HYVideoDesktop.exe
 [c3c76829-1d8b-49a2-afb4-196c443f1b0b]
-Text=人工桌面
-Icon=.\N0vaDesktop.exe
+Text = 人工桌面
+Icon = .\N0vaDesktop.exe
 [a2a9545d-a0c2-42b4-9708-a0b2badd77c9]
-Text=附到「开始」菜单(&U)(StartIsBack)
-Icon=.\StartIsBackCfg.exe
+ResText = @*,-5381
+Text = 附到「开始」菜单(&U)(StartIsBack)
+Icon = .\StartIsBackCfg.exe
 [6a451c0a-9597-4915-bcce-6e859bc996b2]
-Text=Pin to Start (Start10)
-Icon=.\Start10.exe
+Text = Pin to Start (Start10)
+Icon = .\Start10.exe
 [af8fa9c9-9907-463e-bdc3-4cc1200d6310]
-Text=Start Menu 8
-Icon=*,2
+Text = Start Menu 8
+Icon = *,2
 [07451604-fbe4-4475-9dd6-261b7b619417]
-Text=电脑管家经典开始菜单
-Icon=.\QMStart.exe
+Text = 电脑管家经典开始菜单
+Icon = .\QMStart.exe
 [2d5ad9eb-31bc-48f7-a438-28f363632c73]
-Text=开启布丁桌面
-Icon=.\PDLanuncher.exe
+Text = 开启布丁桌面
+Icon = .\PDLanuncher.exe
 [b5e436bc-642a-4bf6-b725-26038af26e89]
-Text=开启猎豹轻桌面
-Icon=.\kdesk.exe
+Text = 开启猎豹轻桌面
+Icon = .\kdesk.exe
 [5f8d079b-8ce6-4f58-bf10-55c1b68d88f3]
-Text=选择颜色设置
-Icon=.\ChromaTune.exe
+Text = 选择颜色设置
+Icon = .\ChromaTune.exe
 [6c125022-639d-43cc-9f3d-647e6cc69ef1]
-Text=右键菜单背景图片插件(第三方)
+Text = 右键菜单背景图片插件(第三方)
 
 ;--------------文件处理----------------
 [b298d29a-a6ed-11de-ba8c-a68e55d89593]
-Text=Notepad++
+Text = Notepad++
 [36d94110-787c-4828-9c1b-0dafebc36069]
-Text=EditPlus
-Icon=.\EditPlus.exe
+Text = EditPlus
+Icon = .\EditPlus.exe
 [b5eedee0-c06e-11cf-8c56-444553540000]
-Text=UltraEdit
-Icon=.\uedit64.exe
+Text = UltraEdit
+Icon = .\uedit64.exe
 [51eee242-ad87-11d3-9c1e-0090278bbd99]
-Text=Vim
-Icon=..\vim.exe
+Text = Vim
+Icon = ..\vim.exe
 [ed90173a-3b4c-4e7e-b9cf-79714425d4b5]
-Text=PSPad Editor
-Icon=.\PSPad.exe
+Text = PSPad Editor
+Icon = .\PSPad.exe
 [a3777921-cfd3-4a6b-89bf-08e6b95716e8]
-Text=格式工厂(&F)
-Icon=.\FormatFactory.exe
+Text = 格式工厂(&F)
+Icon = .\FormatFactory.exe
 [af9b72b5-f4e4-44b0-a3d9-b55b748efe90]
-Text=File Converter
-Icon=.\FileConverter.exe
+Text = File Converter
+Icon = .\FileConverter.exe
 [dde4beeb-dde6-48fd-8eb5-035c09923f83]
-Text=Unlocker
-Icon=.\Unlocker.exe
+Text = Unlocker
+Icon = .\Unlocker.exe
 [0bb27cda-7029-4c0e-9c56-d922b229f0eb]
-Text=解除文件锁定(LockHunter)
-Icon=.\LockHunter.exe
+Text = 解除文件锁定(LockHunter)
+Icon = .\LockHunter.exe
 [410bf280-86ef-4e0f-8279-ec5848546ad3]
-Text=IObit Unlocker
-Icon=.\IObitUnlocker.exe
+Text = IObit Unlocker
+Icon = .\IObitUnlocker.exe
 [836ab26c-2de4-41d3-ac24-4c6c2699b960]
-Text=强力卸载(IObit Uninstaller)
+Text = 强力卸载(IObit Uninstaller)
 [2803063f-4b8d-4dc6-8874-d1802487fe2d]
-Text=Advanced SystemCare
-Icon=*,3
+Text = Advanced SystemCare
+Icon = *,3
 [fe8e6ad6-dabe-45e1-88c2-48dc4578924c]
-Text=Uninstall Tool
+Text = Uninstall Tool
 [2c5515dc-2a7e-4bfd-b813-cacc2b685eb7]
-Text=Revo Uninstaller Pro
-Icon=*,1
+Text = Revo Uninstaller Pro
+Icon = *,1
 [b3026062-4d7e-3601-9a6b-622ceac3fc5c]
-Text=File Governor
-Icon=.\FileGovernor.exe
+Text = File Governor
+Icon = .\FileGovernor.exe
 [1650dc30-2343-498a-b49a-37b90918f611]
-Text=CleanMyPC
+Text = CleanMyPC
 [6cb83a5a-aa68-4895-9f54-175e789ae149]
-Text=Balabolka
-Icon=.\balabolka.exe
+Text = Balabolka
+Icon = .\balabolka.exe
 [0440049f-d1dc-4e46-b27b-98393d79486b]
-Text=PowerRename(&W)
+ResText = @*,-101
+Text = PowerRename(&W)
 [2e7a2c6c-b938-40a4-ba1c-c7ec982dc202]
-Text=发布DWF
-Icon=.\AcLauncher.exe
+Text = 发布DWF
+Icon = .\AcLauncher.exe
 [57fa2d12-d22d-490a-805a-5cb48e84f12a]
-Text=Beyond Compare
-Icon=.\BCompare.exe
+Text = Beyond Compare
+Icon = .\BCompare.exe
 [c3b42c03-c1b7-4c1a-b384-bbae19646333]
-Text=UltraCompare
-Icon=.\uc.exe
+Text = UltraCompare
+Icon = .\uc.exe
 [1ed0f018-76b9-4db9-9c06-ca0f3088f04f]
-Text=FileLocator Pro
+Text = FileLocator Pro
 [00000000-0000-0000-0000-000000000012]
-Text=显示隐藏文件+扩展名
+Text = 显示隐藏文件+扩展名
 [c1b2c38f-3dca-4e3d-bc34-d5b87b636543]
-Text=FileMenu Tools
+Text = FileMenu Tools
 [189f1e63-33a7-404b-b2f6-8c76a452cc54]
-Text=Smart Defrag
-Icon=*,2
+Text = Smart Defrag
+Icon = *,2
 [4380c993-0c43-4e02-9a7a-0d40b6ea7590]
-Text=Defraggler
-Icon=.\Defraggler.exe
+Text = Defraggler
+Icon = .\Defraggler.exe
 [271dc252-6fe1-4d59-9053-e4cf50ab99de]
-Text=VMware
-Icon=.\vmware.exe
+Text = VMware
+Icon = .\vmware.exe
 [e4d28edc-8c0b-43ee-9e7d-c8a8682334dc]
-Text=VMware 64bit
-Icon=.\vmware.exe
+Text = VMware 64bit
+Icon = .\vmware.exe
 [c52b9871-e5e9-41fd-b84d-c5acadbec7ae]
-Text=Locale Emulator
-Icon=.\LEGUI.exe
+Text = Locale Emulator
+Icon = .\LEGUI.exe
 [0a479751-02bc-11d3-a855-0004ac2568aa]
-Text=NTFS文件连接扩展配置工具
-Icon=.\LSEConfig.exe
+Text = NTFS文件连接扩展配置工具
+Icon = .\LSEConfig.exe
 [fdf253ac-1724-4853-be34-c2dbc18fb5ca]
-Text=Copywhiz
-Icon=.\Copywhiz.exe
+Text = Copywhiz
+Icon = .\Copywhiz.exe
 [6c467336-8281-4e60-8204-430ced96822d]
-Text=共享文件夹同步
+Text = 共享文件夹同步
 [6fa85dad-ac32-4d74-9cba-6a1c038f9a56]
-Text=文档加密/解密
+Text = 文档加密/解密
 [ef479680-ea35-4ea9-b093-7114f3e3e0da]
-Text=Directory Lister
-Icon=.\DirListerPro.exe
+Text = Directory Lister
+Icon = .\DirListerPro.exe
 [8e57c449-7891-49bb-80e5-ddac375f8ac8]
-Text=使用微表格打开
-Icon=.\microexcel.exe
+Text = 使用微表格打开
+Icon = .\microexcel.exe
 [0d8b46ea-7d35-4921-b88c-7e2b1e2d80f0]
-Text=WPS Office
-Icon=..\..\wpsoffice.exe
+Text = WPS Office
+Icon = ..\..\wpsoffice.exe
 
 ;-------------UWP新模块----------------
 [776dbc8d-7347-478c-8d71-791e12ef49d8]
-UwpName=Microsoft.SkypeApp
-Text=@*,-101
-Icon=.\Skype.exe
+UwpName = Microsoft.SkypeApp
+ResText = @*,-101
+Text = 使用 Skype 共享
+Icon = .\Skype.exe
 [9f156763-7844-4dc4-b2b1-901f640f5155]
-UwpName=Microsoft.WindowsTerminal
-Text=Open in Windows Terminal
-Icon=.\WindowsTerminal.exe
+UwpName = Microsoft.WindowsTerminal
+Text = Open in Windows Terminal
+Icon = .\WindowsTerminal.exe

+ 28 - 16
ContextMenuManager/Properties/Resources/Texts/ThirdRulesDic.xml

@@ -4,44 +4,56 @@
 Item的子元素Rule为相关注册表内容,RegPath省略则默认为Group主路径,以\开头则为Group主路径的子项路径;
 ValueName为相关键名,On为启用键值,Off为禁用键值;不设置On或Off属性时,其值为null,对应注册表键值不存在;
 每个Item可能受多个注册表Rule影响,按照顺序进行键值判定;判定规则:当有多条规则时,前面的规则注册表键值匹配On则为On,匹配Off则为Off,并终止判断,都不匹配时继续往下判断,若所有规则都不匹配则为On
-ValueKind为键值类型,默认键值类型ValueKind为REG_DWORD,为默认值时可省略,目前仅支持REG_SZ、REG_DWORD、REG_EXPAND_SZ的键值类型-->
+ValueKind为键值类型,默认键值类型ValueKind为REG_DWORD,为默认值时可省略,目前仅支持REG_SZ、REG_DWORD、REG_EXPAND_SZ、REG_BINARY的键值类型-->
 <Data>
   <Group Text='System'>
     <Item Text='系统 右键菜单' RestartExplorer=''>
       <Rule RegPath='HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer' ValueName='NoViewContextMenu' Off='1'/>
-      <Rule RegPath='HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer' ValueName='NoViewContextMenu' Off='1'/>
+      <Rule RegPath='HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer' ValueName='NoViewContextMenu' Off='1'/>
     </Item>
     <Item Text='系统 使用经典紧凑右键菜单' RestartExplorer=''>
       <OSVersion Compare='>='>10.0.14393</OSVersion>
       <OSVersion Compare='&lt;'>10.0.17763</OSVersion>
       <Rule RegPath='HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\FlightedFeatures' ValueName='ImmersiveContextMenu' On='0'/>
     </Item>
+    <Item Text='Shell类型菜单同时操作文件对象数量限制' Tip='系统默认值为15,超过15为无限制' IsNumberItem=''>
+      <Rule RegPath='HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer' ValueName='MultipleInvokePromptMinimum' Max='32767' Min='1' Default='15'/>
+    </Item>
+    <Item Text='创建快捷方式时去除 "快捷方式" 后缀' RestartExplorer=''>
+      <Rule RegPath='HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\NamingTemplates' ValueName='ShortcutNameTemplate' On='%s' ValueKind='REG_SZ'/>
+      <Rule RegPath='HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\NamingTemplates' ValueName='ShortcutNameTemplate' On='%s' ValueKind='REG_SZ'/>
+      <Rule RegPath='HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer' ValueName='Link' On='00 00 00 00' ValueKind='REG_BINARY'/>
+    </Item>
+    <Item Text='文件(夹) 复制粘贴去除 "副本" 后缀'>
+      <Rule RegPath='HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\NamingTemplates' ValueName='CopyNameTemplate' On='%s' ValueKind='REG_SZ'/>
+      <Rule RegPath='HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\NamingTemplates' ValueName='CopyNameTemplate' On='%s' ValueKind='REG_SZ'/>
+    </Item>
     <Item Text='文件(夹) 加密 解密' Tip='本设备加密后的文件需解密后才能在其他设备中打开'>
       <Rule RegPath='HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced' ValueName='EncryptionContextMenu' On='1'/>
-      <Rule RegPath='HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' ValueName='EncryptionContextMenu' On='1'/>
+      <Rule RegPath='HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced' ValueName='EncryptionContextMenu' On='1'/>
     </Item>
     <Item Text='任务栏 右键菜单' RestartExplorer=''>
       <Rule RegPath='HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer' ValueName='NoTrayContextMenu' Off='1'/>
-      <Rule RegPath='HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer' ValueName='NoTrayContextMenu' Off='1'/>
+      <Rule RegPath='HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer' ValueName='NoTrayContextMenu' Off='1'/>
     </Item>
     <Item Text='任务栏 任务栏设置 锁定任务栏' RestartExplorer=''>
       <Rule RegPath='HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer' ValueName='TaskbarLockAll' Off='1'/>
-      <Rule RegPath='HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer' ValueName='TaskbarLockAll' Off='1'/>
+      <Rule RegPath='HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer' ValueName='TaskbarLockAll' Off='1'/>
     </Item>
     <Item Text='任务栏 工具栏' RestartExplorer='' Tip='禁用后已启用工具栏将被禁用, 请谨慎操作'>
       <Rule RegPath='HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer' ValueName='NoToolbarsOnTaskbar' Off='1'/>
       <Rule RegPath='HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer' ValueName='NoCloseDragDropBands' Off='1'/>
-      <Rule RegPath='HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer' ValueName='NoToolbarsOnTaskbar' Off='1'/>
-      <Rule RegPath='HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer' ValueName='NoCloseDragDropBands' Off='1'/>
+      <Rule RegPath='HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer' ValueName='NoToolbarsOnTaskbar' Off='1'/>
+      <Rule RegPath='HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer' ValueName='NoCloseDragDropBands' Off='1'/>
     </Item>
     <Item Text='任务栏 固定到任务栏' RestartExplorer='' Tip='禁用时已固定图标会被隐藏,重新启用会重现&#x000A;文件右键菜单“固定到任务栏”会同时消失&#x000A;且无法拖拽文件到任务栏进行固定'>
       <Rule RegPath='HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Explorer' ValueName='TaskbarNoPinnedList' Off='1'/>
-      <Rule RegPath='HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\Explorer' ValueName='TaskbarNoPinnedList' Off='1'/>
+      <Rule RegPath='HKEY_CURRENT_USER\SOFTWARE\Policies\Microsoft\Windows\Explorer' ValueName='TaskbarNoPinnedList' Off='1'/>
     </Item>
     <Item Text='任务栏 人脉' RestartExplorer=''>
       <OSVersion Compare='>='>10.0.16199</OSVersion>
       <Rule RegPath='HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\People' ValueName='PeopleBand' Off='0'/>
-      <Rule RegPath='HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\Explorer' ValueName='HidePeopleBar' Off='1'/>
+      <Rule RegPath='HKEY_CURRENT_USER\SOFTWARE\Policies\Microsoft\Windows\Explorer' ValueName='HidePeopleBar' Off='1'/>
     </Item>
     <Item Text='任务栏 Windows lnk 工作区' Tip='禁用此项将同时禁用 Win+W 快捷键'>
       <OSVersion Compare='>='>10.0</OSVersion>
@@ -55,24 +67,24 @@ ValueKind为键值类型,默认键值类型ValueKind为REG_DWORD,为默认
     <Item Text='开始 程序右键菜单 卸载' RestartExplorer=''>
       <OSVersion Compare='>='>6.2</OSVersion>
       <Rule RegPath='HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Explorer' ValueName='NoUninstallFromStart' Off='1'/>
-      <Rule RegPath='HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\Explorer' ValueName='NoUninstallFromStart' Off='1'/>
+      <Rule RegPath='HKEY_CURRENT_USER\SOFTWARE\Policies\Microsoft\Windows\Explorer' ValueName='NoUninstallFromStart' Off='1'/>
     </Item>
     <Item Text='开始 程序右键菜单 以其他用户身份运行' RestartExplorer=''>
       <OSVersion Compare='>='>10.0</OSVersion>
       <Rule RegPath='HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Explorer' ValueName='ShowRunAsDifferentUserInStart' On='1'/>
-      <Rule RegPath='HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\Explorer' ValueName='ShowRunAsDifferentUserInStart' On='1'/>
+      <Rule RegPath='HKEY_CURRENT_USER\SOFTWARE\Policies\Microsoft\Windows\Explorer' ValueName='ShowRunAsDifferentUserInStart' On='1'/>
     </Item>
     <Item Text='开始 磁贴调整大小、布局、固定、卸载' RestartExplorer=''>
       <OSVersion Compare='>='>6.2</OSVersion>
       <Rule RegPath='HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer' ValueName='NoChangeStartMenu' Off='1'/>
-      <Rule RegPath='HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer' ValueName='NoChangeStartMenu' Off='1'/>
+      <Rule RegPath='HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer' ValueName='NoChangeStartMenu' Off='1'/>
     </Item>
     <Item Text='开始 任务栏 程序右键显示最近打开文件跳转列表'>
       <OSVersion Compare='>='>10.0</OSVersion>
       <Rule RegPath='HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced' ValueName='Start_TrackDocs' Off='0'/>
-      <Rule RegPath='HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' ValueName='Start_TrackDocs' Off='0'/>
+      <Rule RegPath='HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced' ValueName='Start_TrackDocs' Off='0'/>
     </Item>
-    <Item Text='开始 任务栏 程序右键最近打开文件跳转列表数量限制' IsNumberItem=''>
+    <Item Text='开始 任务栏 程序右键最近打开文件跳转列表数量限制' Tip='系统默认值为13' IsNumberItem=''>
       <OSVersion Compare='>='>10.0</OSVersion>
       <Rule RegPath='HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced' ValueName='JumpListItems_Maximum' Max='60' Min='0' Default='13'/>
     </Item>
@@ -95,7 +107,7 @@ ValueKind为键值类型,默认键值类型ValueKind为REG_DWORD,为默认
     <Item Text='预览压缩文件'>
       <Rule ValueName='shell_Preview' On='1' Off='0'/>
     </Item>
-    <Item Text='预览文件数量限制' IsNumberItem=''>
+    <Item Text='预览文件数量限制' Tip='默认值为6' IsNumberItem=''>
       <Rule ValueName='shell_PreviewSize' Max='20' Min='1' Default='6'/>
     </Item>
     <Item Text='新建文件夹'>
@@ -229,7 +241,7 @@ ValueKind为键值类型,默认键值类型ValueKind为REG_DWORD,为默认
     </Item>
   </Group>
 
-  <Group Text='NVIDIA' Guid='3d1975af-48c6-4f8e-a182-be0e08fa86a9' RegPath='HKEY_CURRENT_USER\Software\NVIDIA Corporation'>
+  <Group Text='NVIDIA' Guid='3d1975af-48c6-4f8e-a182-be0e08fa86a9' RegPath='HKEY_CURRENT_USER\SOFTWARE\NVIDIA Corporation'>
     <Item Text='显示桌面上下文菜单'>
       <Rule RegPath='\Global\NvCplApi\Policies' ValueName='ContextUIPolicy' On='1' Off='0'/>
     </Item>

+ 10 - 10
ContextMenuManager/Properties/Resources/Texts/UwpModeItemsDic.xml

@@ -1,18 +1,18 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- 微软在Win10右键菜单中新增的UWP模块, 非Shell、ShellEx类型,
-但是可通过GUID锁定屏蔽来禁用右键菜单项目,
+但是可通过GUID锁定屏蔽来禁用相关右键菜单项目,
 GUID查找位置:HKEY_CLASSES_ROOT\PackagedCom\Package\[包名]\Class\[GUID],
 Scene的各子节点为菜单项目出现位置, Item必须有Guid属性,
 UwpName、Text、Icon、Tip等属性写在GuidInfosDic.ini里面-->
 
 <Scene>
-	<File>
-		<Item Guid='776dbc8d-7347-478c-8d71-791e12ef49d8'/>
-	</File>
-	<Directory>
-		<Item Guid='9f156763-7844-4dc4-b2b1-901f640f5155'/>
-	</Directory>
-	<Background>
-		<Item Guid='9f156763-7844-4dc4-b2b1-901f640f5155'/>
-	</Background>
+  <File>
+    <Item Guid='776dbc8d-7347-478c-8d71-791e12ef49d8'/>
+  </File>
+  <Directory>
+    <Item Guid='9f156763-7844-4dc4-b2b1-901f640f5155'/>
+  </Directory>
+  <Background>
+    <Item Guid='9f156763-7844-4dc4-b2b1-901f640f5155'/>
+  </Background>
 </Scene>

+ 154 - 43
ContextMenuManager/Updater.cs

@@ -1,86 +1,197 @@
-using BluePointLilac.Methods;
+using BluePointLilac.Controls;
+using BluePointLilac.Methods;
+using ContextMenuManager.Controls;
 using System;
+using System.Collections.Generic;
+using System.Globalization;
 using System.IO;
+using System.Linq;
 using System.Net;
+using System.Runtime.Serialization.Json;
 using System.Text;
 using System.Windows.Forms;
+using System.Xml;
 
 namespace ContextMenuManager
 {
     sealed class Updater
     {
-        const string UpdateUrl = "https://gitee.com/BluePointLilac/ContextMenuManager/raw/master/Update.ini";
-        const string GuidInfosDicUrl = "https://gitee.com/BluePointLilac/ContextMenuManager/raw/master/ContextMenuManager/Properties/Resources/Texts/GuidInfosDic.ini";
-        const string ThirdRulesDicUrl = "https://gitee.com/BluePointLilac/ContextMenuManager/raw/master/ContextMenuManager/Properties/Resources/Texts/ThirdRulesDic.xml";
-        const string EnhanceMenusDicUrl = "https://gitee.com/BluePointLilac/ContextMenuManager/raw/master/ContextMenuManager/Properties/Resources/Texts/EnhanceMenusDic.xml";
-        const string UwpModeItemsDicUrl = "https://gitee.com/BluePointLilac/ContextMenuManager/raw/master/ContextMenuManager/Properties/Resources/Texts/UwpModeItemsDic.xml";
+        const string GithubLatest = "https://api.github.com/repos/BluePointLilac/ContextMenuManager/releases/latest";
+        const string GiteeLatest = "https://gitee.com/api/v5/repos/BluePointLilac/ContextMenuManager/releases/latest";
+        const string GithubLangs = "https://api.github.com/repos/BluePointLilac/ContextMenuManager/contents/languages";
+        const string GiteeLangs = "https://gitee.com/api/v5/repos/BluePointLilac/ContextMenuManager/contents/languages";
+        const string GithubTexts = "https://raw.githubusercontent.com/BluePointLilac/ContextMenuManager/master/ContextMenuManager/Properties/Resources/Texts";
+        const string GiteeTexts = "https://gitee.com/BluePointLilac/ContextMenuManager/raw/master/ContextMenuManager/Properties/Resources/Texts";
+        const string GithubDonate = "https://raw.githubusercontent.com/BluePointLilac/ContextMenuManager/master/Donate.md";
+        const string GiteeDonate = "https://gitee.com/BluePointLilac/ContextMenuManager/raw/master/Donate.md";
 
         public static void PeriodicUpdate()
         {
-            Version appVersion = new Version(Application.ProductVersion);
-            //如果上次检测更新时间为一个月以前就进行更新操作
-            bool flag1 = AppConfig.LastCheckUpdateTime.AddMonths(1) < DateTime.Today;
-            //如果配置文件中的版本号与程序版本号不同也进行更新操作
-            bool flag2 = appVersion != AppConfig.Version;
-            if(flag1 || flag2)
-            {
-                CheckUpdate();
-                AppConfig.Version = appVersion;
-                AppConfig.LastCheckUpdateTime = DateTime.Today;
-            }
+            int day = AppConfig.UpdateFrequency;
+            if(day == -1) return;//自动检测更新频率为-1则从不自动检查更新
+            //如果上次检测更新时间加上时间间隔早于今天以前就进行更新操作
+            if(AppConfig.LastCheckUpdateTime.AddDays(day) < DateTime.Today) Update();
         }
 
-        public static bool CheckUpdate()
+        public static bool Update()
         {
-            UpdateText(AppConfig.WebGuidInfosDic, GuidInfosDicUrl);
-            UpdateText(AppConfig.WebThirdRulesDic, ThirdRulesDicUrl);
-            UpdateText(AppConfig.WebEnhanceMenusDic, EnhanceMenusDicUrl);
-            UpdateText(AppConfig.WebUwpModeItemsDic, UwpModeItemsDicUrl);
-            try { return UpdateApp(); } catch { return false; }
+            AppConfig.LastCheckUpdateTime = DateTime.Today;
+            UpdateText();
+            return UpdateApp();
         }
 
         private static bool UpdateApp()
         {
-            IniReader reader = new IniReader(new StringBuilder(GetWebString(UpdateUrl)));
-            Version version1;
-            try
+            string url = AppConfig.RequestUseGithub ? GithubLatest : GiteeLatest;
+            XmlDocument doc = GetWebJsonToXml(url);
+            if(doc == null) return false;
+            XmlNode root = doc.FirstChild;
+            XmlElement tagNameXE = (XmlElement)root.SelectSingleNode("tag_name");
+            Version webVer = new Version(tagNameXE.InnerText);
+            Version appVer = new Version(Application.ProductVersion);
+            if(webVer > appVer)
+            {
+                XmlElement bodyXE = (XmlElement)root.SelectSingleNode("body");
+                string info = AppString.Message.UpdateInfo.Replace("%v1", appVer.ToString()).Replace("%v2", webVer.ToString());
+                info += "\r\n\r\n" + MachinedInfo(bodyXE.InnerText);
+                if(MessageBoxEx.Show(info, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
+                {
+                    string netVer = Environment.Version > new Version(4, 0) ? "4.0" : "3.5";
+                    XmlElement assetsXE = (XmlElement)root.SelectSingleNode("assets");
+                    foreach(XmlElement itemXE in assetsXE.SelectNodes("item"))
+                    {
+                        XmlElement nameXE = (XmlElement)itemXE.SelectSingleNode("name");
+                        if(nameXE != null && nameXE.InnerText.Contains(netVer))
+                        {
+                            XmlElement urlXE = (XmlElement)itemXE.SelectSingleNode("browser_download_url");
+                            using(DownloadDialog dlg = new DownloadDialog())
+                            {
+                                dlg.Url = urlXE?.InnerText;
+                                dlg.FilePath = Path.GetTempFileName();
+                                if(dlg.ShowDialog() == DialogResult.OK)
+                                {
+                                    MessageBoxEx.Show(AppString.Message.UpdateSucceeded, MessageBoxButtons.OK, MessageBoxIcon.Information);
+                                    SingleInstance.Restart(null, dlg.FilePath);
+                                }
+                            }
+                        }
+                    }
+                }
+                return true;
+            }
+            return false;
+        }
+
+        private static void UpdateText()
+        {
+            string url = AppConfig.RequestUseGithub ? GithubTexts : GiteeTexts;
+            string[] fileNames = new[]
+            {
+                AppConfig.GUIDINFOSDICINI, AppConfig.ENHANCEMENUSICXML,
+                AppConfig.THIRDRULESDICXML, AppConfig.UWPMODEITEMSDICXML
+            };
+            foreach(string fileName in fileNames)
             {
-                version1 = new Version(reader.GetValue("Update", "Version"));
+                string fileUrl = $"{url}/{fileName}";
+                string filePath = $@"{AppConfig.WebDicsDir}\{fileName}";
+                string contents = GetWebString(fileUrl);
+                if(string.IsNullOrEmpty(contents)) continue;
+                contents = contents.Replace("\n", Environment.NewLine);
+                File.WriteAllText(filePath, contents, Encoding.Unicode);
             }
-            catch
+        }
+
+        public static bool ShowLanguageDialog()
+        {
+            string url = AppConfig.RequestUseGithub ? GithubLangs : GiteeLangs;
+            XmlDocument doc = GetWebJsonToXml(url);
+            if(doc == null) return false;
+            Dictionary<string, string> langs = new Dictionary<string, string>();
+            foreach(XmlElement itemXE in doc.FirstChild.SelectNodes("item"))
             {
-                version1 = new Version(Application.ProductVersion);
+                XmlElement nameXE = (XmlElement)itemXE.SelectSingleNode("name");
+                XmlElement urlXE = (XmlElement)itemXE.SelectSingleNode("download_url");
+                string lang = Path.GetFileNameWithoutExtension(nameXE.InnerText);
+                langs.Add(lang, urlXE.InnerText);
             }
-            Version version2 = new Version(Application.ProductVersion);
-            if(version1 > version2)
+            using(SelectDialog dlg = new SelectDialog())
             {
-                string info = reader.GetValue("Update", "Info").Replace("\\n", Environment.NewLine);
-                if(MessageBoxEx.Show($"{AppString.MessageBox.UpdateApp}{version1}{Environment.NewLine}{info}",
-                    MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
+                dlg.Items = langs.Keys.ToArray();
+                dlg.Title = AppString.Dialog.DownloadLanguages;
+                string lang = CultureInfo.CurrentUICulture.Name;
+                if(dlg.Items.Contains(lang)) dlg.Selected = lang;
+                else dlg.SelectedIndex = 0;
+                if(dlg.ShowDialog() == DialogResult.OK)
                 {
-                    string url = reader.GetValue("Update", "Url");
-                    ExternalProgram.OpenUrl(url);
+                    lang = dlg.Selected;
+                    string contents = GetWebString(langs[lang]);
+                    string filePath = $@"{AppConfig.LangsDir}\{lang}.ini";
+                    File.WriteAllText(filePath, contents, Encoding.Unicode);
                     return true;
                 }
             }
             return false;
         }
 
-        private static void UpdateText(string filePath, string url)
+        public static void ShowDonateDialog()
         {
+            string url = AppConfig.RequestUseGithub ? GithubDonate : GiteeDonate;
             string contents = GetWebString(url);
-            if(!contents.IsNullOrWhiteSpace())
-                File.WriteAllText(filePath, contents.Replace("\n", Environment.NewLine), Encoding.Unicode);
+            //string contents = File.ReadAllText(@"..\..\..\Donate.md");//用于求和更新Donate.md文件
+            if(contents == null) ExternalProgram.OpenUrl(url);
+            else
+            {
+                using(DonateListDialog dlg = new DonateListDialog())
+                {
+                    dlg.DanateData = contents;
+                    dlg.ShowDialog();
+                }
+            }
+        }
+
+        private static string MachinedInfo(string info)
+        {
+            string str = string.Empty;
+            string[] lines = info.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None);
+            for(int m = 0; m < lines.Length; m++)
+            {
+                string line = lines[m];
+                for(int n = 1; n <= 6; n++)
+                {
+                    if(line.StartsWith(new string('#', n) + ' '))
+                    {
+                        line = line.Substring(n + 1);
+                        break;
+                    }
+                }
+                str += line + Environment.NewLine;
+            }
+            return str;
         }
 
         private static string GetWebString(string url)
         {
             try
             {
-                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
-                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
-                using(StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
-                    return reader.ReadToEnd();
+                using(WebResponse response = WebRequest.Create(url).GetResponse())
+                using(StreamReader stream = new StreamReader(response.GetResponseStream()))
+                    return stream?.ReadToEnd();
+            }
+            catch { return null; }
+        }
+
+        private static XmlDocument GetWebJsonToXml(string url)
+        {
+            try
+            {
+                using(WebResponse response = WebRequest.Create(url).GetResponse())
+                using(StreamReader stream = new StreamReader(response.GetResponseStream()))
+                using(XmlReader reader = JsonReaderWriterFactory.CreateJsonReader(stream?.BaseStream, XmlDictionaryReaderQuotas.Max))
+                {
+                    XmlDocument doc = new XmlDocument();
+                    doc.Load(reader);
+                    return doc;
+                }
             }
             catch { return null; }
         }

+ 59 - 47
Donate.md

@@ -8,9 +8,9 @@
 
 ## 捐赠名单
 
-> 此名单不定期更新(上次更新:**2021-04-11**)
+> 此名单不定期更新(上次更新:**2021-05-14**)
 
-> 累计金额:**408.3** 元,累计人次:**71** 人次
+> 累计金额:**501.78** 元,累计人次:**83** 人次
 
 |日期|用户ID|平台|金额|备注
 |:--:|:--:|:--:|:--:|:--:
@@ -40,48 +40,60 @@
 |2020-12-18|*班|微信|5|加油
 |2020-12-25|*贵|微信|10|点赞!
 |2020-12-31|*昊|支付宝|15|支持一下,大佬继续加油
-|2020-01-03|匿名|微信|4|
-|2020-01-03|s*h|微信|2|
-|2020-01-06|*檬|微信|1|
-|2020-01-09|*。|微信|2|
-|2020-01-09|**璐|支付宝|5|支持开源
-|2020-01-11|*%|微信|1|
-|2020-01-13|*犇|微信|3|辛苦,喝瓶肥宅快乐水
-|2020-01-15|*柚|微信|1|
-|2020-01-15|**轩|支付宝|10|
-|2020-01-23|**政|支付宝|1.88|支持大佬
-|2020-01-26|*宁|微信|10|软件很好用,支持你
-|2020-01-28|*闯|支付宝|5|
-|2020-01-28|m*c|微信|4|
-|2020-01-28|*闯|支付宝|5|
-|2020-02-02|*强|微信|1|
-|2020-02-02|i*y|微信|5|cmm太好用了 救大命
-|2020-02-06|F*t|微信|1|感谢作者,牛年牛牛牛
-|2020-02-10|L*g|微信|2|
-|2020-02-11|戴*n|微信|5|太好用了,第一次捐赠
-|2020-02-12|*奕|支付宝|2.8|真不错
-|2020-02-18|**凯|支付宝|6|方便好用,支持你
-|2020-02-24|**方|支付宝|2|
-|2020-02-25|闭*g|微信|3|请大佬喝饮料🥤
-|2020-02-26|**海|支付宝|30|
-|2020-02-26|*觉|微信|1.6|
-|2020-02-28|*奇|微信|10|
-|2020-03-02|*瑜|微信|3|
-|2020-03-04|**方|支付宝|2|
-|2020-03-05|*科|支付宝|1|
-|2020-03-10|*y|微信|6.66|
-|2020-03-12|*禹|支付宝|5|
-|2020-03-12|*游|微信|50|谢谢您的软件
-|2020-03-13|k*h|微信|6.66|右键管理强迫症福音
-|2020-03-13|*🍊|微信|10|软件好用,十分感谢!
-|2020-03-16|**骏|支付宝|0.1|
-|2020-03-16|**华|支付宝|5|
-|2020-03-19|**阳|支付宝|1|感谢帮我移除了天翼云盘右键菜单
-|2020-03-23|*👀|微信|6.66|
-|2020-03-25|**楠|支付宝|1|
-|2020-03-29|花*.|微信|3|挺好用哒哒
-|2020-03-30|*珊|微信|10|
-|2020-04-02|**霖|支付宝|10|
-|2020-04-03|**科|支付宝|6|
-|2020-04-08|**帅|支付宝|2|
-|2020-04-08|*财|微信|2|菜单管理工具太棒了
+|2021-01-03|匿名|微信|4|
+|2021-01-03|s*h|微信|2|
+|2021-01-06|*檬|微信|1|
+|2021-01-09|*。|微信|2|
+|2021-01-09|**璐|支付宝|5|支持开源
+|2021-01-11|*%|微信|1|
+|2021-01-13|*犇|微信|3|辛苦,喝瓶肥宅快乐水
+|2021-01-15|*柚|微信|1|
+|2021-01-15|**轩|支付宝|10|
+|2021-01-23|**政|支付宝|1.88|支持大佬
+|2021-01-26|*宁|微信|10|软件很好用,支持你
+|2021-01-28|*闯|支付宝|5|
+|2021-01-28|m*c|微信|4|
+|2021-01-28|*闯|支付宝|5|
+|2021-02-02|*强|微信|1|
+|2021-02-02|i*y|微信|5|cmm太好用了 救大命
+|2021-02-06|F*t|微信|1|感谢作者,牛年牛牛牛
+|2021-02-10|L*g|微信|2|
+|2021-02-11|戴*n|微信|5|太好用了,第一次捐赠
+|2021-02-12|*奕|支付宝|2.8|真不错
+|2021-02-18|**凯|支付宝|6|方便好用,支持你
+|2021-02-24|**方|支付宝|2|
+|2021-02-25|闭*g|微信|3|请大佬喝饮料🥤
+|2021-02-26|**海|支付宝|30|
+|2021-02-26|*觉|微信|1.6|
+|2021-02-28|*奇|微信|10|
+|2021-03-02|*瑜|微信|3|
+|2021-03-04|**方|支付宝|2|
+|2021-03-05|*科|支付宝|1|
+|2021-03-10|*y|微信|6.66|
+|2021-03-12|*禹|支付宝|5|
+|2021-03-12|*游|微信|50|谢谢您的软件
+|2021-03-13|k*h|微信|6.66|右键管理强迫症福音
+|2021-03-13|*🍊|微信|10|软件好用,十分感谢!
+|2021-03-16|**骏|支付宝|0.1|
+|2021-03-16|**华|支付宝|5|
+|2021-03-19|**阳|支付宝|1|感谢帮我移除了天翼云盘右键菜单
+|2021-03-23|*👀|微信|6.66|
+|2021-03-25|**楠|支付宝|1|
+|2021-03-29|花*.|微信|3|挺好用哒哒
+|2021-03-30|*珊|微信|10|
+|2021-04-02|**霖|支付宝|10|
+|2021-04-03|**科|支付宝|6|
+|2021-04-08|**帅|支付宝|2|
+|2021-04-11|*财|微信|2|菜单管理工具太棒了
+|2021-04-12|**基|支付宝|5|请喝维他奶
+|2021-04-13|**方|支付宝|4|
+|2021-04-14|**明|支付宝|50|
+|2021-04-21|*。|微信|5|
+|2021-04-22|生鲜鱼弱|微信|6.66|加油
+|2021-04-26|**彬|支付宝|6.66|大佬加油!!!
+|2021-04-28|*浦|微信|6.66|
+|2021-04-29|j*y|微信|0.5|清理右键菜单
+|2021-05-06|*越|支付宝|3|
+|2021-05-08|**泽|支付宝|3|
+|2021-05-10|G*H|微信|5|
+|2021-05-11|j*k|微信|1|谢谢!

+ 2 - 2
README-en.md

@@ -17,11 +17,11 @@
 * localization support, contributions are welcome
 
 ## Screenshots
-![](Screenshot-en.png)
+![](Screenshot/Screenshot-en.png)
 
 ## Third-party resources
 * Main program icon from [EasyIcon][EasyIcon]<br>![][AppIcon]
-* [Button icons][AppImage] from [Alibaba Iconfont][IconFont]![](AppImage.png)
+* [Button icons][AppImage] from [Alibaba Iconfont][IconFont]![](Screenshot/AppImage.png)
 
 ## Updates
 * Program and dictionary updates can be installed within the program, overwritting the original files.

+ 3 - 8
README.md

@@ -10,21 +10,16 @@
 
 ## 兼容性能
 * 适用于Win7、8、8.1、10、Vista
-* 适用于 x64、x32 CPU 操作系统
+* 适用于 64bit、32bit CPU 操作系统
 * 适用于高分屏,最佳显示缩放比为150%
 * 程序支持国际化多语言显示,欢迎为此程序制作语言字典
 
 ## 运行截图
-![](Screenshot.png)
+![](Screenshot/Screenshot.png)
 
 ## 资源引用
 * 程序主图标来自 [EasyIcon][EasyIcon]<br>![][AppIcon]
-* [程序按钮图标][AppImage] 主要来自于 [阿里巴巴矢量图标资源库][IconFont]<br>![](AppImage.png)
-
-## 下载更新
-* 程序有检查更新功能,除了更新程序本身还会更新程序字典,下载完成后直接覆盖原文件即可
-* 由于Github Raw被墙,Gitee Raw有月访问次数上限,故将程序设置为每月自动检测一次更新,<br>
-大家也可以自行浏览 [Github Releases][GitHub Releases] 或 [Gitee 发行版][Gitee Releases] 检查程序是否有更新。
+* [程序按钮图标][AppImage] 主要来自于 [阿里巴巴矢量图标资源库][IconFont]<br>![](Screenshot/AppImage.png)
 
 ## 温馨提示
 * 一些特殊菜单项目(ShellEx类型,比如文件的加密(&Y))可能会受到其他因素影响,导致不会显示<br>在右键菜单中,但是按照程序使用的通用规则在此程序中仍会显示为启用,这是正常现象。

+ 0 - 0
AppImage.png → Screenshot/AppImage.png


+ 0 - 0
Screenshot-en.png → Screenshot/Screenshot-en.png


+ 0 - 0
Screenshot.png → Screenshot/Screenshot.png


+ 5 - 3
Update.ini

@@ -1,4 +1,6 @@
+;自3.3.0.0版本以后使用新的更新模块,此文件不再使用
+
 [Update]
-Version=3.2.0.0
-Url=https://github.com/BluePointLilac/ContextMenuManager/releases/download/3.2.0.0/ContextMenuManager.zip
-Info=【更新描述】\n(1).优化部分代码,修复部分Bug;\n(2).添加拖拽文件分析菜单功能;\n(3).添加分析自定义注册表路径菜单功能;\n(4).添加隐藏已禁用菜单项目功能;\n(5).添加了翻译程序功能;\n(6).减小了程序文件大小。
+Version=3.3.0.0
+Url=https://github.com/BluePointLilac/ContextMenuManager/releases/download/3.3.0.0/ContextMenuManager.zip
+Info=【更新描述】\n(1).完善程序更新功能;\n(2).添加下载其他语言功能;\n(3).完善GUID字典功能.\n(4).新增了程序字典.\n(5).修复已知Bug,优化大量代码.

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 23 - 31
languages/en-US.ini


+ 11 - 17
languages/ja-JP.ini

@@ -1,8 +1,3 @@
-;此文件为ContextMenuManager程序的显示文本字典, 字典内换行符使用\n转义
-;如果你想要帮助作者为此程序添加其他语言字典, 可以修改此文本并保存在.\config\languages文件夹内, 
-;比如美国英语字典保存为en-US.ini, 并给[General]\Language赋值 en-US 英语
-;可以在Github或Gitee上Fork该项目并提交申请给我,或者直接发送文件到邮箱[email protected]
-
 [General]
 Language = ja-JP 日本語
 Translator = 夕綺Yuuki
@@ -119,35 +114,34 @@ EditSubItems = 「%s」のサブメニュー項目を編集
 CheckReference = 引用を追加したいメニュー項目をチェックしてください
 CheckCommon = 追加したい一般的なメニュー項目を確認してください
 SelectExtension = ファイル拡張子を選択してください
-SelectSubMenuMode = 当現在のマルチレベルメニューのサブ項目数は0です。二つの選択肢がある:\n①このマルチレベルメニューのすべてのサブメニュー項目はプライベートですが、\n②このマルチレベルメニューは、他のマルチレベルメニューと同じサブアイテムを参照できます、\n選択してください。
+SelectSubMenuMode = 当現在のマルチレベルメニューのサブ項目数は0です。二つの選択肢がある:\r\n①このマルチレベルメニューのすべてのサブメニュー項目はプライベートですが、\r\n②このマルチレベルメニューは、他のマルチレベルメニューと同じサブアイテムを参照できます、\r\n選択してください。
 
-[MessageBox]
+[Message]
 TextCannotBeEmpty = メニューテキストを空にすることはできません!
 CommandCannotBeEmpty = メニューコマンドを空にすることはできません!
 StringParsingFailed = ローカライズされた文字列解析に失敗!
 TextLengthCannotExceed80 = メニューテキストが長すぎます。長さは80を超えることはできません!
-ConfirmDeletePermanently = このアイテムを完全に削除しますか。\nこの操作は復元できません、注意してください!
+ConfirmDeletePermanently = このアイテムを完全に削除しますか。\r\nこの操作は復元できません、注意してください!
 ConfirmDeleteReference = プロジェクトへの参照を削除しますか。
 ConfirmDelete = このアイテムを削除しますか。
-ConfirmDeleteReferenced = このアイテムを完全に削除しますか。\nこのアイテムを参照するすべてのアイテムは無効になります、注意してください。
-CannotAddNewItem = システムはサブメニュー項目の最大数を16に制限します、\n追加できません!
-UnsupportedFilename = サポートされていないファイル名、\n同じファイル名のメニュー項目がすでに存在している可能性があります!
+ConfirmDeleteReferenced = このアイテムを完全に削除しますか。\r\nこのアイテムを参照するすべてのアイテムは無効になります、注意してください。
+CannotAddNewItem = システムはサブメニュー項目の最大数を16に制限します、\r\n追加できません!
+UnsupportedFilename = サポートされていないファイル名、\r\n同じファイル名のメニュー項目がすでに存在している可能性があります!
 UnsupportedExtension = サポートされていないファイル拡張子!
 CannotChangePath = ファイルパスの変更は許可されていません!
 CopiedToClipboard = クリップボードにコピー:
 UnknownGuid = 不明なGuid!
 HasBeenAdded = このアイテムが追加されました!
-EditInitialData = プレーンテキストファイル(.txt、.batなど)のみをサポートします、\nバイナリデータを書き込む必要がある場合は、レジストリ内の関連するタイプの「Data」キー値を自分で編集してください、\n編集を続けますか。
-PromptIsOpenItem = このアイテムは「開く」メニュー、\n盲目的な操作には、ファイルやフォルダを開くことができなくなる場合があります、\n続行するかどうか。(お勧めしません)
+EditInitialData = プレーンテキストファイル(.txt、.batなど)のみをサポートします、\r\nバイナリデータを書き込む必要がある場合は、レジストリ内の関連するタイプの「Data」キー値を自分で編集してください、\r\n編集を続けますか。
+PromptIsOpenItem = このアイテムは「開く」メニュー、\r\n盲目的な操作には、ファイルやフォルダを開くことができなくなる場合があります、\r\n続行するかどうか。(お勧めしません)
 RestartApp = プログラムが再起動します!
-UpdateApp = 現在アップデートがありますが、ダウンロードしますか。\n更新情報:バージョン番号
 FileOrFolderNotExists = ファイルまたはフォルダーが存在しません!
 
 [Tip]
-RestartExplorer = Explorerを再起動すると、デスクトップがしばらくちらつきます。通常の現象を心配する必要はありません、\n後でコンピュータを再起動またはログオフして、操作を有効にすることもできます。
+RestartExplorer = Explorerを再起動すると、デスクトップがしばらくちらつきます。通常の現象を心配する必要はありません、\r\n後でコンピュータを再起動またはログオフして、操作を有効にすることもできます。
 CustomFolder = このオプションを無効にすると、ファイルシステムオブジェクトのプロパティパネルのカスタムタブも無効になります
-SendToDrive = リムーバブルディスクが挿入されている場合にのみ機能します、\nリムーバブルディスクのすべてのパーティションを表示する
-BuildSendtoMenu = このオプションを無効にすると、メインメニューのポップアップ速度が速くなります、\nただし、サブメニューポップアップへの送信速度が遅くなります
+SendToDrive = リムーバブルディスクが挿入されている場合にのみ機能します、\r\nリムーバブルディスクのすべてのパーティションを表示する
+BuildSendtoMenu = このオプションを無効にすると、メインメニューのポップアップ速度が速くなります、\r\nただし、サブメニューポップアップへの送信速度が遅くなります
 InvalidItem = メニュー項目が無効な場合、この項目の下にあるすべてのメニュー項目が非表示になります(削除することをお勧めします)
 EditSubItems = サブメニュー項目の編集
 AddExistingItems = 既存のプロジェクトへの参照を追加

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 59 - 49
languages/zh-CN.ini


이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.