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.

208 lines
6.9 KiB

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