WaitHelper.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. using DevExpress.Utils.Drawing;
  2. using DevExpress.Utils.Extensions;
  3. using DevExpress.XtraSplashScreen;
  4. using DevExpress.XtraWaitForm;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.ComponentModel;
  8. using System.Data;
  9. using System.Drawing;
  10. using System.IO;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Threading;
  14. using System.Threading.Tasks;
  15. using System.Windows.Forms;
  16. using static DevExpress.XtraEditors.RoundedSkinPanel;
  17. namespace DxHelper
  18. {
  19. /// <summary>
  20. /// 等待窗体帮助类,包含WaitForm、OverlayForm、
  21. /// </summary>
  22. public static class WaitHelper
  23. {
  24. #region private field
  25. private static IOverlaySplashScreenHandle _handle;
  26. private static OverlayTextPainter _overlayLabel = new OverlayTextPainterEx();
  27. private static List<string> _tips = new List<string>();
  28. private static Random _random = new Random();
  29. private static DateTime _updateTime;
  30. #endregion
  31. #region public function
  32. /// <summary>
  33. /// 显示等待窗体
  34. /// </summary>
  35. /// <param name="title">标题</param>
  36. /// <param name="caption">文本</param>
  37. /// <param name="owner">等待窗体的父窗体,默认值为激活的主程序窗体</param>
  38. public static void ShowWaitForm(string title, string caption, Form owner = null)
  39. {
  40. SplashScreenManager.ShowForm(owner, typeof(MyWaitForm), true, true, false);
  41. SplashScreenManager.Default.SetWaitFormCaption(title);//标题
  42. SplashScreenManager.Default.SetWaitFormDescription(caption);//描述
  43. }
  44. /// <summary>
  45. /// 显示等待窗体(文本固定为请稍后和加载中...)
  46. /// </summary>
  47. /// <param name="owner">等待窗体的父窗体,默认值为激活的主程序窗体</param>
  48. public static void ShowWaitForm(Form owner = null)
  49. {
  50. SplashScreenManager.ShowForm(owner, typeof(MyWaitForm), true, true, false);
  51. SplashScreenManager.Default.SetWaitFormCaption("请稍后");//标题
  52. SplashScreenManager.Default.SetWaitFormDescription("加载中...");//描述
  53. }
  54. /// <summary>
  55. /// 关闭等待窗体和程序启动画面窗体
  56. /// </summary>
  57. public static void CloseForm()
  58. {
  59. SplashScreenManager.CloseForm(false, 0, null);
  60. }
  61. /// <summary>
  62. /// 在某个control上显示半透明遮罩层
  63. /// </summary>
  64. /// <param name="owner">遮罩层覆盖的Control</param>
  65. public static void ShowOverlayForm(Control owner)
  66. {
  67. int opacity = 180;
  68. if (SystemInformation.TerminalServerSession)
  69. opacity = 255; //远程桌面(RDP)下禁用opacity,否则网络可能会卡断
  70. if (owner == null || !owner.Visible) return;
  71. _overlayLabel.Font = new Font(owner.Font.FontFamily, 18);
  72. _overlayLabel.Text = null;
  73. _handle = SplashScreenManager.ShowOverlayForm(owner, opacity: opacity, fadeIn: false, fadeOut: false, customPainter: new OverlayWindowCompositePainter(_overlayLabel));
  74. }
  75. /// <summary>
  76. /// 更新遮罩层上的文本
  77. /// </summary>
  78. /// <param name="text"></param>
  79. public static void UpdateOverlyText(string text)
  80. {
  81. _overlayLabel.Text = text;
  82. }
  83. /// <summary>
  84. /// 关闭上一次显示的半透明遮罩层
  85. /// </summary>
  86. public static void CloseOverlayForm()
  87. {
  88. if (_handle == null) return;
  89. if (!string.IsNullOrWhiteSpace(_overlayLabel.Text))
  90. {
  91. Task.Run(() =>
  92. {
  93. Thread.Sleep(1000);
  94. SplashScreenManager.CloseOverlayForm(_handle);
  95. });
  96. }
  97. else
  98. SplashScreenManager.CloseOverlayForm(_handle);
  99. }
  100. /// <summary>
  101. /// 显示程序启动画面
  102. /// </summary>
  103. public static void ShowSplashScreen(string title, string company)
  104. {
  105. SplashScreenManager.ShowForm(typeof(MySplashScreen)); //调用
  106. SplashScreenManager.Default?.SendCommand(SplashScreenCommand.UpdateTitle, title);
  107. SplashScreenManager.Default?.SendCommand(SplashScreenCommand.UpdateCompany, company);
  108. _updateTime = DateTime.Now;
  109. Task.Run(() =>
  110. {
  111. var tips = _tips.Skip(0).ToList();
  112. while (true)
  113. {
  114. while ((DateTime.Now - _updateTime).TotalMilliseconds < 2000)
  115. {
  116. Thread.Sleep(100);
  117. }
  118. var tipsIdx = _random.Next(0, tips.Count);
  119. var res = UpdateSplashMessage(_tips[tipsIdx]);
  120. if (!res) break;
  121. tips.RemoveAt(tipsIdx);
  122. if (!tips.Any()) break;
  123. }
  124. });
  125. }
  126. /// <summary>
  127. /// 更新启动画面窗体的文本消息
  128. /// </summary>
  129. /// <param name="msg"></param>
  130. /// <returns>如果启动窗体已关闭返回false,否则返回true</returns>
  131. public static bool UpdateSplashMessage(string msg)
  132. {
  133. _updateTime = DateTime.Now;
  134. SplashScreenManager.Default?.SendCommand(SplashScreenCommand.UpdateMessage, msg);
  135. if (SplashScreenManager.Default == null || !SplashScreenManager.Default.IsSplashFormVisible) return false;
  136. return true;
  137. }
  138. public static void SetSplashTips(IEnumerable<string> tips)
  139. {
  140. _tips.Clear();
  141. _tips.AddRange(tips);
  142. }
  143. public static void SetSplashTips(string tipsFile)
  144. {
  145. _tips.Clear();
  146. if (File.Exists(tipsFile))
  147. _tips.AddRange(File.ReadAllLines(tipsFile));
  148. }
  149. #endregion
  150. #region internal class
  151. class OverlayTextPainterEx : OverlayTextPainter
  152. {
  153. protected override Rectangle CalcTextBounds(OverlayLayeredWindowObjectInfoArgs drawArgs)
  154. {
  155. Size textSz = CalcTextSize(drawArgs);
  156. return textSz.AlignWith(drawArgs.Bounds).WithY(drawArgs.ImageBounds.GetCenterPoint().Y - textSz.Height / 2);
  157. }
  158. }
  159. partial class MyWaitForm : WaitForm
  160. {
  161. private Form owner;
  162. public MyWaitForm()
  163. {
  164. InitializeComponent();
  165. this.progressPanel1.AutoHeight = true;
  166. this.StartPosition = FormStartPosition.CenterParent;
  167. }
  168. #region Overrides
  169. public override void SetCaption(string caption)
  170. {
  171. base.SetCaption(caption);
  172. this.progressPanel1.Caption = caption;
  173. }
  174. public override void SetDescription(string description)
  175. {
  176. base.SetDescription(description);
  177. this.progressPanel1.Description = description;
  178. }
  179. public override void ProcessCommand(Enum cmd, object arg)
  180. {
  181. base.ProcessCommand(cmd, arg);
  182. }
  183. #endregion
  184. public enum WaitFormCommand
  185. {
  186. }
  187. public void ShowWaitForm(Form owner, string description, string caption)
  188. {
  189. SplashScreenManager.ShowForm(owner, typeof(WaitHelper), true, true, false);
  190. SplashScreenManager.Default.SetWaitFormDescription(description);//描述
  191. SplashScreenManager.Default.SetWaitFormCaption(caption);//标题
  192. }
  193. public void ShowWaitForm(Form owner)
  194. {
  195. this.owner = owner;
  196. SplashScreenManager.ShowForm(owner, typeof(WaitHelper), true, true, false);
  197. }
  198. public void CloseWaitForm()
  199. {
  200. SplashScreenManager.CloseForm(false, 0, owner);
  201. }
  202. }
  203. partial class MyWaitForm
  204. {
  205. /// <summary>
  206. /// Required designer variable.
  207. /// </summary>
  208. private System.ComponentModel.IContainer components = null;
  209. /// <summary>
  210. /// Clean up any resources being used.
  211. /// </summary>
  212. /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
  213. protected override void Dispose(bool disposing)
  214. {
  215. if (disposing && (components != null))
  216. {
  217. components.Dispose();
  218. }
  219. base.Dispose(disposing);
  220. }
  221. #region Windows Form Designer generated code
  222. /// <summary>
  223. /// Required method for Designer support - do not modify
  224. /// the contents of this method with the code editor.
  225. /// </summary>
  226. private void InitializeComponent()
  227. {
  228. this.progressPanel1 = new DevExpress.XtraWaitForm.ProgressPanel();
  229. this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
  230. this.tableLayoutPanel1.SuspendLayout();
  231. this.SuspendLayout();
  232. //
  233. // progressPanel1
  234. //
  235. this.progressPanel1.Appearance.BackColor = System.Drawing.Color.Transparent;
  236. this.progressPanel1.Appearance.Options.UseBackColor = true;
  237. this.progressPanel1.AppearanceCaption.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F);
  238. this.progressPanel1.AppearanceCaption.Options.UseFont = true;
  239. this.progressPanel1.AppearanceDescription.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F);
  240. this.progressPanel1.AppearanceDescription.Options.UseFont = true;
  241. this.progressPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
  242. this.progressPanel1.ImageHorzOffset = 20;
  243. this.progressPanel1.Location = new System.Drawing.Point(0, 17);
  244. this.progressPanel1.Margin = new System.Windows.Forms.Padding(0, 3, 0, 3);
  245. this.progressPanel1.Name = "progressPanel1";
  246. this.progressPanel1.Size = new System.Drawing.Size(246, 39);
  247. this.progressPanel1.TabIndex = 0;
  248. this.progressPanel1.Text = "progressPanel1";
  249. //
  250. // tableLayoutPanel1
  251. //
  252. this.tableLayoutPanel1.AutoSize = true;
  253. this.tableLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
  254. this.tableLayoutPanel1.BackColor = System.Drawing.Color.Transparent;
  255. this.tableLayoutPanel1.ColumnCount = 1;
  256. this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
  257. this.tableLayoutPanel1.Controls.Add(this.progressPanel1, 0, 0);
  258. this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
  259. this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
  260. this.tableLayoutPanel1.Name = "tableLayoutPanel1";
  261. this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(0, 14, 0, 14);
  262. this.tableLayoutPanel1.RowCount = 1;
  263. this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
  264. this.tableLayoutPanel1.Size = new System.Drawing.Size(246, 73);
  265. this.tableLayoutPanel1.TabIndex = 1;
  266. //
  267. // Form1
  268. //
  269. this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
  270. this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
  271. this.AutoSize = true;
  272. this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
  273. this.ClientSize = new System.Drawing.Size(246, 73);
  274. this.Controls.Add(this.tableLayoutPanel1);
  275. this.DoubleBuffered = true;
  276. this.Name = "Form1";
  277. this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
  278. this.Text = "Form1";
  279. this.tableLayoutPanel1.ResumeLayout(false);
  280. this.ResumeLayout(false);
  281. this.PerformLayout();
  282. }
  283. #endregion
  284. private DevExpress.XtraWaitForm.ProgressPanel progressPanel1;
  285. private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
  286. }
  287. partial class MySplashScreen : SplashScreen
  288. {
  289. public MySplashScreen()
  290. {
  291. InitializeComponent();
  292. this.labMsg.Text = "";
  293. peImage.Properties.Appearance.Font = new Font(peImage.Properties.Appearance.Font.FontFamily, 16);
  294. peImage.Properties.NullText = "某系统";
  295. this.labelCopyright.Text = $"Copyright © {DateTime.Now.Year} 总参第五十七研究所";
  296. }
  297. #region Overrides
  298. public override void ProcessCommand(Enum cmd, object arg)
  299. {
  300. var command = (SplashScreenCommand)cmd;
  301. base.ProcessCommand(cmd, arg);
  302. if (command == SplashScreenCommand.UpdateMessage)
  303. {
  304. this.labMsg.Text = arg.ToString();
  305. }
  306. else if (command == SplashScreenCommand.UpdateTitle)
  307. {
  308. peImage.Properties.NullText = arg?.ToString();
  309. }
  310. else if (command == SplashScreenCommand.UpdateCompany && arg != null && !string.IsNullOrWhiteSpace(arg.ToString()))
  311. {
  312. this.labelCopyright.Text = $"Copyright © {DateTime.Now.Year} {arg}";
  313. }
  314. else if (command == SplashScreenCommand.UpdateCompany && (arg == null || string.IsNullOrWhiteSpace(arg.ToString())))
  315. {
  316. this.labelCopyright.Visible = false;
  317. }
  318. }
  319. #endregion
  320. }
  321. enum SplashScreenCommand
  322. {
  323. UpdateMessage,
  324. UpdateTitle,
  325. UpdateCompany
  326. }
  327. partial class MySplashScreen
  328. {
  329. /// <summary>
  330. /// Required designer variable.
  331. /// </summary>
  332. private System.ComponentModel.IContainer components = null;
  333. /// <summary>
  334. /// Clean up any resources being used.
  335. /// </summary>
  336. /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
  337. protected override void Dispose(bool disposing)
  338. {
  339. if (disposing && (components != null))
  340. {
  341. components.Dispose();
  342. }
  343. base.Dispose(disposing);
  344. }
  345. #region Windows Form Designer generated code
  346. /// <summary>
  347. /// Required method for Designer support - do not modify
  348. /// the contents of this method with the code editor.
  349. /// </summary>
  350. private void InitializeComponent()
  351. {
  352. this.progressBarControl = new DevExpress.XtraEditors.MarqueeProgressBarControl();
  353. this.labelCopyright = new DevExpress.XtraEditors.LabelControl();
  354. this.labMsg = new DevExpress.XtraEditors.LabelControl();
  355. this.peImage = new DevExpress.XtraEditors.PictureEdit();
  356. this.tablePanel1 = new DevExpress.Utils.Layout.TablePanel();
  357. ((System.ComponentModel.ISupportInitialize)(this.progressBarControl.Properties)).BeginInit();
  358. ((System.ComponentModel.ISupportInitialize)(this.peImage.Properties)).BeginInit();
  359. ((System.ComponentModel.ISupportInitialize)(this.tablePanel1)).BeginInit();
  360. this.tablePanel1.SuspendLayout();
  361. this.SuspendLayout();
  362. //
  363. // progressBarControl
  364. //
  365. this.progressBarControl.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
  366. | System.Windows.Forms.AnchorStyles.Right)));
  367. this.progressBarControl.EditValue = 0;
  368. this.progressBarControl.Location = new System.Drawing.Point(24, 230);
  369. this.progressBarControl.Name = "progressBarControl";
  370. this.progressBarControl.Size = new System.Drawing.Size(402, 11);
  371. this.progressBarControl.TabIndex = 5;
  372. //
  373. // labelCopyright
  374. //
  375. this.labelCopyright.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder;
  376. this.tablePanel1.SetColumn(this.labelCopyright, 1);
  377. this.labelCopyright.Location = new System.Drawing.Point(191, 8);
  378. this.labelCopyright.Name = "labelCopyright";
  379. this.tablePanel1.SetRow(this.labelCopyright, 0);
  380. this.labelCopyright.Size = new System.Drawing.Size(66, 20);
  381. this.labelCopyright.TabIndex = 6;
  382. this.labelCopyright.Text = "Copyright";
  383. //
  384. // labMsg
  385. //
  386. this.labMsg.Location = new System.Drawing.Point(24, 198);
  387. this.labMsg.Margin = new System.Windows.Forms.Padding(3, 3, 3, 1);
  388. this.labMsg.Name = "labMsg";
  389. this.labMsg.Size = new System.Drawing.Size(62, 20);
  390. this.labMsg.TabIndex = 7;
  391. this.labMsg.Text = "Starting...";
  392. //
  393. // peImage
  394. //
  395. this.peImage.Dock = System.Windows.Forms.DockStyle.Top;
  396. this.peImage.Location = new System.Drawing.Point(1, 1);
  397. this.peImage.Name = "peImage";
  398. this.peImage.Properties.AllowFocused = false;
  399. this.peImage.Properties.Appearance.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(128)))), ((int)(((byte)(255)))));
  400. this.peImage.Properties.Appearance.Options.UseBackColor = true;
  401. this.peImage.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder;
  402. this.peImage.Properties.NullText = "系统名称";
  403. this.peImage.Properties.ShowEditMenuItem = DevExpress.Utils.DefaultBoolean.False;
  404. this.peImage.Properties.ShowMenu = false;
  405. this.peImage.Size = new System.Drawing.Size(448, 185);
  406. this.peImage.TabIndex = 9;
  407. //
  408. // tablePanel1
  409. //
  410. this.tablePanel1.Appearance.BackColor = System.Drawing.Color.Transparent;
  411. this.tablePanel1.Appearance.Options.UseBackColor = true;
  412. this.tablePanel1.Columns.AddRange(new DevExpress.Utils.Layout.TablePanelColumn[] {
  413. new DevExpress.Utils.Layout.TablePanelColumn(DevExpress.Utils.Layout.TablePanelEntityStyle.Relative, 1F),
  414. new DevExpress.Utils.Layout.TablePanelColumn(DevExpress.Utils.Layout.TablePanelEntityStyle.AutoSize, 0F),
  415. new DevExpress.Utils.Layout.TablePanelColumn(DevExpress.Utils.Layout.TablePanelEntityStyle.Relative, 1F)});
  416. this.tablePanel1.Controls.Add(this.labelCopyright);
  417. this.tablePanel1.Dock = System.Windows.Forms.DockStyle.Bottom;
  418. this.tablePanel1.Location = new System.Drawing.Point(1, 250);
  419. this.tablePanel1.Name = "tablePanel1";
  420. this.tablePanel1.Padding = new System.Windows.Forms.Padding(1);
  421. this.tablePanel1.Rows.AddRange(new DevExpress.Utils.Layout.TablePanelRow[] {
  422. new DevExpress.Utils.Layout.TablePanelRow(DevExpress.Utils.Layout.TablePanelEntityStyle.Relative, 1F)});
  423. this.tablePanel1.Size = new System.Drawing.Size(448, 37);
  424. this.tablePanel1.TabIndex = 10;
  425. //
  426. // SplashScreen1
  427. //
  428. this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
  429. this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
  430. this.ClientSize = new System.Drawing.Size(450, 288);
  431. this.Controls.Add(this.tablePanel1);
  432. this.Controls.Add(this.peImage);
  433. this.Controls.Add(this.labMsg);
  434. this.Controls.Add(this.progressBarControl);
  435. this.Name = "SplashScreen1";
  436. this.Padding = new System.Windows.Forms.Padding(1);
  437. this.Text = "SplashScreen1";
  438. ((System.ComponentModel.ISupportInitialize)(this.progressBarControl.Properties)).EndInit();
  439. ((System.ComponentModel.ISupportInitialize)(this.peImage.Properties)).EndInit();
  440. ((System.ComponentModel.ISupportInitialize)(this.tablePanel1)).EndInit();
  441. this.tablePanel1.ResumeLayout(false);
  442. this.tablePanel1.PerformLayout();
  443. this.ResumeLayout(false);
  444. this.PerformLayout();
  445. }
  446. #endregion
  447. private DevExpress.XtraEditors.MarqueeProgressBarControl progressBarControl;
  448. private DevExpress.XtraEditors.LabelControl labelCopyright;
  449. private DevExpress.XtraEditors.LabelControl labMsg;
  450. private DevExpress.XtraEditors.PictureEdit peImage;
  451. private DevExpress.Utils.Layout.TablePanel tablePanel1;
  452. }
  453. #endregion
  454. }
  455. }