UCDispHalcon.xaml.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Windows;
  4. using System.Windows.Controls;
  5. namespace Plugins.Halcon.Views
  6. {
  7. /// <summary>
  8. /// HALCON 主页多画面显示控件(镜像 UCDispVm/UCDispVpp 的角色):按 RowColNumber 铺设画面框网格,
  9. /// 支持双击放大/还原。单例,供 <see cref="Engines.HalconEngine"/> 与 HALCON 图像显示插件访问。
  10. /// </summary>
  11. public partial class UCDispHalcon : UserControl
  12. {
  13. private static readonly Lazy<UCDispHalcon> _instance = new Lazy<UCDispHalcon>(CreateInstance);
  14. public static UCDispHalcon Instance => _instance.Value;
  15. /// <summary>
  16. /// WPF 控件必须在 STA(UI) 线程创建。「Halcon图像显示」节点在流程执行的后台(MTA)线程首次访问 Instance 时
  17. /// (例如当前主页引擎不是 Halcon、GetMainView 从未在 UI 线程创建过它),若直接 new 会抛
  18. /// “调用线程必须为 STA”。故不在 UI 线程时经 Dispatcher 切到 UI 线程创建。
  19. /// </summary>
  20. private static UCDispHalcon CreateInstance()
  21. {
  22. var app = System.Windows.Application.Current;
  23. if (app != null && !app.Dispatcher.CheckAccess())
  24. return app.Dispatcher.Invoke(() => new UCDispHalcon());
  25. return new UCDispHalcon();
  26. }
  27. /// <summary>当前画面框集合(下标 = 画面序号-1)。</summary>
  28. public List<HalconWindow> halconWindow { get; } = new List<HalconWindow>();
  29. private int[] _rowCol = new[] { 0, 1 };
  30. private HalconWindow _maximized;
  31. public UCDispHalcon()
  32. {
  33. InitializeComponent();
  34. }
  35. /// <summary>{画面总数, 排列方式}:arrange 1=水平最优行列,2=垂直最优行列;总数0=清空。</summary>
  36. public int[] RowColNumber
  37. {
  38. get => _rowCol;
  39. set
  40. {
  41. _rowCol = value ?? new[] { 0, 1 };
  42. RebuildFrames();
  43. }
  44. }
  45. private void RebuildFrames()
  46. {
  47. if (!Dispatcher.CheckAccess()) { Dispatcher.Invoke(new Action(RebuildFrames)); return; }
  48. // 复位放大态
  49. MaxGrid.Children.Clear();
  50. MaxGrid.Visibility = Visibility.Collapsed;
  51. _maximized = null;
  52. RootGrid.Children.Clear();
  53. RootGrid.RowDefinitions.Clear();
  54. RootGrid.ColumnDefinitions.Clear();
  55. RootGrid.Visibility = Visibility.Visible;
  56. halconWindow.Clear();
  57. int count = _rowCol.Length > 0 ? _rowCol[0] : 0;
  58. int arrange = _rowCol.Length > 1 ? _rowCol[1] : 1;
  59. if (count <= 0) return;
  60. int cols = (int)Math.Ceiling(Math.Sqrt(count));
  61. if (cols < 1) cols = 1;
  62. if (arrange == 2)
  63. {
  64. int rows = (int)Math.Ceiling(Math.Sqrt(count));
  65. if (rows < 1) rows = 1;
  66. cols = (int)Math.Ceiling((double)count / rows);
  67. if (cols < 1) cols = 1;
  68. }
  69. int rowCount = (count + cols - 1) / cols;
  70. for (int c = 0; c < cols; c++) RootGrid.ColumnDefinitions.Add(new ColumnDefinition());
  71. for (int r = 0; r < rowCount; r++) RootGrid.RowDefinitions.Add(new RowDefinition());
  72. for (int i = 0; i < count; i++)
  73. {
  74. var w = new HalconWindow(i + 1);
  75. Grid.SetRow(w, i / cols);
  76. Grid.SetColumn(w, i % cols);
  77. // 数量除不尽时,最后一个跨列填满本行剩余位置(不补空白格)
  78. if (i == count - 1)
  79. {
  80. int remain = cols - (i % cols);
  81. if (remain > 1) Grid.SetColumnSpan(w, remain);
  82. }
  83. w.MouseDouble += OnFrameDoubleClick;
  84. RootGrid.Children.Add(w);
  85. halconWindow.Add(w);
  86. }
  87. }
  88. private void OnFrameDoubleClick(HalconWindow window, int number)
  89. {
  90. if (!Dispatcher.CheckAccess()) { Dispatcher.Invoke(() => OnFrameDoubleClick(window, number)); return; }
  91. if (_maximized == window) return;
  92. window.MouseDouble -= OnFrameDoubleClick;
  93. RootGrid.Children.Remove(window);
  94. RootGrid.Visibility = Visibility.Collapsed;
  95. MaxGrid.Children.Clear();
  96. MaxGrid.Children.Add(window);
  97. MaxGrid.Visibility = Visibility.Visible;
  98. window.MouseDouble += OnMaxDoubleClick;
  99. _maximized = window;
  100. }
  101. private void OnMaxDoubleClick(HalconWindow window, int number)
  102. {
  103. if (!Dispatcher.CheckAccess()) { Dispatcher.Invoke(() => OnMaxDoubleClick(window, number)); return; }
  104. window.MouseDouble -= OnMaxDoubleClick;
  105. MaxGrid.Children.Clear();
  106. MaxGrid.Visibility = Visibility.Collapsed;
  107. // Grid.Row/Column 附加属性随元素保留,重新加回即落回原位
  108. RootGrid.Children.Add(window);
  109. RootGrid.Visibility = Visibility.Visible;
  110. window.MouseDouble += OnFrameDoubleClick;
  111. _maximized = null;
  112. }
  113. }
  114. }