You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

207 lines
6.9 KiB

3 years ago
  1. using Apewer.Surface;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Drawing;
  5. using System.Text;
  6. using System.Windows.Forms;
  7. namespace Apewer.Tray
  8. {
  9. /// <summary>托盘。</summary>
  10. class Tray
  11. {
  12. Form _form = null;
  13. NotifyIcon _icon = null;
  14. Tray(Action action)
  15. {
  16. _tray = this;
  17. _form = new Form();
  18. _form.FormBorderStyle = FormBorderStyle.None;
  19. _form.Size = new Size(0, 0);
  20. _form.StartPosition = FormStartPosition.CenterScreen;
  21. _form.ShowInTaskbar = false;
  22. _form.Text = "";
  23. _form.Paint += (s, e) =>
  24. {
  25. if (_form.Visible)
  26. {
  27. _form.Visible = false;
  28. action?.Invoke();
  29. }
  30. };
  31. Application.Run(_form);
  32. }
  33. static Tray _tray = null;
  34. static object _locker = new object();
  35. /// <summary>托盘图标。</summary>
  36. public NotifyIcon Icon { get => _tray?._icon; }
  37. /// <summary>在托盘线程中执行方法。</summary>
  38. public static void Invoke(Action action, bool async = false)
  39. {
  40. lock (_locker)
  41. {
  42. if (action == null) return;
  43. if (_tray == null) return;
  44. if (async) _tray?._form.BeginInvoke(new Action(action));
  45. else _tray?._form.Invoke(new Action(action));
  46. }
  47. }
  48. /// <summary>在托盘线程中执行方法。</summary>
  49. public static void BeginInvoke(Action action)
  50. {
  51. lock (_locker)
  52. {
  53. if (action == null) return;
  54. if (_tray == null) return;
  55. _tray?._form.BeginInvoke(new Action(action));
  56. }
  57. }
  58. /// <summary>启动托盘,阻塞当前线程。</summary>
  59. [STAThread]
  60. public static void Run(Action after = null)
  61. {
  62. lock (_locker)
  63. {
  64. if (_tray != null) return;
  65. FormsUtility.StartInitialization();
  66. FormsUtility.CrossThread();
  67. new Tray(after);
  68. }
  69. }
  70. /// <summary>退出托盘。</summary>
  71. public static void Exit()
  72. {
  73. lock (_locker)
  74. {
  75. if (_tray != null)
  76. {
  77. if (_tray._icon != null)
  78. {
  79. _tray._icon.Visible = false;
  80. _tray._icon.Dispose();
  81. }
  82. _tray._form.Close();
  83. _tray._form.Dispose();
  84. }
  85. _tray = null;
  86. }
  87. }
  88. /// <summary>显示托盘图标。</summary>
  89. public static void ShowIcon(Icon icon = null)
  90. {
  91. lock (_locker)
  92. {
  93. if (_tray == null) return;
  94. if (_tray._icon == null) _tray._icon = new NotifyIcon();
  95. _tray._icon.Icon = icon;
  96. _tray._icon.Visible = true;
  97. }
  98. }
  99. /// <summary>隐藏托盘图标。</summary>
  100. public static void HideIcon()
  101. {
  102. lock (_locker)
  103. {
  104. if (_tray == null) return;
  105. if (_tray._icon == null) return;
  106. _tray._icon.Visible = false;
  107. }
  108. }
  109. /// <summary>显示消息对话框。</summary>
  110. public static void MessageBox(string text, string caption = "", Action ok = null)
  111. {
  112. Invoke(() =>
  113. {
  114. System.Windows.Forms.MessageBox.Show(text, caption, MessageBoxButtons.OK);
  115. ok?.Invoke();
  116. });
  117. }
  118. /// <summary>显示确认对话框。</summary>
  119. public static void YesNo(string text, string caption = "", Action yes = null, Action no = null)
  120. {
  121. Invoke(() =>
  122. {
  123. var result = System.Windows.Forms.MessageBox.Show(text, caption, MessageBoxButtons.YesNo);
  124. if (result == DialogResult.Yes) yes?.Invoke();
  125. else if (result == DialogResult.No) no?.Invoke();
  126. });
  127. }
  128. /// <summary>显示打开文件对话框。</summary>
  129. public static void OpenFile(string title = null, Action<string[]> ok = null, Action cancel = null, bool multiselect = false, string filter = null, string directory = null)
  130. {
  131. Invoke(() =>
  132. {
  133. DialogResult result;
  134. string[] paths;
  135. using (var dialog = new OpenFileDialog())
  136. {
  137. if (!string.IsNullOrEmpty(title)) dialog.Title = title;
  138. if (!string.IsNullOrEmpty(filter)) dialog.Filter = filter;
  139. if (!string.IsNullOrEmpty(directory)) dialog.InitialDirectory = directory;
  140. dialog.Multiselect = multiselect;
  141. result = dialog.ShowDialog();
  142. paths = dialog.FileNames;
  143. }
  144. if (result == DialogResult.OK) ok?.Invoke(paths);
  145. else if (result == DialogResult.Cancel) cancel?.Invoke();
  146. });
  147. }
  148. /// <summary>显示保存文件对话框。</summary>
  149. public static void SaveFile(string title = null, Action<string> ok = null, Action cancel = null, string filter = null, string directory = null)
  150. {
  151. Invoke(() =>
  152. {
  153. DialogResult result;
  154. string path;
  155. using (var dialog = new SaveFileDialog())
  156. {
  157. if (!string.IsNullOrEmpty(title)) dialog.Title = title;
  158. if (!string.IsNullOrEmpty(filter)) dialog.Filter = filter;
  159. if (!string.IsNullOrEmpty(directory)) dialog.InitialDirectory = directory;
  160. result = dialog.ShowDialog();
  161. path = dialog.FileName;
  162. }
  163. if (result == DialogResult.OK) ok?.Invoke(path);
  164. else if (result == DialogResult.Cancel) cancel?.Invoke();
  165. });
  166. }
  167. /// <summary>显示选择文件夹对话框。</summary>
  168. public static void SelectFolder(string description = null, Action<string> ok = null, Action cancel = null)
  169. {
  170. Invoke(() =>
  171. {
  172. DialogResult result;
  173. string path;
  174. using (var dialog = new FolderBrowserDialog())
  175. {
  176. if (!string.IsNullOrEmpty(description)) dialog.Description = description;
  177. dialog.ShowNewFolderButton = true;
  178. result = dialog.ShowDialog();
  179. path = dialog.SelectedPath;
  180. }
  181. if (result == DialogResult.OK) ok?.Invoke(path);
  182. else if (result == DialogResult.Cancel) cancel?.Invoke();
  183. });
  184. }
  185. }
  186. }