using HalconDotNet; using LB_SmartVision.Tool; using System.Data; using System.Runtime.InteropServices; using System.Xml.Linq; namespace LB_SmartVision.Forms.Pages.ProcessPage { public partial class AllProcessesPage : TabPage { public ObservableConcurrentDictionary dicProcessControls = new ObservableConcurrentDictionary(); // 保存控件原始布局(尺寸+位置),用于恢复矩阵布局 private Dictionary _originalControlLayouts = new Dictionary(); // 标记是否处于全屏状态 private bool _isFullScreen = false; // 记录当前全屏的控件标题 private string _fullScreenControlTitle = string.Empty; /// /// 实例化流程界面 /// /// public AllProcessesPage() { InitializeComponent(); Name = "AllProcessesPage"; Text = "主界面"; //this.Font = new Font("Microsoft YaHei UI", 16F, FontStyle.Regular, GraphicsUnit.Point, 0); this.BackColor = Color.FromArgb(32, 41, 50); InitVisionUI(); this.Invalidated += AllProcessesPage_Invalidated; } private void AllProcessesPage_Invalidated(object? sender, InvalidateEventArgs e) => InitVisionUI(); public void InitVisionUI() { List keys = dicProcessControls.Keys.ToList(); foreach (var title in keys) { bool isExist = false; foreach (var layout in GlobalVar.dicLayout.Values) { if (layout.Title == title) { isExist = true; break; } } if (!isExist) { if (dicProcessControls.ContainsKey(title)) { // 移除前先解绑事件,避免内存泄漏 var control = dicProcessControls[title]; control.event_MouseDoubleClick -= ProcessControl_DoubleClick; this.controlsPanel.Controls.Remove(dicProcessControls[title]); dicProcessControls.TryRemove(title, out _); // 移除原始布局记录 if (_originalControlLayouts.ContainsKey(title)) _originalControlLayouts.Remove(title); } } } int enableLayout = 0; foreach (var layout in GlobalVar.dicLayout.Values) { if (GlobalVar.dicProcesses.ContainsKey(layout.ProcessName)) enableLayout++; } //总行数,向下取整 int matrixRows = (int)Math.Floor(Math.Sqrt(enableLayout)); if (enableLayout == 0 || matrixRows == 0) { _originalControlLayouts.Clear(); _isFullScreen = false; _fullScreenControlTitle = string.Empty; // 无启用布局时直接返回,避免除零错误 return; } //总列数,向上取整 int matrixColumns = (int)Math.Ceiling((double)enableLayout / matrixRows); int index = 0; // 计算每个ProcessControl的尺寸(按行列均分面板大小) int controlWidth = this.controlsPanel.Width / matrixColumns; int controlHeight = this.controlsPanel.Height / matrixRows; // 每次重构布局时清空原始记录 _originalControlLayouts.Clear(); for (int i = 0; i < GlobalVar.dicLayout.Count; i++) { string name = GlobalVar.dicLayout[i].ProcessName; string title = GlobalVar.dicLayout[i].Title; if (GlobalVar.dicProcesses.ContainsKey(name)) { // 计算当前控件的行列索引 int colIndex = index % matrixColumns; // 列索引(0,1,0,1...) int rowIndex = index / matrixColumns; // 行索引(0,0,1,1...) // 计算原始位置和尺寸(矩阵布局) Size originalSize = new Size(controlWidth, controlHeight); Point originalLocation = new Point(colIndex * controlWidth, rowIndex * controlHeight); ProcessControl processControl; if (dicProcessControls.ContainsKey(title)) { // 复用已有控件,更新尺寸和位置 processControl = dicProcessControls[title]; processControl.Size = originalSize; processControl.Location = originalLocation; processControl.Visible = true; // 解绑旧事件,避免重复绑定 processControl.event_MouseDoubleClick -= ProcessControl_DoubleClick; } else { // 新建控件,按矩阵布局赋值尺寸和位置 processControl = new ProcessControl(GlobalVar.dicLayout[i]); processControl.Size = originalSize; processControl.Location = originalLocation; processControl.SetTitle(title); // 添加到字典和面板 dicProcessControls.TryAdd(title, processControl); this.controlsPanel.Controls.Add(processControl); } // 绑定双击事件(左键)和鼠标按下事件(右键双击) processControl.event_MouseDoubleClick += ProcessControl_DoubleClick; // 保存原始布局(矩阵状态) _originalControlLayouts[title] = (originalSize, originalLocation); // 更新图片 if (GlobalVar.dicProcesses[name].GetImage(GlobalVar.dicLayout[i], out _, out HObject recordImage)) dicProcessControls[title].ShowHoImage(recordImage); index++; // 仅启用的布局索引递增 } } // 如果当前是全屏状态,恢复矩阵布局后重置状态 if (_isFullScreen) { _isFullScreen = false; _fullScreenControlTitle = string.Empty; } } #region 双击事件处理(全屏/恢复布局) /// /// 左键双击事件:全屏显示当前ProcessControl /// private void ProcessControl_DoubleClick(object sender, EventArgs e) { if (_isFullScreen) { RestoreMatrixLayout(); return; } var targetControl = sender as ProcessControl; if (targetControl == null || string.IsNullOrEmpty(targetControl.Title)) return; // 记录全屏的控件标题 _fullScreenControlTitle = targetControl.Title; _isFullScreen = true; // 隐藏所有其他ProcessControl,仅显示目标控件 foreach (var kvp in dicProcessControls) { if (kvp.Key != _fullScreenControlTitle) { kvp.Value.Visible = false; } else { // 目标控件设为面板大小,位置(0,0)(全屏) kvp.Value.Size = this.controlsPanel.Size; kvp.Value.Location = new Point(0, 0); kvp.Value.BringToFront(); // 确保在最上层 } } } /// /// 恢复矩阵布局(复用InitVisionUI的核心逻辑,避免代码重复) /// private void RestoreMatrixLayout() { // 1. 重置全屏状态 _isFullScreen = false; _fullScreenControlTitle = string.Empty; // 2. 恢复所有控件的原始尺寸、位置和可见性 foreach (var kvp in dicProcessControls) { string title = kvp.Key; var control = kvp.Value; // 3. 从原始布局字典中恢复尺寸和位置 if (_originalControlLayouts.TryGetValue(title, out var originalLayout)) { control.Size = originalLayout.Size; control.Location = originalLayout.Location; } control.Visible = true; // 显示控件 } } #endregion } }