| | |
| | | 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> |
| | |
| | | |
| | | Name = "AllProcessesPage"; |
| | | Text = "主界面"; |
| | | //this.Font = new Font("Microsoft YaHei UI", 16F, FontStyle.Regular, GraphicsUnit.Point, 0); |
| | | this.BackColor = Color.FromArgb(32, 41, 50); |
| | | |
| | | InitVisionUI(); |
| | |
| | | |
| | | public void InitVisionUI() |
| | | { |
| | | this.controlsPanel.Dock = DockStyle.Fill; |
| | | List<string> keys = dicProcessControls.Keys.ToList(); |
| | | |
| | | foreach (var title in keys) |
| | |
| | | { |
| | | 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); |
| | | } |
| | | } |
| | | } |
| | |
| | | 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 processControl = dicProcessControls[title]; |
| | | processControl.Size |
| | | = new Size(this.controlsPanel.Size.Width / enableLayout |
| | | , this.controlsPanel.Size.Height-40); |
| | | 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 |
| | | } |
| | | } |