LB_SmartVision/Forms/Pages/ProcessPage/AllProcessesPage.cs
@@ -9,7 +9,12 @@
    public partial class AllProcessesPage : TabPage
    {
        public ObservableConcurrentDictionary<string, ProcessControl> dicProcessControls = new ObservableConcurrentDictionary<string, ProcessControl>();
        // 保存控件原始布局(尺寸+位置),用于恢复矩阵布局
        private Dictionary<string, (Size Size, Point Location)> _originalControlLayouts = new Dictionary<string, (Size, Point)>();
        // 标记是否处于全屏状态
        private bool _isFullScreen = false;
        // 记录当前全屏的控件标题
        private string _fullScreenControlTitle = string.Empty;
        /// <summary>
        /// 实例化流程界面
        /// </summary>
@@ -49,8 +54,16 @@
                {
                    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);
                    }
                }
            }
@@ -61,45 +74,142 @@
                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 processControl = dicProcessControls[title];
                        processControl.Size
                            = new Size(this.controlsPanel.Size.Width / enableLayout
                            , this.controlsPanel.Size.Height);
                        processControl.Location
                            = new Point(processControl.Size.Width * index, 0);
                        if (GlobalVar.dicProcesses[name].GetImage(GlobalVar.dicLayout[i], out _, out HObject RecordImage))
                            dicProcessControls[title].ShowHoImage(RecordImage);
                        // 复用已有控件,更新尺寸和位置
                        processControl = dicProcessControls[title];
                        processControl.Size = originalSize;
                        processControl.Location = originalLocation;
                        processControl.Visible = true;
                        // 解绑旧事件,避免重复绑定
                        processControl.event_MouseDoubleClick -= ProcessControl_DoubleClick;
                    }
                    else
                    {
                        ProcessControl processControl = new ProcessControl(GlobalVar.dicLayout[i]);
                        processControl.Size
                            = new Size(this.controlsPanel.Size.Width / enableLayout
                            , this.controlsPanel.Size.Height);
                        processControl.Location
                            = new Point(processControl.Size.Width * index, 0);
                        // 新建控件,按矩阵布局赋值尺寸和位置
                        processControl = new ProcessControl(GlobalVar.dicLayout[i]);
                        processControl.Size = originalSize;
                        processControl.Location = originalLocation;
                        processControl.SetTitle(title);
                        // 添加到字典和面板
                        dicProcessControls.TryAdd(title, processControl);
                        this.controlsPanel.Controls.Add(processControl);
                        if (GlobalVar.dicProcesses[name].GetImage(GlobalVar.dicLayout[i], out _, out HObject RecordImage))
                            dicProcessControls[title].ShowHoImage(RecordImage);
                    }
                    index++;
                    // 绑定双击事件(左键)和鼠标按下事件(右键双击)
                    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 双击事件处理(全屏/恢复布局)
        /// <summary>
        /// 左键双击事件:全屏显示当前ProcessControl
        /// </summary>
        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(); // 确保在最上层
                }
            }
        }
        /// <summary>
        /// 恢复矩阵布局(复用InitVisionUI的核心逻辑,避免代码重复)
        /// </summary>
        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
    }
}