using System; using System.Collections.Generic; using System.Windows; using System.Windows.Controls; namespace Plugins.Halcon.Views { /// /// HALCON 主页多画面显示控件(镜像 UCDispVm/UCDispVpp 的角色):按 RowColNumber 铺设画面框网格, /// 支持双击放大/还原。单例,供 与 HALCON 图像显示插件访问。 /// public partial class UCDispHalcon : UserControl { private static readonly Lazy _instance = new Lazy(CreateInstance); public static UCDispHalcon Instance => _instance.Value; /// /// WPF 控件必须在 STA(UI) 线程创建。「Halcon图像显示」节点在流程执行的后台(MTA)线程首次访问 Instance 时 /// (例如当前主页引擎不是 Halcon、GetMainView 从未在 UI 线程创建过它),若直接 new 会抛 /// “调用线程必须为 STA”。故不在 UI 线程时经 Dispatcher 切到 UI 线程创建。 /// private static UCDispHalcon CreateInstance() { var app = System.Windows.Application.Current; if (app != null && !app.Dispatcher.CheckAccess()) return app.Dispatcher.Invoke(() => new UCDispHalcon()); return new UCDispHalcon(); } /// 当前画面框集合(下标 = 画面序号-1)。 public List halconWindow { get; } = new List(); private int[] _rowCol = new[] { 0, 1 }; private HalconWindow _maximized; public UCDispHalcon() { InitializeComponent(); } /// {画面总数, 排列方式}:arrange 1=水平最优行列,2=垂直最优行列;总数0=清空。 public int[] RowColNumber { get => _rowCol; set { _rowCol = value ?? new[] { 0, 1 }; RebuildFrames(); } } private void RebuildFrames() { if (!Dispatcher.CheckAccess()) { Dispatcher.Invoke(new Action(RebuildFrames)); return; } // 复位放大态 MaxGrid.Children.Clear(); MaxGrid.Visibility = Visibility.Collapsed; _maximized = null; RootGrid.Children.Clear(); RootGrid.RowDefinitions.Clear(); RootGrid.ColumnDefinitions.Clear(); RootGrid.Visibility = Visibility.Visible; halconWindow.Clear(); int count = _rowCol.Length > 0 ? _rowCol[0] : 0; int arrange = _rowCol.Length > 1 ? _rowCol[1] : 1; if (count <= 0) return; int cols = (int)Math.Ceiling(Math.Sqrt(count)); if (cols < 1) cols = 1; if (arrange == 2) { int rows = (int)Math.Ceiling(Math.Sqrt(count)); if (rows < 1) rows = 1; cols = (int)Math.Ceiling((double)count / rows); if (cols < 1) cols = 1; } int rowCount = (count + cols - 1) / cols; for (int c = 0; c < cols; c++) RootGrid.ColumnDefinitions.Add(new ColumnDefinition()); for (int r = 0; r < rowCount; r++) RootGrid.RowDefinitions.Add(new RowDefinition()); for (int i = 0; i < count; i++) { var w = new HalconWindow(i + 1); Grid.SetRow(w, i / cols); Grid.SetColumn(w, i % cols); // 数量除不尽时,最后一个跨列填满本行剩余位置(不补空白格) if (i == count - 1) { int remain = cols - (i % cols); if (remain > 1) Grid.SetColumnSpan(w, remain); } w.MouseDouble += OnFrameDoubleClick; RootGrid.Children.Add(w); halconWindow.Add(w); } } private void OnFrameDoubleClick(HalconWindow window, int number) { if (!Dispatcher.CheckAccess()) { Dispatcher.Invoke(() => OnFrameDoubleClick(window, number)); return; } if (_maximized == window) return; window.MouseDouble -= OnFrameDoubleClick; RootGrid.Children.Remove(window); RootGrid.Visibility = Visibility.Collapsed; MaxGrid.Children.Clear(); MaxGrid.Children.Add(window); MaxGrid.Visibility = Visibility.Visible; window.MouseDouble += OnMaxDoubleClick; _maximized = window; } private void OnMaxDoubleClick(HalconWindow window, int number) { if (!Dispatcher.CheckAccess()) { Dispatcher.Invoke(() => OnMaxDoubleClick(window, number)); return; } window.MouseDouble -= OnMaxDoubleClick; MaxGrid.Children.Clear(); MaxGrid.Visibility = Visibility.Collapsed; // Grid.Row/Column 附加属性随元素保留,重新加回即落回原位 RootGrid.Children.Add(window); RootGrid.Visibility = Visibility.Visible; window.MouseDouble += OnFrameDoubleClick; _maximized = null; } } }