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;
}
}
}