PdnMenuItem.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. using PaintDotNet.Data.Param;
  2. using PaintDotNet.Base.SettingModel;
  3. using PaintDotNet.SystemLayer;
  4. using System;
  5. using System.ComponentModel;
  6. using System.Drawing;
  7. using System.IO;
  8. using System.Reflection;
  9. using System.Windows.Forms;
  10. namespace PaintDotNet
  11. {
  12. internal class PdnMenuItem : ToolStripMenuItem, IFormAssociate
  13. {
  14. /// <summary>
  15. /// 是否可以用在脚本功能里,默认true
  16. /// </summary>
  17. private bool canUseInScript = true;
  18. /// <summary>
  19. /// true可以自动执行 false只能手动执行,默认true
  20. /// </summary>
  21. private bool automaticScript = true;
  22. /// <summary>
  23. /// true自动执行下一步 false手动点击下一步执行,默认false
  24. /// </summary>
  25. private bool autoNextScript = false;
  26. /// <summary>
  27. /// 脚本是否必须打开窗口,并等待执行完成后才能继续的处理(针对通用分析和专用分析)
  28. /// </summary>
  29. private bool needOpenDialog = false;
  30. /// <summary>
  31. /// 脚本是否需要加等待执行完成后才能继续的处理
  32. /// </summary>
  33. private bool needWaitKey = false;
  34. /// <summary>
  35. /// 是否可以选中
  36. /// </summary>
  37. public bool canChecked = false;
  38. /// <summary>
  39. /// AppWorkspace的引用
  40. /// </summary>
  41. private AppWorkspace appWorkspace;
  42. private string textResourceName = null;
  43. private const char noMnemonicChar = (char)0;
  44. private const char mnemonicPrefix = '&';
  45. /// <summary>
  46. /// icon loaded的标记
  47. /// </summary>
  48. private bool iconsLoaded = false;
  49. /// <summary>
  50. /// 标题 loaded的标记
  51. /// </summary>
  52. private bool namesLoaded = false;
  53. /// <summary>
  54. /// 快捷键
  55. /// </summary>
  56. private Keys registeredHotKey = Keys.None;
  57. /// <summary>
  58. /// 当前菜单的唯一id
  59. /// </summary>
  60. private int menuId;
  61. public int MenuId
  62. {
  63. get
  64. {
  65. return this.menuId;
  66. }
  67. set
  68. {
  69. this.menuId = value;
  70. }
  71. }
  72. public bool CanUseInSenseShield
  73. {
  74. get
  75. {
  76. System.Collections.Generic.List<int> menuIdlists = new System.Collections.Generic.List<int>();
  77. menuIdlists.Add(this.menuId);
  78. PdnMenuItem menuItem = this;
  79. while (menuItem.OwnerItem != null && menuItem.OwnerItem is PdnMenuItem)
  80. {
  81. menuIdlists.Insert(0, ((PdnMenuItem)menuItem.OwnerItem).menuId);
  82. menuItem = (PdnMenuItem)menuItem.OwnerItem;
  83. }
  84. return Startup.getMenuIdUsable(menuIdlists, true);
  85. }
  86. }
  87. /// <summary>
  88. /// 是否授权显示该菜单
  89. /// </summary>
  90. public bool CanShowInSenseShield
  91. {
  92. get
  93. {
  94. return Startup.getMenuIdVisible(this.menuId);
  95. }
  96. }
  97. /// <summary>
  98. /// 是否可以用在脚本功能里,默认true
  99. /// </summary>
  100. public bool CanUseInScript
  101. {
  102. get
  103. {
  104. return this.canUseInScript;
  105. }
  106. set
  107. {
  108. this.canUseInScript = value;
  109. }
  110. }
  111. /// <summary>
  112. /// true可以自动执行 false只能手动执行,默认true
  113. /// </summary>
  114. public bool AutomaticScript
  115. {
  116. get
  117. {
  118. return this.automaticScript;
  119. }
  120. set
  121. {
  122. this.automaticScript = value;
  123. }
  124. }
  125. /// <summary>
  126. /// true自动执行下一步 false手动点击下一步执行,默认false
  127. /// </summary>
  128. public bool AutoNextScript
  129. {
  130. get
  131. {
  132. return this.autoNextScript;
  133. }
  134. set
  135. {
  136. this.autoNextScript = value;
  137. }
  138. }
  139. /// <summary>
  140. /// 脚本是否必须打开窗口,并等待执行完成后才能继续的处理(针对通用分析和专用分析)
  141. /// </summary>
  142. public bool NeedOpenDialog
  143. {
  144. get
  145. {
  146. return this.needOpenDialog;
  147. }
  148. set
  149. {
  150. this.needOpenDialog = value;
  151. }
  152. }
  153. /// <summary>
  154. /// 脚本是否需要加等待执行完成后才能继续的处理
  155. /// </summary>
  156. public bool NeedWaitKey
  157. {
  158. get
  159. {
  160. return this.needWaitKey;
  161. }
  162. set
  163. {
  164. this.needWaitKey = value;
  165. }
  166. }
  167. [Browsable(false)]
  168. public AppWorkspace AppWorkspace
  169. {
  170. get
  171. {
  172. return this.appWorkspace;
  173. }
  174. set
  175. {
  176. if (value != this.appWorkspace)
  177. {
  178. OnAppWorkspaceChanging();
  179. this.appWorkspace = value;
  180. OnAppWorkspaceChanged();
  181. }
  182. }
  183. }
  184. public Form AssociatedForm
  185. {
  186. get
  187. {
  188. if (this.appWorkspace == null)
  189. {
  190. return null;
  191. }
  192. else
  193. {
  194. return this.appWorkspace.FindForm();
  195. }
  196. }
  197. }
  198. public new Keys ShortcutKeys
  199. {
  200. get
  201. {
  202. return base.ShortcutKeys;
  203. }
  204. set
  205. {
  206. if (ShortcutKeys != Keys.None)
  207. {
  208. PdnBaseForm.UnregisterFormHotKey(ShortcutKeys, OnShortcutKeyPressed);
  209. }
  210. PdnBaseForm.RegisterFormHotKey(value, OnShortcutKeyPressed);
  211. base.ShortcutKeys = value;
  212. }
  213. }
  214. public void resetShortcutKeys(string itemHotKeys)
  215. {
  216. if (itemHotKeys != null && !itemHotKeys.Equals(""))
  217. {
  218. string[] keys = itemHotKeys.Trim().Split('+');
  219. Keys Key = Keys.None;
  220. foreach (string key in keys)
  221. {
  222. if (Key == Keys.None)
  223. {
  224. Key = (Keys)(Enum.Parse(typeof(Keys), key.Trim()));
  225. }
  226. else
  227. {
  228. Key = (Keys)(Enum.Parse(typeof(Keys), key.Trim())) | Key;
  229. }
  230. }
  231. this.ShortcutKeys = Key;
  232. }
  233. else
  234. {
  235. this.ShortcutKeys = Keys.None;
  236. }
  237. }
  238. public bool HasMnemonic
  239. {
  240. get
  241. {
  242. return (Mnemonic != noMnemonicChar);
  243. }
  244. }
  245. public char Mnemonic
  246. {
  247. get
  248. {
  249. if (string.IsNullOrEmpty(this.Text))
  250. {
  251. return noMnemonicChar;
  252. }
  253. int mnemonicPrefixIndex = this.Text.IndexOf(mnemonicPrefix);
  254. if (mnemonicPrefixIndex >= 0 && mnemonicPrefixIndex < this.Text.Length - 1)
  255. {
  256. return this.Text[mnemonicPrefixIndex + 1];
  257. }
  258. else
  259. {
  260. return noMnemonicChar;
  261. }
  262. }
  263. }
  264. public void PerformClickAsync()
  265. {
  266. this.Owner.BeginInvoke(new Procedure(this.PerformClick));
  267. }
  268. protected virtual void OnAppWorkspaceChanging()
  269. {
  270. foreach (ToolStripItem item in this.DropDownItems)
  271. {
  272. PdnMenuItem asPMI = item as PdnMenuItem;
  273. if (asPMI != null)
  274. {
  275. asPMI.AppWorkspace = null;
  276. }
  277. }
  278. }
  279. protected virtual void OnAppWorkspaceChanged()
  280. {
  281. foreach (ToolStripItem item in this.DropDownItems)
  282. {
  283. PdnMenuItem asPMI = item as PdnMenuItem;
  284. if (asPMI != null)
  285. {
  286. asPMI.AppWorkspace = AppWorkspace;
  287. }
  288. }
  289. }
  290. public PdnMenuItem(string name, Image image, EventHandler eventHandler)
  291. : base(name, image, eventHandler)
  292. {
  293. Constructor();
  294. }
  295. /// <summary>
  296. /// 目前用的构造方法
  297. /// </summary>
  298. /// <param name="type"></param>
  299. public PdnMenuItem(ActionType type)
  300. {
  301. Constructor();
  302. //设置快捷键,如果配置了
  303. SetHotKeyFromConfig((int)type);
  304. //设置名称
  305. this.Name = GetDescription(type);
  306. //设置id
  307. this.MenuId = (int)type;
  308. }
  309. public PdnMenuItem(ActionType type, bool canChecked)
  310. {
  311. Constructor();
  312. //设置快捷键,如果配置了
  313. SetHotKeyFromConfig((int)type);
  314. //设置名称
  315. this.Name = GetDescription(type);
  316. //设置id
  317. this.MenuId = (int)type;
  318. //设置可以被选中
  319. this.canChecked = canChecked;
  320. }
  321. public PdnMenuItem()
  322. {
  323. Constructor();
  324. }
  325. private void Constructor()
  326. {
  327. InitializeComponent();
  328. }
  329. private void InitializeComponent()
  330. {
  331. this.DropDownOpening += new EventHandler(PdnMenuItem_DropDownOpening);
  332. }
  333. private bool OnShortcutKeyPressed(Keys keys)
  334. {
  335. //PerformClick();
  336. return true;
  337. }
  338. private bool OnAccessHotKeyPressed(Keys keys)
  339. {
  340. ShowDropDown();
  341. return true;
  342. }
  343. protected override void OnTextChanged(EventArgs e)
  344. {
  345. if (this.registeredHotKey != Keys.None)
  346. {
  347. PdnBaseForm.UnregisterFormHotKey(this.registeredHotKey, OnAccessHotKeyPressed);
  348. }
  349. char mnemonic = this.Mnemonic;
  350. if (mnemonic != noMnemonicChar && !IsOnDropDown)
  351. {
  352. Keys hotKey = Utility.LetterOrDigitCharToKeys(mnemonic);//快捷键,通过alt+key打开一级菜单
  353. PdnBaseForm.RegisterFormHotKey(Keys.Alt | hotKey, OnAccessHotKeyPressed);//快捷键,通过alt+key打开一级菜单
  354. }
  355. base.OnTextChanged(e);
  356. }
  357. private void PdnMenuItem_DropDownOpening(object sender, EventArgs e)
  358. {
  359. OnDropDownOpening(e);
  360. }
  361. protected virtual void OnDropDownOpening(EventArgs e)
  362. {
  363. if (!this.namesLoaded)
  364. {
  365. LoadNames(this.Name);
  366. }
  367. if (!this.iconsLoaded)
  368. {
  369. LoadIcons();
  370. }
  371. }
  372. /// <summary>
  373. /// 递归查找菜单,如果脚本正在执行,则菜单不可手动点击
  374. /// </summary>
  375. /// <param name="collection"></param>
  376. /// <param name="step"></param>
  377. protected void RecursiveData(ToolStripItemCollection collection)
  378. {
  379. if (!AppWorkspace.ScriptRunning)
  380. return;
  381. Boolean enabled = false;
  382. for (int i = 0; i < collection.Count; i++)
  383. {
  384. if (collection[i] is PdnMenuItem)
  385. {
  386. ((PdnMenuItem)collection[i]).Enabled = enabled;
  387. //RecursiveData(((PdnMenuItem)collection[i]).DropDownItems);
  388. }
  389. //if (!collection[i].Name.Equals("OpenRecent") && !collection[i].Name.Equals("CameraSelection"))
  390. //{
  391. //}
  392. }
  393. }
  394. public void LoadNames(string baseName)
  395. {
  396. foreach (ToolStripItem item in this.DropDownItems)
  397. {
  398. if(!string.IsNullOrWhiteSpace(item.Name))
  399. {
  400. string itemNameBase = baseName + "." + item.Name;
  401. string itemNameText = itemNameBase + ".Text";
  402. string text = PdnResources.GetString(itemNameText);
  403. if (text != null)
  404. {
  405. item.Text = text;
  406. }
  407. PdnMenuItem pmi = item as PdnMenuItem;
  408. if (pmi != null)
  409. {
  410. pmi.textResourceName = itemNameText;
  411. pmi.LoadNames(itemNameBase);
  412. }
  413. }
  414. }
  415. this.namesLoaded = true;
  416. }
  417. public void SetIcon(string imageName)
  418. {
  419. this.ImageTransparentColor = Utility.TransparentKey;
  420. this.Image = PdnResources.GetImageResource(imageName).Reference;
  421. }
  422. public void SetIcon(ImageResource image)
  423. {
  424. this.ImageTransparentColor = Utility.TransparentKey;
  425. this.Image = image.Reference;
  426. }
  427. public void LoadIcons()
  428. {
  429. Type ourType = this.GetType();
  430. FieldInfo[] fields = ourType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
  431. foreach (FieldInfo fi in fields)
  432. {
  433. if (fi.FieldType.IsSubclassOf(typeof(PdnMenuItem)) ||
  434. fi.FieldType == typeof(PdnMenuItem))
  435. {
  436. string iconFileName = "Icons." + fi.Name[0].ToString().ToUpper() + fi.Name.Substring(1) + "Icon.png";
  437. PdnMenuItem mi = (PdnMenuItem)fi.GetValue(this);
  438. Stream iconStream = PdnResources.GetResourceStream(iconFileName);
  439. if (iconStream != null)
  440. {
  441. iconStream.Dispose();
  442. mi.SetIcon(iconFileName);
  443. }
  444. else
  445. {
  446. Tracing.Ping(iconFileName + " not found");
  447. }
  448. }
  449. }
  450. this.iconsLoaded = true;
  451. }
  452. protected override void OnDropDownClosed(EventArgs e)
  453. {
  454. foreach (ToolStripItem item in this.DropDownItems)
  455. {
  456. item.Enabled = true;
  457. }
  458. base.OnDropDownClosed(e);
  459. }
  460. protected override void OnClick(EventArgs e)
  461. {
  462. if ((this.DropDownItems == null || this.DropDownItems.Count == 0) && !this.CanUseInSenseShield)
  463. {
  464. string featureNameNotShield = this.Name ?? this.Text;
  465. Tracing.LogFeature(featureNameNotShield + "not shield");
  466. return;
  467. }
  468. var form = Form.ActiveForm;
  469. if (form != null)
  470. {
  471. form.BeginInvoke(new Procedure(PdnBaseForm.UpdateAllForms));
  472. }
  473. string featureName = this.Name ?? this.Text;
  474. Tracing.LogFeature(featureName);
  475. base.OnClick(e);
  476. }
  477. private void SetHotKeyFromConfig(int menuId)
  478. {
  479. if (Startup.instance.hotkeyModel != null
  480. && Startup.instance.hotkeyModel.items != null
  481. && Startup.instance.hotkeyModel.items.Count > 0)
  482. {
  483. HotkeyModel.Item item = Startup.instance.hotkeyModel.items.Find(m => m.MenuId == menuId);
  484. if (item!=null) {
  485. if (item.HotKeys != null && !item.HotKeys.Equals(""))
  486. {
  487. string[] keys = item.HotKeys.Trim().Split('+');
  488. Keys Key = Keys.None;
  489. foreach (string key in keys)
  490. {
  491. if (Key == Keys.None)
  492. {
  493. Key = (Keys)(Enum.Parse(typeof(Keys), key.Trim()));
  494. }
  495. else
  496. {
  497. Key = (Keys)(Enum.Parse(typeof(Keys), key.Trim())) | Key;
  498. }
  499. }
  500. this.ShortcutKeys = Key;
  501. }
  502. }
  503. }
  504. }
  505. /// <summary>
  506. /// 获取枚举的描述
  507. /// </summary>
  508. /// <param name="en">枚举</param>
  509. /// <returns>返回枚举的描述</returns>
  510. public static string GetDescription(Enum en)
  511. {
  512. Type type = en.GetType(); //获取类型
  513. MemberInfo[] memberInfos = type.GetMember(en.ToString()); //获取成员
  514. if (memberInfos != null && memberInfos.Length > 0)
  515. {
  516. DescriptionAttribute[] attrs = memberInfos[0].GetCustomAttributes(typeof(DescriptionAttribute), false) as DescriptionAttribute[]; //获取描述特性
  517. if (attrs != null && attrs.Length > 0)
  518. {
  519. return attrs[0].Description; //返回当前描述
  520. }
  521. }
  522. return en.ToString();
  523. }
  524. }
  525. }