NewShellDialog.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. using BluePointLilac.Methods;
  2. using System;
  3. using System.IO;
  4. using System.Windows.Forms;
  5. namespace ContextMenuManager.Controls
  6. {
  7. sealed class NewShellDialog : CommonDialog
  8. {
  9. public string ShellPath { get; set; }//传入的Shell注册表路径
  10. public string ScenePath { get; set; }//菜单项所处环境注册表路径
  11. public string NewItemRegPath { get; private set; }//返回的新ShellItem的注册表路径
  12. public string NewItemKeyName => RegistryEx.GetKeyName(NewItemRegPath);
  13. public override void Reset() { }
  14. protected override bool RunDialog(IntPtr hwndOwner)
  15. {
  16. using(NewShellForm frm = new NewShellForm
  17. {
  18. ScenePath = this.ScenePath,
  19. ShellPath = this.ShellPath
  20. })
  21. {
  22. bool flag = frm.ShowDialog() == DialogResult.OK;
  23. if(flag) this.NewItemRegPath = frm.NewItemRegPath;
  24. return flag;
  25. }
  26. }
  27. sealed class NewShellForm : NewItemForm
  28. {
  29. public string ShellPath { get; set; }
  30. public string NewItemRegPath { get; private set; }//返回的新建菜单项注册表路径
  31. public string ScenePath { get; set; }//菜单所处环境路径,用于判断添加后缀
  32. readonly RadioButton rdoSingle = new RadioButton
  33. {
  34. Text = AppString.Dialog.SingleMenu,
  35. AutoSize = true,
  36. Checked = true
  37. };
  38. readonly RadioButton rdoMulti = new RadioButton
  39. {
  40. Text = AppString.Dialog.MultiMenu,
  41. AutoSize = true
  42. };
  43. readonly ShellExecuteCheckBox chkSE = new ShellExecuteCheckBox();
  44. static readonly string[] DirScenePaths = {
  45. ShellList.MENUPATH_DIRECTORY,
  46. $@"{ShellList.SYSFILEASSPATH}\Directory."
  47. };
  48. static readonly string[] FileObjectsScenePaths = {
  49. ShellList.MENUPATH_FILE,
  50. ShellList.MENUPATH_FOLDER,
  51. ShellList.MENUPATH_ALLOBJECTS,
  52. ShellList.SYSFILEASSPATH,
  53. ShellList.MENUPATH_UNKNOWN,
  54. ShellList.MENUPATH_UWPLNK
  55. };
  56. protected override void InitializeComponents()
  57. {
  58. base.InitializeComponents();
  59. this.Controls.AddRange(new Control[] { rdoSingle, rdoMulti, chkSE });
  60. rdoSingle.Top = rdoMulti.Top = btnOk.Top;
  61. rdoSingle.Left = lblCommand.Left;
  62. rdoMulti.Left = rdoSingle.Right + 20.DpiZoom();
  63. chkSE.Top = txtArguments.Top + (txtArguments.Height - chkSE.Height) / 2;
  64. this.Resize += (sender, e) => chkSE.Left = txtArguments.Right + 20.DpiZoom();
  65. this.OnResize(null);
  66. rdoMulti.CheckedChanged += (sender, e) =>
  67. {
  68. if(rdoMulti.Checked)
  69. {
  70. chkSE.Checked = false;
  71. if(WindowsOsVersion.IsEqualVista)
  72. {
  73. MessageBoxEx.Show(AppString.Message.VistaUnsupportedMulti);
  74. rdoSingle.Checked = true;
  75. return;
  76. }
  77. }
  78. lblCommand.Enabled = txtFilePath.Enabled = lblArguments.Enabled
  79. = txtArguments.Enabled = btnBrowse.Enabled = chkSE.Enabled = !rdoMulti.Checked;
  80. };
  81. btnBrowse.Click += (sender, e) => BrowseFile();
  82. btnOk.Click += (sender, e) =>
  83. {
  84. if(txtText.Text.IsNullOrWhiteSpace())
  85. {
  86. MessageBoxEx.Show(AppString.Message.TextCannotBeEmpty);
  87. }
  88. else
  89. {
  90. AddNewItem();
  91. DialogResult = DialogResult.OK;
  92. }
  93. };
  94. }
  95. private void BrowseFile()
  96. {
  97. using(OpenFileDialog dlg = new OpenFileDialog())
  98. {
  99. dlg.DereferenceLinks = false;
  100. dlg.Filter = $"{AppString.Dialog.Program}|*.exe|{AppString.Dialog.AllFiles}|*";
  101. if(dlg.ShowDialog() != DialogResult.OK) return;
  102. string filePath = dlg.FileName;
  103. string arguments = "";
  104. ItemText = Path.GetFileNameWithoutExtension(filePath);
  105. string extension = Path.GetExtension(filePath).ToLower();
  106. if(extension == ".lnk")
  107. {
  108. using(ShellLink shellLink = new ShellLink(filePath))
  109. {
  110. filePath = shellLink.TargetPath;
  111. arguments = shellLink.Arguments;
  112. extension = Path.GetExtension(filePath);
  113. }
  114. }
  115. string exePath = FileExtension.GetExecutablePath(extension);
  116. if(File.Exists(exePath))
  117. {
  118. ItemFilePath = exePath;
  119. Arguments = filePath;
  120. if(!arguments.IsNullOrWhiteSpace()) Arguments += " " + arguments;
  121. }
  122. else
  123. {
  124. ItemFilePath = filePath;
  125. Arguments = arguments;
  126. }
  127. if(Array.FindIndex(DirScenePaths, path
  128. => ScenePath.StartsWith(path, StringComparison.OrdinalIgnoreCase)) != -1)
  129. {
  130. if(ScenePath != ShellList.MENUPATH_BACKGROUND)
  131. {
  132. if(!Arguments.IsNullOrWhiteSpace()) Arguments += " ";
  133. Arguments += "\"%V\"";//自动加目录后缀
  134. }
  135. }
  136. else if(Array.FindIndex(FileObjectsScenePaths, path
  137. => ScenePath.StartsWith(path, StringComparison.OrdinalIgnoreCase)) != -1)
  138. {
  139. if(!Arguments.IsNullOrWhiteSpace()) Arguments += " ";
  140. Arguments += "\"%1\"";//自动加文件对象后缀
  141. }
  142. }
  143. }
  144. private void AddNewItem()
  145. {
  146. using(var shellKey = RegistryEx.GetRegistryKey(ShellPath, true, true))
  147. {
  148. string keyName = "Item";
  149. NewItemRegPath = ObjectPath.GetNewPathWithIndex($@"{ShellPath}\{keyName}", ObjectPath.PathType.Registry, 0);
  150. keyName = RegistryEx.GetKeyName(NewItemRegPath);
  151. using(var key = shellKey.CreateSubKey(keyName, true))
  152. {
  153. key.SetValue("MUIVerb", ItemText);
  154. if(rdoMulti.Checked)
  155. key.SetValue("SubCommands", "");
  156. else
  157. {
  158. if(!ItemCommand.IsNullOrWhiteSpace())
  159. {
  160. string command;
  161. if(!chkSE.Checked) command = ItemCommand;
  162. else command = ShellExecuteDialog.GetCommand(ItemFilePath, Arguments, chkSE.Verb, chkSE.WindowStyle);
  163. key.CreateSubKey("command", true).SetValue("", command);
  164. }
  165. }
  166. }
  167. }
  168. }
  169. }
  170. }
  171. }