init commit

This commit is contained in:
zhaowei.huang
2026-06-14 11:19:15 +08:00
parent e79a3815a5
commit c8e540d272
174 changed files with 60830 additions and 39 deletions
@@ -0,0 +1,263 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SimpleCore.Library;
namespace StandardScene.ExtendDevice.ButtonBox
{
/// <summary>
/// 按钮状态枚举
/// </summary>
public enum ButtonState
{
/// <summary>
/// 未按下
/// </summary>
Released = 0,
/// <summary>
/// 已按下
/// </summary>
Pressed = 1,
/// <summary>
/// 未知状态
/// </summary>
Unknown = 2
}
/// <summary>
/// 按钮盒状态枚举
/// </summary>
public enum ButtonBoxState
{
/// <summary>
/// 离线
/// </summary>
Offline = 0,
/// <summary>
/// 在线
/// </summary>
Online = 1,
/// <summary>
/// 连接中
/// </summary>
Connecting = 2,
/// <summary>
/// 错误
/// </summary>
Error = 3
}
/// <summary>
/// 基础按钮盒类,包含状态机
/// </summary>
public abstract class BasicButtonBox
{
/// <summary>
/// 按钮盒索引
/// </summary>
public int Index { get; set; }
/// <summary>
/// IP地址
/// </summary>
public string Ip { get; set; } = string.Empty;
/// <summary>
/// 端口
/// </summary>
public int Port { get; set; }
/// <summary>
/// 按钮盒状态
/// </summary>
public ButtonBoxState State { get; protected set; } = ButtonBoxState.Offline;
/// <summary>
/// 是否在线
/// </summary>
public bool IsOnline => State == ButtonBoxState.Online;
/// <summary>
/// 按钮状态字典,键为按钮索引
/// </summary>
public Dictionary<int, ButtonState> ButtonStates { get; protected set; } = new Dictionary<int, ButtonState>();
/// <summary>
/// 按钮配置信息字典,键为按钮索引
/// </summary>
public Dictionary<int, ButtonModel> ButtonConfigs { get; protected set; } = new Dictionary<int, ButtonModel>();
/// <summary>
/// 按钮动作执行后清零对应寄存器:默认空实现,具体盒型(如 Azowie)按需重写。
/// 用于解耦 ButtonMission 对具体盒型的 is 判断,便于驱动外移至卫星 dll。
/// </summary>
public virtual void ClearButtonRegister(int buttonIndex)
{
}
/// <summary>
/// 最后更新时间
/// </summary>
public DateTime LastUpdateTime { get; protected set; } = DateTime.Now;
/// <summary>
/// 错误信息
/// </summary>
public string ErrorMessage { get; protected set; } = string.Empty;
/// <summary>
/// 更新按钮盒状态
/// </summary>
public virtual void UpdateState(ButtonBoxState newState, string errorMessage = "")
{
State = newState;
ErrorMessage = errorMessage;
LastUpdateTime = DateTime.Now;
}
/// <summary>
/// 更新按钮状态
/// </summary>
/// <param name="buttonIndex">按钮索引</param>
/// <param name="state">按钮状态</param>
public virtual void UpdateButtonState(int buttonIndex, ButtonState state)
{
bool hadPrev = ButtonStates.TryGetValue(buttonIndex, out var previous);
if (hadPrev && previous == state)
return;
ButtonStates[buttonIndex] = state;
if (hadPrev)
Diagnosis.Post($"按钮盒{Index}_按钮{buttonIndex}:状态变更为{state}", "ButtonBox", false);
LastUpdateTime = DateTime.Now;
}
/// <summary>
/// 获取按钮状态
/// </summary>
/// <param name="buttonIndex">按钮索引</param>
/// <returns>按钮状态,如果不存在则返回Unknown</returns>
public virtual ButtonState GetButtonState(int buttonIndex)
{
return ButtonStates.TryGetValue(buttonIndex, out var state) ? state : ButtonState.Unknown;
}
/// <summary>
/// 初始化按钮状态
/// </summary>
/// <param name="buttonIndices">按钮索引列表</param>
public virtual void InitializeButtons(List<int> buttonIndices)
{
ButtonStates.Clear();
foreach (var index in buttonIndices)
{
ButtonStates[index] = ButtonState.Released;
}
}
/// <summary>
/// 初始化按钮配置信息
/// </summary>
/// <param name="buttonConfigs">按钮配置列表</param>
public virtual void InitializeButtonConfigs(List<ButtonModel> buttonConfigs)
{
ButtonConfigs.Clear();
if (buttonConfigs != null)
{
foreach (var config in buttonConfigs)
{
ButtonConfigs[config.Index] = new ButtonModel
{
Index = config.Index,
TriggerMission = config.TriggerMission,
TriggerMethod = config.TriggerMethod,
TriggerMethodParams = config.TriggerMethodParams,
TriggerState = config.TriggerState,
TriggerDelay = config.TriggerDelay
};
}
}
}
/// <summary>
/// 更新按钮配置信息
/// </summary>
/// <param name="buttonConfigs">按钮配置列表</param>
public virtual void UpdateButtonConfigs(List<ButtonModel> buttonConfigs)
{
if (buttonConfigs == null)
{
ButtonConfigs.Clear();
return;
}
// 创建配置字典
var configDict = buttonConfigs.ToDictionary(b => b.Index);
// 删除配置中不存在的按钮
var toRemove = ButtonConfigs.Keys.Where(k => !configDict.ContainsKey(k)).ToList();
foreach (var key in toRemove)
{
ButtonConfigs.Remove(key);
}
// 添加或更新按钮配置
foreach (var config in buttonConfigs)
{
ButtonConfigs[config.Index] = new ButtonModel
{
Index = config.Index,
TriggerMission = config.TriggerMission,
TriggerMethod = config.TriggerMethod,
TriggerMethodParams = config.TriggerMethodParams,
TriggerState = config.TriggerState,
TriggerDelay = config.TriggerDelay
};
}
}
/// <summary>
/// 获取按钮配置信息
/// </summary>
/// <param name="buttonIndex">按钮索引</param>
/// <returns>按钮配置信息,如果不存在则返回null</returns>
public virtual ButtonModel GetButtonConfig(int buttonIndex)
{
return ButtonConfigs.TryGetValue(buttonIndex, out var config) ? config : null;
}
/// <summary>
/// 连接按钮盒
/// </summary>
public virtual void Connect()
{
UpdateState(ButtonBoxState.Connecting);
}
/// <summary>
/// 断开连接
/// </summary>
public virtual void Disconnect()
{
UpdateState(ButtonBoxState.Offline);
}
/// <summary>
/// 当与此按钮盒绑定的业务方法执行完成后触发的回调。
/// 子类可重写以实现按钮灯反馈、蜂鸣等效果。
/// </summary>
/// <param name="buttonConfig">触发本次调用的按钮配置</param>
/// <param name="isSuccess">业务方法是否执行成功</param>
public virtual void OnActionExecuted(ButtonModel buttonConfig, bool isSuccess)
{
// 基类默认不做任何事,由具体实现按需要重写
}
}
}
@@ -0,0 +1,608 @@
namespace StandardScene.ExtendDevice.ButtonBox
{
partial class ButtonBoxManager
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.buttonBoxListView = new System.Windows.Forms.ListView();
this.columnHeaderBoxIndex = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderIp = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderPort = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.groupBoxButtonBox = new System.Windows.Forms.GroupBox();
this.btnSaveButtonBox = new System.Windows.Forms.Button();
this.btnDeleteButtonBox = new System.Windows.Forms.Button();
this.btnAddButtonBox = new System.Windows.Forms.Button();
this.labelType = new System.Windows.Forms.Label();
this.comboBoxType = new System.Windows.Forms.ComboBox();
this.labelBoxIndex = new System.Windows.Forms.Label();
this.textBoxBoxIndex = new System.Windows.Forms.TextBox();
this.labelPort = new System.Windows.Forms.Label();
this.textBoxPort = new System.Windows.Forms.TextBox();
this.labelIp = new System.Windows.Forms.Label();
this.textBoxIp = new System.Windows.Forms.TextBox();
this.buttonListView = new System.Windows.Forms.ListView();
this.columnHeaderButtonIndex = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderTriggerMission = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderTriggerMethod = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderTriggerMethodParams = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderTriggerState = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderTriggerDelay = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.groupBoxButton = new System.Windows.Forms.GroupBox();
this.btnSaveButton = new System.Windows.Forms.Button();
this.btnDeleteButton = new System.Windows.Forms.Button();
this.btnAddButton = new System.Windows.Forms.Button();
this.labelTriggerMethodParams = new System.Windows.Forms.Label();
this.textBoxTriggerMethodParams = new System.Windows.Forms.TextBox();
this.labelTriggerMethod = new System.Windows.Forms.Label();
this.textBoxTriggerMethod = new System.Windows.Forms.TextBox();
this.labelTriggerMission = new System.Windows.Forms.Label();
this.textBoxTriggerMission = new System.Windows.Forms.TextBox();
this.labelButtonIndex = new System.Windows.Forms.Label();
this.textBoxButtonIndex = new System.Windows.Forms.TextBox();
this.labelTriggerState = new System.Windows.Forms.Label();
this.comboBoxTriggerState = new System.Windows.Forms.ComboBox();
this.labelTriggerDelay = new System.Windows.Forms.Label();
this.textBoxTriggerDelay = new System.Windows.Forms.TextBox();
this.labelTitle = new System.Windows.Forms.Label();
this.groupBoxButtonBox.SuspendLayout();
this.groupBoxButton.SuspendLayout();
this.SuspendLayout();
//
// buttonBoxListView
//
this.buttonBoxListView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.buttonBoxListView.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.buttonBoxListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeaderBoxIndex,
this.columnHeaderIp,
this.columnHeaderPort,
this.columnHeaderType});
this.buttonBoxListView.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.buttonBoxListView.FullRowSelect = true;
this.buttonBoxListView.GridLines = true;
this.buttonBoxListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
this.buttonBoxListView.HideSelection = false;
this.buttonBoxListView.Location = new System.Drawing.Point(15, 55);
this.buttonBoxListView.MultiSelect = false;
this.buttonBoxListView.Name = "buttonBoxListView";
this.buttonBoxListView.OwnerDraw = true;
this.buttonBoxListView.Size = new System.Drawing.Size(450, 290);
this.buttonBoxListView.TabIndex = 0;
this.buttonBoxListView.UseCompatibleStateImageBehavior = false;
this.buttonBoxListView.View = System.Windows.Forms.View.Details;
this.buttonBoxListView.SelectedIndexChanged += new System.EventHandler(this.buttonBoxListView_SelectedIndexChanged);
//
// columnHeaderBoxIndex
//
this.columnHeaderBoxIndex.Text = "编码";
this.columnHeaderBoxIndex.Width = 70;
//
// columnHeaderIp
//
this.columnHeaderIp.Text = "IP地址";
this.columnHeaderIp.Width = 130;
//
// columnHeaderPort
//
this.columnHeaderPort.Text = "端口";
this.columnHeaderPort.Width = 90;
//
// columnHeaderType
//
this.columnHeaderType.Text = "类型";
this.columnHeaderType.Width = 140;
//
// groupBoxButtonBox
//
this.groupBoxButtonBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.groupBoxButtonBox.Controls.Add(this.btnSaveButtonBox);
this.groupBoxButtonBox.Controls.Add(this.btnDeleteButtonBox);
this.groupBoxButtonBox.Controls.Add(this.btnAddButtonBox);
this.groupBoxButtonBox.Controls.Add(this.labelType);
this.groupBoxButtonBox.Controls.Add(this.comboBoxType);
this.groupBoxButtonBox.Controls.Add(this.labelBoxIndex);
this.groupBoxButtonBox.Controls.Add(this.textBoxBoxIndex);
this.groupBoxButtonBox.Controls.Add(this.labelPort);
this.groupBoxButtonBox.Controls.Add(this.textBoxPort);
this.groupBoxButtonBox.Controls.Add(this.labelIp);
this.groupBoxButtonBox.Controls.Add(this.textBoxIp);
this.groupBoxButtonBox.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.groupBoxButtonBox.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(68)))), ((int)(((byte)(68)))), ((int)(((byte)(68)))));
this.groupBoxButtonBox.Location = new System.Drawing.Point(15, 360);
this.groupBoxButtonBox.Name = "groupBoxButtonBox";
this.groupBoxButtonBox.Padding = new System.Windows.Forms.Padding(12, 10, 12, 12);
this.groupBoxButtonBox.Size = new System.Drawing.Size(450, 250);
this.groupBoxButtonBox.TabIndex = 1;
this.groupBoxButtonBox.TabStop = false;
this.groupBoxButtonBox.Text = "按钮盒信息";
//
// btnSaveButtonBox
//
this.btnSaveButtonBox.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(122)))), ((int)(((byte)(204)))));
this.btnSaveButtonBox.FlatAppearance.BorderSize = 0;
this.btnSaveButtonBox.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(92)))), ((int)(((byte)(153)))));
this.btnSaveButtonBox.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(102)))), ((int)(((byte)(170)))));
this.btnSaveButtonBox.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnSaveButtonBox.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnSaveButtonBox.ForeColor = System.Drawing.Color.White;
this.btnSaveButtonBox.Location = new System.Drawing.Point(330, 200);
this.btnSaveButtonBox.Name = "btnSaveButtonBox";
this.btnSaveButtonBox.Size = new System.Drawing.Size(100, 38);
this.btnSaveButtonBox.TabIndex = 10;
this.btnSaveButtonBox.Text = "保存";
this.btnSaveButtonBox.UseVisualStyleBackColor = false;
this.btnSaveButtonBox.Click += new System.EventHandler(this.btnSaveButtonBox_Click);
//
// btnDeleteButtonBox
//
this.btnDeleteButtonBox.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(53)))), ((int)(((byte)(69)))));
this.btnDeleteButtonBox.FlatAppearance.BorderSize = 0;
this.btnDeleteButtonBox.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(165)))), ((int)(((byte)(40)))), ((int)(((byte)(52)))));
this.btnDeleteButtonBox.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(187)))), ((int)(((byte)(45)))), ((int)(((byte)(59)))));
this.btnDeleteButtonBox.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnDeleteButtonBox.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnDeleteButtonBox.ForeColor = System.Drawing.Color.White;
this.btnDeleteButtonBox.Location = new System.Drawing.Point(220, 200);
this.btnDeleteButtonBox.Name = "btnDeleteButtonBox";
this.btnDeleteButtonBox.Size = new System.Drawing.Size(100, 38);
this.btnDeleteButtonBox.TabIndex = 9;
this.btnDeleteButtonBox.Text = "删除";
this.btnDeleteButtonBox.UseVisualStyleBackColor = false;
this.btnDeleteButtonBox.Click += new System.EventHandler(this.btnDeleteButtonBox_Click);
//
// btnAddButtonBox
//
this.btnAddButtonBox.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(167)))), ((int)(((byte)(69)))));
this.btnAddButtonBox.FlatAppearance.BorderSize = 0;
this.btnAddButtonBox.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(125)))), ((int)(((byte)(52)))));
this.btnAddButtonBox.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(33)))), ((int)(((byte)(136)))), ((int)(((byte)(56)))));
this.btnAddButtonBox.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnAddButtonBox.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnAddButtonBox.ForeColor = System.Drawing.Color.White;
this.btnAddButtonBox.Location = new System.Drawing.Point(110, 200);
this.btnAddButtonBox.Name = "btnAddButtonBox";
this.btnAddButtonBox.Size = new System.Drawing.Size(100, 38);
this.btnAddButtonBox.TabIndex = 8;
this.btnAddButtonBox.Text = "添加";
this.btnAddButtonBox.UseVisualStyleBackColor = false;
this.btnAddButtonBox.Click += new System.EventHandler(this.btnAddButtonBox_Click);
//
// labelType
//
this.labelType.AutoSize = true;
this.labelType.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelType.Location = new System.Drawing.Point(28, 168);
this.labelType.Name = "labelType";
this.labelType.Size = new System.Drawing.Size(65, 24);
this.labelType.TabIndex = 7;
this.labelType.Text = "类型:";
//
// comboBoxType
//
this.comboBoxType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxType.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.comboBoxType.FormattingEnabled = true;
this.comboBoxType.Location = new System.Drawing.Point(110, 165);
this.comboBoxType.Name = "comboBoxType";
this.comboBoxType.Size = new System.Drawing.Size(320, 32);
this.comboBoxType.TabIndex = 6;
//
// labelBoxIndex
//
this.labelBoxIndex.AutoSize = true;
this.labelBoxIndex.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelBoxIndex.Location = new System.Drawing.Point(28, 48);
this.labelBoxIndex.Name = "labelBoxIndex";
this.labelBoxIndex.Size = new System.Drawing.Size(65, 24);
this.labelBoxIndex.TabIndex = 1;
this.labelBoxIndex.Text = "编码:";
//
// textBoxBoxIndex
//
this.textBoxBoxIndex.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxBoxIndex.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxBoxIndex.Location = new System.Drawing.Point(110, 45);
this.textBoxBoxIndex.Name = "textBoxBoxIndex";
this.textBoxBoxIndex.Size = new System.Drawing.Size(320, 30);
this.textBoxBoxIndex.TabIndex = 0;
//
// labelIp
//
this.labelIp.AutoSize = true;
this.labelIp.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelIp.Location = new System.Drawing.Point(18, 88);
this.labelIp.Name = "labelIp";
this.labelIp.Size = new System.Drawing.Size(85, 24);
this.labelIp.TabIndex = 3;
this.labelIp.Text = "IP地址:";
//
// textBoxIp
//
this.textBoxIp.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxIp.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxIp.Location = new System.Drawing.Point(110, 85);
this.textBoxIp.Name = "textBoxIp";
this.textBoxIp.Size = new System.Drawing.Size(320, 30);
this.textBoxIp.TabIndex = 2;
this.textBoxIp.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(255)))));
//
// labelPort
//
this.labelPort.AutoSize = true;
this.labelPort.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelPort.Location = new System.Drawing.Point(28, 128);
this.labelPort.Name = "labelPort";
this.labelPort.Size = new System.Drawing.Size(65, 24);
this.labelPort.TabIndex = 5;
this.labelPort.Text = "端口:";
//
// textBoxPort
//
this.textBoxPort.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxPort.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxPort.Location = new System.Drawing.Point(110, 125);
this.textBoxPort.Name = "textBoxPort";
this.textBoxPort.Size = new System.Drawing.Size(320, 30);
this.textBoxPort.TabIndex = 4;
//
// buttonListView
//
this.buttonListView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.buttonListView.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.buttonListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeaderButtonIndex,
this.columnHeaderTriggerState,
this.columnHeaderTriggerDelay,
this.columnHeaderTriggerMission,
this.columnHeaderTriggerMethod,
this.columnHeaderTriggerMethodParams});
this.buttonListView.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.buttonListView.FullRowSelect = true;
this.buttonListView.GridLines = true;
this.buttonListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
this.buttonListView.HideSelection = false;
this.buttonListView.Location = new System.Drawing.Point(483, 55);
this.buttonListView.MultiSelect = false;
this.buttonListView.Name = "buttonListView";
this.buttonListView.OwnerDraw = true;
this.buttonListView.Size = new System.Drawing.Size(700, 290);
this.buttonListView.TabIndex = 2;
this.buttonListView.UseCompatibleStateImageBehavior = false;
this.buttonListView.View = System.Windows.Forms.View.Details;
this.buttonListView.SelectedIndexChanged += new System.EventHandler(this.buttonListView_SelectedIndexChanged);
//
// columnHeaderButtonIndex
//
this.columnHeaderButtonIndex.Text = "编码";
this.columnHeaderButtonIndex.Width = 70;
//
// columnHeaderTriggerState
//
this.columnHeaderTriggerState.Text = "触发状态";
this.columnHeaderTriggerState.Width = 100;
//
// columnHeaderTriggerDelay
//
this.columnHeaderTriggerDelay.Text = "触发延迟";
this.columnHeaderTriggerDelay.Width = 90;
//
// columnHeaderTriggerMission
//
this.columnHeaderTriggerMission.Text = "触发任务";
this.columnHeaderTriggerMission.Width = 140;
//
// columnHeaderTriggerMethod
//
this.columnHeaderTriggerMethod.Text = "触发方法";
this.columnHeaderTriggerMethod.Width = 140;
//
// columnHeaderTriggerMethodParams
//
this.columnHeaderTriggerMethodParams.Text = "方法参数";
this.columnHeaderTriggerMethodParams.Width = 160;
//
// groupBoxButton
//
this.groupBoxButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.groupBoxButton.Controls.Add(this.btnSaveButton);
this.groupBoxButton.Controls.Add(this.btnDeleteButton);
this.groupBoxButton.Controls.Add(this.btnAddButton);
this.groupBoxButton.Controls.Add(this.labelTriggerMethodParams);
this.groupBoxButton.Controls.Add(this.textBoxTriggerMethodParams);
this.groupBoxButton.Controls.Add(this.labelTriggerMethod);
this.groupBoxButton.Controls.Add(this.textBoxTriggerMethod);
this.groupBoxButton.Controls.Add(this.labelTriggerMission);
this.groupBoxButton.Controls.Add(this.textBoxTriggerMission);
this.groupBoxButton.Controls.Add(this.labelButtonIndex);
this.groupBoxButton.Controls.Add(this.textBoxButtonIndex);
this.groupBoxButton.Controls.Add(this.labelTriggerState);
this.groupBoxButton.Controls.Add(this.comboBoxTriggerState);
this.groupBoxButton.Controls.Add(this.labelTriggerDelay);
this.groupBoxButton.Controls.Add(this.textBoxTriggerDelay);
this.groupBoxButton.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.groupBoxButton.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(68)))), ((int)(((byte)(68)))), ((int)(((byte)(68)))));
this.groupBoxButton.Location = new System.Drawing.Point(483, 360);
this.groupBoxButton.Name = "groupBoxButton";
this.groupBoxButton.Padding = new System.Windows.Forms.Padding(12, 10, 12, 12);
this.groupBoxButton.Size = new System.Drawing.Size(700, 250);
this.groupBoxButton.TabIndex = 3;
this.groupBoxButton.TabStop = false;
this.groupBoxButton.Text = "按钮信息";
//
// btnSaveButton
//
this.btnSaveButton.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(122)))), ((int)(((byte)(204)))));
this.btnSaveButton.FlatAppearance.BorderSize = 0;
this.btnSaveButton.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(92)))), ((int)(((byte)(153)))));
this.btnSaveButton.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(102)))), ((int)(((byte)(170)))));
this.btnSaveButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnSaveButton.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnSaveButton.ForeColor = System.Drawing.Color.White;
this.btnSaveButton.Location = new System.Drawing.Point(580, 180);
this.btnSaveButton.Name = "btnSaveButton";
this.btnSaveButton.Size = new System.Drawing.Size(100, 38);
this.btnSaveButton.TabIndex = 13;
this.btnSaveButton.Text = "保存";
this.btnSaveButton.UseVisualStyleBackColor = false;
this.btnSaveButton.Click += new System.EventHandler(this.btnSaveButton_Click);
//
// btnDeleteButton
//
this.btnDeleteButton.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(53)))), ((int)(((byte)(69)))));
this.btnDeleteButton.FlatAppearance.BorderSize = 0;
this.btnDeleteButton.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(165)))), ((int)(((byte)(40)))), ((int)(((byte)(52)))));
this.btnDeleteButton.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(187)))), ((int)(((byte)(45)))), ((int)(((byte)(59)))));
this.btnDeleteButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnDeleteButton.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnDeleteButton.ForeColor = System.Drawing.Color.White;
this.btnDeleteButton.Location = new System.Drawing.Point(470, 180);
this.btnDeleteButton.Name = "btnDeleteButton";
this.btnDeleteButton.Size = new System.Drawing.Size(100, 38);
this.btnDeleteButton.TabIndex = 12;
this.btnDeleteButton.Text = "删除";
this.btnDeleteButton.UseVisualStyleBackColor = false;
this.btnDeleteButton.Click += new System.EventHandler(this.btnDeleteButton_Click);
//
// btnAddButton
//
this.btnAddButton.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(167)))), ((int)(((byte)(69)))));
this.btnAddButton.FlatAppearance.BorderSize = 0;
this.btnAddButton.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(125)))), ((int)(((byte)(52)))));
this.btnAddButton.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(33)))), ((int)(((byte)(136)))), ((int)(((byte)(56)))));
this.btnAddButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnAddButton.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnAddButton.ForeColor = System.Drawing.Color.White;
this.btnAddButton.Location = new System.Drawing.Point(360, 180);
this.btnAddButton.Name = "btnAddButton";
this.btnAddButton.Size = new System.Drawing.Size(100, 38);
this.btnAddButton.TabIndex = 11;
this.btnAddButton.Text = "添加";
this.btnAddButton.UseVisualStyleBackColor = false;
this.btnAddButton.Click += new System.EventHandler(this.btnAddButton_Click);
//
// labelTriggerMethodParams
//
this.labelTriggerMethodParams.AutoSize = true;
this.labelTriggerMethodParams.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelTriggerMethodParams.Location = new System.Drawing.Point(370, 128);
this.labelTriggerMethodParams.Name = "labelTriggerMethodParams";
this.labelTriggerMethodParams.Size = new System.Drawing.Size(103, 24);
this.labelTriggerMethodParams.TabIndex = 11;
this.labelTriggerMethodParams.Text = "方法参数:";
//
// textBoxTriggerMethodParams
//
this.textBoxTriggerMethodParams.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxTriggerMethodParams.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxTriggerMethodParams.Location = new System.Drawing.Point(490, 125);
this.textBoxTriggerMethodParams.Name = "textBoxTriggerMethodParams";
this.textBoxTriggerMethodParams.Size = new System.Drawing.Size(190, 30);
this.textBoxTriggerMethodParams.TabIndex = 10;
//
// labelTriggerState
//
this.labelTriggerState.AutoSize = true;
this.labelTriggerState.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelTriggerState.Location = new System.Drawing.Point(370, 48);
this.labelTriggerState.Name = "labelTriggerState";
this.labelTriggerState.Size = new System.Drawing.Size(103, 24);
this.labelTriggerState.TabIndex = 3;
this.labelTriggerState.Text = "触发状态:";
//
// comboBoxTriggerState
//
this.comboBoxTriggerState.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxTriggerState.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.comboBoxTriggerState.FormattingEnabled = true;
this.comboBoxTriggerState.Location = new System.Drawing.Point(490, 45);
this.comboBoxTriggerState.Name = "comboBoxTriggerState";
this.comboBoxTriggerState.Size = new System.Drawing.Size(190, 32);
this.comboBoxTriggerState.TabIndex = 2;
//
// labelTriggerDelay
//
this.labelTriggerDelay.AutoSize = true;
this.labelTriggerDelay.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelTriggerDelay.Location = new System.Drawing.Point(28, 88);
this.labelTriggerDelay.Name = "labelTriggerDelay";
this.labelTriggerDelay.Size = new System.Drawing.Size(103, 24);
this.labelTriggerDelay.TabIndex = 5;
this.labelTriggerDelay.Text = "触发延迟:";
//
// textBoxTriggerDelay
//
this.textBoxTriggerDelay.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxTriggerDelay.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxTriggerDelay.Location = new System.Drawing.Point(150, 85);
this.textBoxTriggerDelay.Name = "textBoxTriggerDelay";
this.textBoxTriggerDelay.Size = new System.Drawing.Size(200, 30);
this.textBoxTriggerDelay.TabIndex = 4;
//
// labelTriggerMethod
//
this.labelTriggerMethod.AutoSize = true;
this.labelTriggerMethod.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelTriggerMethod.Location = new System.Drawing.Point(28, 128);
this.labelTriggerMethod.Name = "labelTriggerMethod";
this.labelTriggerMethod.Size = new System.Drawing.Size(103, 24);
this.labelTriggerMethod.TabIndex = 9;
this.labelTriggerMethod.Text = "触发方法:";
//
// textBoxTriggerMethod
//
this.textBoxTriggerMethod.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxTriggerMethod.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxTriggerMethod.Location = new System.Drawing.Point(150, 125);
this.textBoxTriggerMethod.Name = "textBoxTriggerMethod";
this.textBoxTriggerMethod.Size = new System.Drawing.Size(200, 30);
this.textBoxTriggerMethod.TabIndex = 8;
//
// labelTriggerMission
//
this.labelTriggerMission.AutoSize = true;
this.labelTriggerMission.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelTriggerMission.Location = new System.Drawing.Point(370, 88);
this.labelTriggerMission.Name = "labelTriggerMission";
this.labelTriggerMission.Size = new System.Drawing.Size(103, 24);
this.labelTriggerMission.TabIndex = 7;
this.labelTriggerMission.Text = "触发任务:";
//
// textBoxTriggerMission
//
this.textBoxTriggerMission.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxTriggerMission.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxTriggerMission.Location = new System.Drawing.Point(490, 85);
this.textBoxTriggerMission.Name = "textBoxTriggerMission";
this.textBoxTriggerMission.Size = new System.Drawing.Size(190, 30);
this.textBoxTriggerMission.TabIndex = 6;
//
// labelButtonIndex
//
this.labelButtonIndex.AutoSize = true;
this.labelButtonIndex.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelButtonIndex.Location = new System.Drawing.Point(28, 48);
this.labelButtonIndex.Name = "labelButtonIndex";
this.labelButtonIndex.Size = new System.Drawing.Size(65, 24);
this.labelButtonIndex.TabIndex = 1;
this.labelButtonIndex.Text = "编码:";
//
// textBoxButtonIndex
//
this.textBoxButtonIndex.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxButtonIndex.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxButtonIndex.Location = new System.Drawing.Point(150, 45);
this.textBoxButtonIndex.Name = "textBoxButtonIndex";
this.textBoxButtonIndex.Size = new System.Drawing.Size(200, 30);
this.textBoxButtonIndex.TabIndex = 0;
//
// labelTitle
//
this.labelTitle.AutoSize = true;
this.labelTitle.Font = new System.Drawing.Font("微软雅黑", 16F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelTitle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(51)))), ((int)(((byte)(51)))), ((int)(((byte)(51)))));
this.labelTitle.Location = new System.Drawing.Point(15, 12);
this.labelTitle.Name = "labelTitle";
this.labelTitle.Size = new System.Drawing.Size(150, 42);
this.labelTitle.TabIndex = 4;
this.labelTitle.Text = "按钮盒管理";
//
// ButtonBoxManager
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(245)))), ((int)(((byte)(245)))), ((int)(((byte)(247)))));
this.ClientSize = new System.Drawing.Size(1200, 620);
this.Controls.Add(this.labelTitle);
this.Controls.Add(this.groupBoxButton);
this.Controls.Add(this.buttonListView);
this.Controls.Add(this.groupBoxButtonBox);
this.Controls.Add(this.buttonBoxListView);
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.MinimumSize = new System.Drawing.Size(1200, 620);
this.Name = "ButtonBoxManager";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "按钮盒管理";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ButtonBoxManager_FormClosing);
this.Load += new System.EventHandler(this.ButtonBoxManager_Load);
this.groupBoxButtonBox.ResumeLayout(false);
this.groupBoxButtonBox.PerformLayout();
this.groupBoxButton.ResumeLayout(false);
this.groupBoxButton.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ListView buttonBoxListView;
private System.Windows.Forms.ColumnHeader columnHeaderBoxIndex;
private System.Windows.Forms.ColumnHeader columnHeaderIp;
private System.Windows.Forms.ColumnHeader columnHeaderPort;
private System.Windows.Forms.ColumnHeader columnHeaderType;
private System.Windows.Forms.GroupBox groupBoxButtonBox;
private System.Windows.Forms.TextBox textBoxIp;
private System.Windows.Forms.Label labelIp;
private System.Windows.Forms.Label labelPort;
private System.Windows.Forms.TextBox textBoxPort;
private System.Windows.Forms.Label labelBoxIndex;
private System.Windows.Forms.TextBox textBoxBoxIndex;
private System.Windows.Forms.Label labelType;
private System.Windows.Forms.ComboBox comboBoxType;
private System.Windows.Forms.Button btnAddButtonBox;
private System.Windows.Forms.Button btnDeleteButtonBox;
private System.Windows.Forms.Button btnSaveButtonBox;
private System.Windows.Forms.ListView buttonListView;
private System.Windows.Forms.ColumnHeader columnHeaderButtonIndex;
private System.Windows.Forms.ColumnHeader columnHeaderTriggerMission;
private System.Windows.Forms.ColumnHeader columnHeaderTriggerMethod;
private System.Windows.Forms.ColumnHeader columnHeaderTriggerMethodParams;
private System.Windows.Forms.GroupBox groupBoxButton;
private System.Windows.Forms.Label labelButtonIndex;
private System.Windows.Forms.TextBox textBoxButtonIndex;
private System.Windows.Forms.Label labelTriggerMission;
private System.Windows.Forms.TextBox textBoxTriggerMission;
private System.Windows.Forms.Label labelTriggerMethod;
private System.Windows.Forms.TextBox textBoxTriggerMethod;
private System.Windows.Forms.Label labelTriggerMethodParams;
private System.Windows.Forms.TextBox textBoxTriggerMethodParams;
private System.Windows.Forms.Label labelTriggerState;
private System.Windows.Forms.ComboBox comboBoxTriggerState;
private System.Windows.Forms.Label labelTriggerDelay;
private System.Windows.Forms.TextBox textBoxTriggerDelay;
private System.Windows.Forms.ColumnHeader columnHeaderTriggerState;
private System.Windows.Forms.ColumnHeader columnHeaderTriggerDelay;
private System.Windows.Forms.Button btnAddButton;
private System.Windows.Forms.Button btnDeleteButton;
private System.Windows.Forms.Button btnSaveButton;
private System.Windows.Forms.Label labelTitle;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StandardScene.ExtendDevice.ButtonBox
{
/// <summary>
/// 按钮盒模型
/// </summary>
public class ButtonBoxModel
{
public string Ip { get; set; } = string.Empty;
public int Port { get; set; } = 0;
public int Index { get; set; } = 0;
public string Type { get; set; } = string.Empty;
public List<ButtonModel> Buttons { get; set; } = new List<ButtonModel>();
}
/// <summary>
/// 按钮模型
/// </summary>
public class ButtonModel
{
public int Index { get; set; } = 0;
public string TriggerMission { get; set; } = string.Empty;
public string TriggerMethod { get; set; } = string.Empty;
public string TriggerMethodParams { get; set; } = string.Empty;
public string TriggerState { get; set; } = string.Empty;
public ushort TriggerDelay { get; set; } = 0;
}
}
@@ -0,0 +1,806 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using LessokajiWeaverUtilities.MagicAttributes;
using LessokajiWeaverUtilities.Utilities;
using SimpleLite;
using SimpleLite.RCS;
using SimpleLite.RCS.CarTypes;
using SimpleCore;
using SimpleCore.Library;
using StandardScene;
using StandardScene.Utils;
namespace StandardScene.ExtendDevice.ButtonBox
{
[MissionType(Name = "按钮进程")]
[I18N.DocumentTranslation(Name = "ButtonMission",locale = "en")]
public class ButtonMission:Mission
{
private const string DataFileName = "ButtonBoxConfig.json";
private string _dataFilePath;
/// <summary>
/// 当前所有按钮盒实例列表
/// </summary>
private List<BasicButtonBox> _buttonBoxes = new List<BasicButtonBox>();
/// <summary>
/// 用于管理异步循环的取消令牌源
/// </summary>
private CancellationTokenSource _cancellationTokenSource;
/// <summary>
/// 保存监控配置与状态的后台任务,便于关闭时等待
/// </summary>
private Task _configTask;
private Task _stateTask;
/// <summary>
/// 同步锁,用于保护按钮盒列表的并发访问
/// </summary>
private readonly object _syncLock = new object();
[MethodMember(Name = "启动进程")]
[I18N.DocumentTranslation(Name = "Start Mission", locale = "en")]
public override void Execute()
{
// 设置数据文件路径
_dataFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, DataFileName);
// 如果已经启动,先停止之前的循环
StopInternalAsync().GetAwaiter().GetResult();
// 创建新的取消令牌源
_cancellationTokenSource = new CancellationTokenSource();
// 启动异步循环
var token = _cancellationTokenSource.Token;
_configTask = Task.Run(async () => await MonitorButtonBoxConfigAsync(token), token);
_stateTask = Task.Run(async () => await MonitorButtonStatesAsync(token), token);
status.status = "Running";
}
/// <summary>
/// 异步监控按钮盒配置文件
/// </summary>
private async Task MonitorButtonBoxConfigAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
try
{
// 读取配置文件
var configButtonBoxes = LoadButtonBoxConfig();
// 同步按钮盒列表
SyncButtonBoxes(configButtonBoxes);
// 等待10秒
await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken);
}
catch (OperationCanceledException)
{
// 正常取消,退出循环
break;
}
catch (Exception ex)
{
// 记录错误,但继续运行
Diagnosis.Log($"按钮盒配置监控错误: {ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
// 发生错误时等待5秒后重试
try
{
await Task.Delay(TimeSpan.FromSeconds(5), cancellationToken);
}
catch (OperationCanceledException)
{
break;
}
}
}
}
/// <summary>
/// 停止监控任务
/// </summary>
[MethodMember(Name = "停止进程")]
[I18N.DocumentTranslation(Name = "Stop Mission", locale = "en")]
public void Stop()
{
StopInternalAsync().GetAwaiter().GetResult();
status.status = "/";
}
/// <summary>
/// 取消并释放当前的取消令牌源
/// </summary>
private async Task StopInternalAsync()
{
var cts = Interlocked.Exchange(ref _cancellationTokenSource, null);
var configTask = Interlocked.Exchange(ref _configTask, null);
var stateTask = Interlocked.Exchange(ref _stateTask, null);
if (cts == null && configTask == null && stateTask == null)
{
return;
}
try
{
cts?.Cancel();
}
catch (ObjectDisposedException)
{
// 已释放,忽略
}
var runningTasks = new[] { configTask, stateTask }
.Where(t => t != null)
.ToArray();
if (runningTasks.Length > 0)
{
var aggregateTask = Task.WhenAll(runningTasks);
var timeoutTask = Task.Delay(TimeSpan.FromSeconds(5));
var completedTask = await Task.WhenAny(aggregateTask, timeoutTask).ConfigureAwait(false);
if (completedTask == timeoutTask)
{
Diagnosis.Log("停止按钮监控任务超时", "ButtonMission", true);
}
else
{
try
{
await aggregateTask.ConfigureAwait(false);
}
catch (Exception ex)
{
Diagnosis.Log($"停止按钮监控任务时发生异常: {ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
}
}
}
cts?.Dispose();
DisconnectAllButtonBoxes();
}
/// <summary>
/// 断开所有按钮盒连接
/// </summary>
private void DisconnectAllButtonBoxes()
{
List<BasicButtonBox> snapshot;
lock (_syncLock)
{
snapshot = _buttonBoxes.ToList();
}
foreach (var box in snapshot)
{
try
{
box.Disconnect();
}
catch (Exception ex)
{
Diagnosis.Log($"停止按钮盒失败: Index={box.Index}, Error={ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
}
}
}
/// <summary>
/// 监控按钮状态,用于触发按钮动作
/// </summary>
private async Task MonitorButtonStatesAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
try
{
List<(BasicButtonBox Box, ButtonModel Config)> snapshot;
lock (_syncLock)
{
snapshot = _buttonBoxes
.SelectMany(box => box.ButtonConfigs.Values.Select(cfg => (Box: box, Config: cfg)))
.ToList();
}
foreach (var (box, config) in snapshot)
{
if (box == null || config == null)
{
continue;
}
if (string.IsNullOrWhiteSpace(config.TriggerMission) ||
string.IsNullOrWhiteSpace(config.TriggerMethod))
{
continue;
}
var desiredState = ButtonState.Pressed;
if (!string.IsNullOrWhiteSpace(config.TriggerState) &&
Enum.TryParse(config.TriggerState, out ButtonState parsedState))
{
desiredState = parsedState;
}
var currentState = box.GetButtonState(config.Index);
bool isActive = currentState == desiredState&&box.IsOnline;
int delay = config.TriggerDelay;
if (delay <= 0)
{
delay = 1;
}
int uniqueId = unchecked((box.Index << 16) ^ config.Index);
LadderLogic.TriggerOnce(isActive, delay*1000, () =>
{
ExecuteButtonAction(config, box);
}, uniqueId);
}
}
catch (OperationCanceledException)
{
break;
}
catch (Exception ex)
{
Diagnosis.Log($"按钮状态监控错误: {ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
}
try
{
await Task.Delay(TimeSpan.FromMilliseconds(500), cancellationToken);
}
catch (OperationCanceledException)
{
break;
}
}
}
/// <summary>
/// 加载按钮盒配置文件
/// </summary>
private List<ButtonBoxModel> LoadButtonBoxConfig()
{
try
{
if (File.Exists(_dataFilePath))
{
var jsonContent = File.ReadAllText(_dataFilePath, Encoding.UTF8);
if (!string.IsNullOrWhiteSpace(jsonContent))
{
var buttonBoxes = jsonContent.JsonTo<List<ButtonBoxModel>>();
return buttonBoxes ?? new List<ButtonBoxModel>();
}
}
}
catch (Exception ex)
{
Diagnosis.Log($"加载按钮盒配置文件失败: {ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
}
return new List<ButtonBoxModel>();
}
/// <summary>
/// 同步按钮盒列表,根据配置文件进行增删改
/// </summary>
private void SyncButtonBoxes(List<ButtonBoxModel> configButtonBoxes)
{
var boxesToAdd = new List<ButtonBoxModel>();
lock (_syncLock)
{
// 创建配置中的按钮盒索引字典,用于快速查找
var configDict = configButtonBoxes.ToDictionary(b => b.Index);
// 创建当前按钮盒索引字典
var currentDict = _buttonBoxes.ToDictionary(b => b.Index);
// 1. 删除:在配置中不存在的按钮盒
var toRemove = _buttonBoxes.Where(b => !configDict.ContainsKey(b.Index)).ToList();
foreach (var buttonBox in toRemove)
{
try
{
// 断开连接
buttonBox.Disconnect();
_buttonBoxes.Remove(buttonBox);
Diagnosis.Post($"删除按钮盒: Index={buttonBox.Index}, IP={buttonBox.Ip}", "ButtonMission", true);
}
catch (Exception ex)
{
Diagnosis.Log($"删除按钮盒失败: {ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
}
}
// 2. 添加和修改:遍历配置中的按钮盒
foreach (var configBox in configButtonBoxes)
{
if (currentDict.TryGetValue(configBox.Index, out var existingBox))
{
// 修改:检查是否需要更新
if (ShouldUpdateButtonBox(existingBox, configBox))
{
try
{
UpdateButtonBox(existingBox, configBox);
Diagnosis.Post($"更新按钮盒: Index={configBox.Index}, IP={configBox.Ip}, Type={configBox.Type}", "ButtonMission", true);
}
catch (Exception ex)
{
Diagnosis.Log($"更新按钮盒失败: {ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
}
}
}
else
{
boxesToAdd.Add(configBox);
}
}
}
foreach (var configBox in boxesToAdd)
{
try
{
var newBox = CreateButtonBoxInstance(configBox);
if (newBox != null)
{
lock (_syncLock)
{
_buttonBoxes.Add(newBox);
}
Diagnosis.Post($"添加按钮盒: Index={configBox.Index}, IP={configBox.Ip}, Type={configBox.Type}", "ButtonMission", true);
}
else
{
Diagnosis.Log($"无法创建按钮盒实例: Index={configBox.Index}, Type={configBox.Type}", "ButtonMission", true);
}
}
catch (Exception ex)
{
Diagnosis.Log($"添加按钮盒失败: {ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
}
}
}
/// <summary>
/// 判断是否需要更新按钮盒
/// </summary>
private bool ShouldUpdateButtonBox(BasicButtonBox existingBox, ButtonBoxModel configBox)
{
// 检查基本属性是否变更
if (existingBox.Ip != configBox.Ip
|| existingBox.Port != configBox.Port
|| existingBox.GetType().Name != configBox.Type)
{
return true;
}
// 检查按钮信息是否变更
return HasButtonConfigsChanged(existingBox, configBox);
}
/// <summary>
/// 检查按钮配置信息是否变更
/// </summary>
private bool HasButtonConfigsChanged(BasicButtonBox existingBox, ButtonBoxModel configBox)
{
var configButtons = configBox.Buttons ?? new List<ButtonModel>();
var configDict = configButtons.ToDictionary(b => b.Index);
var existingDict = existingBox.ButtonConfigs;
// 检查按钮数量是否变化
if (existingDict.Count != configDict.Count)
{
return true;
}
// 检查每个按钮的配置是否变化
foreach (var configButton in configButtons)
{
if (!existingDict.TryGetValue(configButton.Index, out var existingButton))
{
// 新增了按钮
return true;
}
// 检查按钮配置是否变化
if (existingButton.TriggerMission != configButton.TriggerMission
|| existingButton.TriggerMethod != configButton.TriggerMethod
|| existingButton.TriggerMethodParams != configButton.TriggerMethodParams
|| existingButton.TriggerState != configButton.TriggerState
|| existingButton.TriggerDelay != configButton.TriggerDelay)
{
return true;
}
}
// 检查是否有按钮被删除
foreach (var existingKey in existingDict.Keys)
{
if (!configDict.ContainsKey(existingKey))
{
return true;
}
}
return false;
}
/// <summary>
/// 更新按钮盒属性
/// </summary>
private void UpdateButtonBox(BasicButtonBox buttonBox, ButtonBoxModel configBox)
{
// 如果类型改变,需要重新创建实例
if (buttonBox.GetType().Name != configBox.Type)
{
// 断开旧连接
buttonBox.Disconnect();
// 从列表中移除
_buttonBoxes.Remove(buttonBox);
// 创建新实例
var newBox = CreateButtonBoxInstance(configBox);
if (newBox != null)
{
_buttonBoxes.Add(newBox);
}
}
else
{
// 只更新属性
bool needReconnect = buttonBox.Ip != configBox.Ip || buttonBox.Port != configBox.Port;
buttonBox.Ip = configBox.Ip;
buttonBox.Port = configBox.Port;
// 更新按钮配置信息
buttonBox.UpdateButtonConfigs(configBox.Buttons);
// 初始化按钮状态(基于配置中的按钮索引)
var buttonIndices = configBox.Buttons?.Select(b => b.Index).ToList() ?? new List<int>();
buttonBox.InitializeButtons(buttonIndices);
// 如果IP或端口改变,需要重新连接
if (needReconnect)
{
buttonBox.Disconnect();
buttonBox.Connect();
}
}
}
/// <summary>
/// 通过类型字符串创建按钮盒实例
/// </summary>
private BasicButtonBox CreateButtonBoxInstance(ButtonBoxModel configBox)
{
if (string.IsNullOrWhiteSpace(configBox.Type))
{
return null;
}
try
{
// 获取当前命名空间下所有继承自BasicButtonBox的类
// 跨程序集发现:按钮盒具体类型可能位于卫星插件 dllStandardScene.Devices.ButtonBox),
// 用内核同款全域类型发现替代仅扫当前程序集的 GetExecutingAssembly。
var buttonBoxType = SimpleLite.Utils.UiTypeDiscovery.AllTypes()
.FirstOrDefault(t => t.IsClass
&& !t.IsAbstract
&& t.Namespace == typeof(BasicButtonBox).Namespace
&& t.IsSubclassOf(typeof(BasicButtonBox))
&& t.Name == configBox.Type);
if (buttonBoxType == null)
{
Diagnosis.Log($"未找到按钮盒类型: {configBox.Type}", "ButtonMission", true);
return null;
}
// 使用反射创建实例
var instance = (BasicButtonBox)Activator.CreateInstance(buttonBoxType);
// 设置属性
instance.Index = configBox.Index;
instance.Ip = configBox.Ip;
instance.Port = configBox.Port;
// 初始化按钮配置信息
instance.InitializeButtonConfigs(configBox.Buttons);
// 初始化按钮状态(基于配置中的按钮索引)
var buttonIndices = configBox.Buttons?.Select(b => b.Index).ToList() ?? new List<int>();
instance.InitializeButtons(buttonIndices);
// 自动连接
instance.Connect();
return instance;
}
catch (Exception ex)
{
Diagnosis.Log($"创建按钮盒实例失败: Type={configBox.Type}, Error={ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
return null;
}
}
/// <summary>
/// 获取当前所有按钮盒实例(只读)
/// </summary>
public IReadOnlyList<BasicButtonBox> GetButtonBoxes()
{
lock (_syncLock)
{
return _buttonBoxes.ToList().AsReadOnly();
}
}
/// <summary>
/// 执行按钮动作(在独立线程中异步执行,避免阻塞按钮监控循环)
/// </summary>
private void ExecuteButtonAction(ButtonModel buttonConfig, BasicButtonBox buttonBox)
{
Task.Run(() => ExecuteButtonActionInternal(buttonConfig, buttonBox));
}
/// <summary>
/// 实际执行业务方法的内部逻辑,包含成功/失败反馈。
/// </summary>
private void ExecuteButtonActionInternal(ButtonModel buttonConfig, BasicButtonBox buttonBox)
{
var success = false;
try
{
// 按钮动作执行后清零对应按钮寄存器(具体盒型按需重写,默认空实现)
buttonBox.ClearButtonRegister(buttonConfig.Index);
if (string.IsNullOrWhiteSpace(buttonConfig.TriggerMission) ||
string.IsNullOrWhiteSpace(buttonConfig.TriggerMethod))
{
// 配置不完整,直接反馈失败
Diagnosis.Log("按钮配置缺少 TriggerMission 或 TriggerMethod,无法执行动作", "ButtonMission", true);
return;
}
var mission = SimpleProject.proj?.Missions?
.FirstOrDefault(m => m.GetType().Name == buttonConfig.TriggerMission || m.name == buttonConfig.TriggerMission);
if (mission == null)
{
Diagnosis.Log($"未找到触发任务: {buttonConfig.TriggerMission}", "ButtonMission", true);
return;
}
var method = mission.GetType().GetMethod(buttonConfig.TriggerMethod,
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
if (method == null)
{
Diagnosis.Log($"任务 {buttonConfig.TriggerMission} 中未找到方法 {buttonConfig.TriggerMethod}", "ButtonMission", true);
return;
}
var parameters = ParseMethodParameters(buttonConfig.TriggerMethodParams, method);
if (method.IsStatic)
{
var result = method.Invoke(null, parameters);
success = HandleMethodResult(result);
}
else
{
var result = method.Invoke(mission, parameters);
success = HandleMethodResult(result);
}
}
catch (Exception ex)
{
Diagnosis.Log($"执行按钮动作失败: {ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
}
finally
{
// 业务方法执行完成后,回调按钮盒进行反馈(如灯光、蜂鸣等)
try
{
buttonBox.OnActionExecuted(buttonConfig, success);
}
catch (Exception feedbackEx)
{
Diagnosis.Log($"按钮盒执行反馈失败: {ExceptionFormatter.FormatEx(feedbackEx)}", "ButtonMission", true);
}
}
}
/// <summary>
/// 处理反射调用结果:支持 Task/Task&lt;bool&gt; 等异步返回类型。
/// 返回 true 表示执行成功。
/// </summary>
private bool HandleMethodResult(object result)
{
try
{
switch (result)
{
case null:
return true;
case Task<bool> tb:
return tb.GetAwaiter().GetResult();
case Task t:
t.GetAwaiter().GetResult();
return true;
case bool b:
return b;
default:
return true;
}
}
catch (Exception ex)
{
Diagnosis.Log($"按钮动作方法异步执行失败: {ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
return false;
}
}
/// <summary>
/// 解析方法参数
/// </summary>
private object[] ParseMethodParameters(string paramsStr, MethodInfo methodInfo)
{
var paramInfos = methodInfo.GetParameters();
if (paramInfos.Length == 0)
{
return Array.Empty<object>();
}
if (string.IsNullOrWhiteSpace(paramsStr))
{
return paramInfos.Select(p => p.HasDefaultValue ? p.DefaultValue : GetDefaultValue(p.ParameterType)).ToArray();
}
try
{
var paramStrings = paramsStr.Split(',');
var parameters = new List<object>();
for (int i = 0; i < paramInfos.Length; i++)
{
var paramInfo = paramInfos[i];
var paramType = paramInfo.ParameterType;
if (i < paramStrings.Length)
{
var trimmed = paramStrings[i].Trim();
parameters.Add(ConvertParameter(trimmed, paramType));
}
else
{
parameters.Add(paramInfo.HasDefaultValue ? paramInfo.DefaultValue : GetDefaultValue(paramType));
}
}
return parameters.ToArray();
}
catch (Exception ex)
{
Diagnosis.Log($"解析按钮参数失败: {ExceptionFormatter.FormatEx(ex)}", "ButtonMission", true);
return paramInfos.Select(p => p.HasDefaultValue ? p.DefaultValue : GetDefaultValue(p.ParameterType)).ToArray();
}
}
/// <summary>
/// 转换参数
/// </summary>
private object ConvertParameter(string value, Type targetType)
{
if (targetType == typeof(string))
{
return value;
}
if (targetType == typeof(int) || targetType == typeof(int?))
{
return int.TryParse(value, out int result) ? result : (targetType == typeof(int?) ? (int?)null : 0);
}
if (targetType == typeof(double) || targetType == typeof(double?))
{
return double.TryParse(value, out double result) ? result : (targetType == typeof(double?) ? (double?)null : 0d);
}
if (targetType == typeof(float) || targetType == typeof(float?))
{
return float.TryParse(value, out float result) ? result : (targetType == typeof(float?) ? (float?)null : 0f);
}
if (targetType == typeof(bool) || targetType == typeof(bool?))
{
return bool.TryParse(value, out bool result) ? result : (targetType == typeof(bool?) ? (bool?)null : false);
}
if (targetType.IsEnum)
{
try
{
return Enum.Parse(targetType, value, true);
}
catch
{
return Enum.GetValues(targetType).GetValue(0);
}
}
return value;
}
/// <summary>
/// 获取类型默认值
/// </summary>
private object GetDefaultValue(Type type)
{
if (type.IsValueType)
{
return Activator.CreateInstance(type);
}
return null;
}
/// <summary>
/// 打开按钮盒管理界面
/// </summary>
[MethodMember(Name = "打开管理界面")]
[I18N.DocumentTranslation(Name = "Open Manager", locale = "en")]
public static void OpenViewer()
{
try
{
var manager = ButtonBoxManager.Instance;
// 确保窗体没有被销毁
if (manager.IsDisposed)
{
// 如果窗体被销毁,单例会自动重新创建
manager = ButtonBoxManager.Instance;
}
if (manager.Visible)
{
// 如果界面已经可见,将其激活并置于最前
if (manager.WindowState == FormWindowState.Minimized)
{
manager.WindowState = FormWindowState.Normal;
}
manager.Activate();
manager.BringToFront();
}
else
{
// 如果界面不可见,显示它
manager.Show();
manager.Activate();
}
}
catch (Exception ex)
{
MessageBox.Show($"打开按钮盒管理界面失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
@@ -0,0 +1,278 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SimpleCore.Library;
namespace StandardScene.ExtendDevice.Door
{
/// <summary>
/// 门状态枚举
/// </summary>
public enum DoorState
{
/// <summary>
/// 关闭
/// </summary>
Closed = 0,
/// <summary>
/// 打开
/// </summary>
Open = 1,
/// <summary>
/// 未知状态
/// </summary>
Unknown = 2
}
/// <summary>
/// 门控制器状态枚举
/// </summary>
public enum DoorControllerState
{
/// <summary>
/// 离线
/// </summary>
Offline = 0,
/// <summary>
/// 在线
/// </summary>
Online = 1,
/// <summary>
/// 连接中
/// </summary>
Connecting = 2,
/// <summary>
/// 错误
/// </summary>
Error = 3
}
/// <summary>
/// 基础门控制器类
/// </summary>
public abstract class BasicDoorController
{
/// <summary>
/// 控制器索引
/// </summary>
public int Index { get; set; }
/// <summary>
/// IP地址
/// </summary>
public string Ip { get; set; } = string.Empty;
/// <summary>
/// 端口
/// </summary>
public int Port { get; set; } = 502;
/// <summary>
/// 控制器状态
/// </summary>
public DoorControllerState State { get; protected set; } = DoorControllerState.Offline;
/// <summary>
/// 是否在线
/// </summary>
public bool IsOnline => State == DoorControllerState.Online;
/// <summary>
/// 门状态字典,键为门索引
/// </summary>
public Dictionary<int, DoorState> DoorStates { get; protected set; } = new Dictionary<int, DoorState>();
/// <summary>
/// 门目标控制字典,键为门索引,值为期望的开关状态(true=打开,false=关闭)
/// 仅作为指令缓存,实际通信由具体门控制器内部线程完成
/// </summary>
public Dictionary<int, bool> DoorControlTargets { get; protected set; } = new Dictionary<int, bool>();
/// <summary>
/// 门配置信息字典,键为门索引
/// </summary>
public Dictionary<int, DoorModel> DoorConfigs { get; protected set; } = new Dictionary<int, DoorModel>();
/// <summary>
/// 最后更新时间
/// </summary>
public DateTime LastUpdateTime { get; protected set; } = DateTime.Now;
/// <summary>
/// 错误信息
/// </summary>
public string ErrorMessage { get; protected set; } = string.Empty;
/// <summary>
/// 更新控制器状态
/// </summary>
public virtual void UpdateState(DoorControllerState newState, string errorMessage = "")
{
State = newState;
ErrorMessage = errorMessage;
LastUpdateTime = DateTime.Now;
}
/// <summary>
/// 更新门状态
/// </summary>
/// <param name="doorIndex">门索引</param>
/// <param name="state">门状态</param>
public virtual void UpdateDoorState(int doorIndex, DoorState state)
{
if (!DoorStates.ContainsKey(doorIndex))
{
Diagnosis.Post($"门控制器{Index}不存在门{doorIndex}");
}
DoorStates[doorIndex] = state;
LastUpdateTime = DateTime.Now;
}
/// <summary>
/// 获取门状态
/// </summary>
/// <param name="doorIndex">门索引</param>
/// <returns>门状态,如果不存在则返回Unknown</returns>
public virtual DoorState GetDoorState(int doorIndex)
{
return DoorStates.TryGetValue(doorIndex, out var state) ? state : DoorState.Unknown;
}
/// <summary>
/// 初始化门状态
/// </summary>
/// <param name="doorIndices">门索引列表</param>
public virtual void InitializeDoors(List<int> doorIndices)
{
DoorStates.Clear();
DoorControlTargets.Clear();
foreach (var index in doorIndices)
{
DoorStates[index] = DoorState.Closed;
DoorControlTargets[index] = false;
}
}
/// <summary>
/// 初始化门配置信息
/// </summary>
/// <param name="doorConfigs">门配置列表</param>
public virtual void InitializeDoorConfigs(List<DoorModel> doorConfigs)
{
DoorConfigs.Clear();
if (doorConfigs != null)
{
foreach (var config in doorConfigs)
{
DoorConfigs[config.Index] = new DoorModel
{
Index = config.Index,
ControlAddress = config.ControlAddress,
OpenStatusAddress = config.OpenStatusAddress,
NoControl = config.NoControl
};
}
}
}
/// <summary>
/// 更新门配置信息
/// </summary>
/// <param name="doorConfigs">门配置列表</param>
public virtual void UpdateDoorConfigs(List<DoorModel> doorConfigs)
{
if (doorConfigs == null)
{
DoorConfigs.Clear();
return;
}
// 创建配置字典
var configDict = doorConfigs.ToDictionary(d => d.Index);
// 删除配置中不存在的门
var toRemove = DoorConfigs.Keys.Where(k => !configDict.ContainsKey(k)).ToList();
foreach (var key in toRemove)
{
DoorConfigs.Remove(key);
}
// 添加或更新门配置
foreach (var config in doorConfigs)
{
DoorConfigs[config.Index] = new DoorModel
{
Index = config.Index,
ControlAddress = config.ControlAddress,
OpenStatusAddress = config.OpenStatusAddress,
NoControl = config.NoControl
};
}
}
/// <summary>
/// 获取门配置信息
/// </summary>
/// <param name="doorIndex">门索引</param>
/// <returns>门配置信息,如果不存在则返回null</returns>
public virtual DoorModel GetDoorConfig(int doorIndex)
{
return DoorConfigs.TryGetValue(doorIndex, out var config) ? config : null;
}
/// <summary>
/// 设置门的目标控制状态(仅修改内存字段,不直接进行通信)
/// 实际的通信写入由具体门控制器在内部线程中根据该目标状态执行
/// </summary>
/// <param name="doorIndex">门索引</param>
/// <param name="open">true=打开,false=关闭</param>
public virtual void SetDoorControlTarget(int doorIndex, bool open)
{
// 统一支持 NoControl:当门被配置为不允许发送任何控制指令时,
// 强制将目标置为 false,并避免为其它控制器留下“需要开门”的目标。
if (DoorConfigs.TryGetValue(doorIndex, out var cfg) && cfg != null && cfg.NoControl)
{
DoorControlTargets[doorIndex] = false;
LastUpdateTime = DateTime.Now;
return;
}
DoorControlTargets[doorIndex] = open;
LastUpdateTime = DateTime.Now;
}
/// <summary>
/// 连接门控制器
/// </summary>
public virtual void Connect()
{
UpdateState(DoorControllerState.Connecting);
}
/// <summary>
/// 断开连接
/// </summary>
public virtual void Disconnect()
{
UpdateState(DoorControllerState.Offline);
}
/// <summary>
/// 读取门状态(开到位信号)
/// </summary>
/// <param name="doorIndex">门索引</param>
/// <returns>门状态</returns>
public abstract bool ReadDoorState(int doorIndex);
/// <summary>
/// 写入门控制信号(开关控制)
/// </summary>
/// <param name="doorIndex">门索引</param>
/// <param name="open">true=打开,false=关闭</param>
public abstract void WriteDoorControl(int doorIndex, bool open);
}
}
@@ -0,0 +1,521 @@
namespace StandardScene.ExtendDevice.Door
{
partial class DoorManager
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.doorControllerListView = new System.Windows.Forms.ListView();
this.columnHeaderControllerIndex = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderIp = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderPort = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.groupBoxController = new System.Windows.Forms.GroupBox();
this.btnSaveController = new System.Windows.Forms.Button();
this.btnDeleteController = new System.Windows.Forms.Button();
this.btnAddController = new System.Windows.Forms.Button();
this.labelType = new System.Windows.Forms.Label();
this.comboBoxType = new System.Windows.Forms.ComboBox();
this.labelControllerIndex = new System.Windows.Forms.Label();
this.textBoxControllerIndex = new System.Windows.Forms.TextBox();
this.labelPort = new System.Windows.Forms.Label();
this.textBoxPort = new System.Windows.Forms.TextBox();
this.labelIp = new System.Windows.Forms.Label();
this.textBoxIp = new System.Windows.Forms.TextBox();
this.doorListView = new System.Windows.Forms.ListView();
this.columnHeaderDoorIndex = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderControlAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderOpenStatusAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.groupBoxDoor = new System.Windows.Forms.GroupBox();
this.btnSaveDoor = new System.Windows.Forms.Button();
this.btnDeleteDoor = new System.Windows.Forms.Button();
this.btnAddDoor = new System.Windows.Forms.Button();
this.labelOpenStatusAddress = new System.Windows.Forms.Label();
this.textBoxOpenStatusAddress = new System.Windows.Forms.TextBox();
this.labelControlAddress = new System.Windows.Forms.Label();
this.textBoxControlAddress = new System.Windows.Forms.TextBox();
this.labelDoorIndex = new System.Windows.Forms.Label();
this.textBoxDoorIndex = new System.Windows.Forms.TextBox();
this.labelTitle = new System.Windows.Forms.Label();
this.groupBoxController.SuspendLayout();
this.groupBoxDoor.SuspendLayout();
this.SuspendLayout();
//
// doorControllerListView
//
this.doorControllerListView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.doorControllerListView.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.doorControllerListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeaderControllerIndex,
this.columnHeaderIp,
this.columnHeaderPort,
this.columnHeaderType});
this.doorControllerListView.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.doorControllerListView.FullRowSelect = true;
this.doorControllerListView.GridLines = true;
this.doorControllerListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
this.doorControllerListView.HideSelection = false;
this.doorControllerListView.Location = new System.Drawing.Point(15, 55);
this.doorControllerListView.MultiSelect = false;
this.doorControllerListView.Name = "doorControllerListView";
this.doorControllerListView.OwnerDraw = true;
this.doorControllerListView.Size = new System.Drawing.Size(450, 290);
this.doorControllerListView.TabIndex = 0;
this.doorControllerListView.UseCompatibleStateImageBehavior = false;
this.doorControllerListView.View = System.Windows.Forms.View.Details;
this.doorControllerListView.SelectedIndexChanged += new System.EventHandler(this.doorControllerListView_SelectedIndexChanged);
//
// columnHeaderControllerIndex
//
this.columnHeaderControllerIndex.Text = "编码";
this.columnHeaderControllerIndex.Width = 70;
//
// columnHeaderIp
//
this.columnHeaderIp.Text = "IP地址";
this.columnHeaderIp.Width = 130;
//
// columnHeaderPort
//
this.columnHeaderPort.Text = "端口";
this.columnHeaderPort.Width = 90;
//
// columnHeaderType
//
this.columnHeaderType.Text = "类型";
this.columnHeaderType.Width = 140;
//
// groupBoxController
//
this.groupBoxController.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.groupBoxController.Controls.Add(this.btnSaveController);
this.groupBoxController.Controls.Add(this.btnDeleteController);
this.groupBoxController.Controls.Add(this.btnAddController);
this.groupBoxController.Controls.Add(this.labelType);
this.groupBoxController.Controls.Add(this.comboBoxType);
this.groupBoxController.Controls.Add(this.labelControllerIndex);
this.groupBoxController.Controls.Add(this.textBoxControllerIndex);
this.groupBoxController.Controls.Add(this.labelPort);
this.groupBoxController.Controls.Add(this.textBoxPort);
this.groupBoxController.Controls.Add(this.labelIp);
this.groupBoxController.Controls.Add(this.textBoxIp);
this.groupBoxController.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.groupBoxController.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(68)))), ((int)(((byte)(68)))), ((int)(((byte)(68)))));
this.groupBoxController.Location = new System.Drawing.Point(15, 360);
this.groupBoxController.Name = "groupBoxController";
this.groupBoxController.Padding = new System.Windows.Forms.Padding(12, 10, 12, 12);
this.groupBoxController.Size = new System.Drawing.Size(450, 250);
this.groupBoxController.TabIndex = 1;
this.groupBoxController.TabStop = false;
this.groupBoxController.Text = "门控制器信息";
//
// btnSaveController
//
this.btnSaveController.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(122)))), ((int)(((byte)(204)))));
this.btnSaveController.FlatAppearance.BorderSize = 0;
this.btnSaveController.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(92)))), ((int)(((byte)(153)))));
this.btnSaveController.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(102)))), ((int)(((byte)(170)))));
this.btnSaveController.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnSaveController.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnSaveController.ForeColor = System.Drawing.Color.White;
this.btnSaveController.Location = new System.Drawing.Point(330, 200);
this.btnSaveController.Name = "btnSaveController";
this.btnSaveController.Size = new System.Drawing.Size(100, 38);
this.btnSaveController.TabIndex = 10;
this.btnSaveController.Text = "保存";
this.btnSaveController.UseVisualStyleBackColor = false;
this.btnSaveController.Click += new System.EventHandler(this.btnSaveController_Click);
//
// btnDeleteController
//
this.btnDeleteController.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(53)))), ((int)(((byte)(69)))));
this.btnDeleteController.FlatAppearance.BorderSize = 0;
this.btnDeleteController.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(165)))), ((int)(((byte)(40)))), ((int)(((byte)(52)))));
this.btnDeleteController.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(187)))), ((int)(((byte)(45)))), ((int)(((byte)(59)))));
this.btnDeleteController.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnDeleteController.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnDeleteController.ForeColor = System.Drawing.Color.White;
this.btnDeleteController.Location = new System.Drawing.Point(220, 200);
this.btnDeleteController.Name = "btnDeleteController";
this.btnDeleteController.Size = new System.Drawing.Size(100, 38);
this.btnDeleteController.TabIndex = 9;
this.btnDeleteController.Text = "删除";
this.btnDeleteController.UseVisualStyleBackColor = false;
this.btnDeleteController.Click += new System.EventHandler(this.btnDeleteController_Click);
//
// btnAddController
//
this.btnAddController.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(167)))), ((int)(((byte)(69)))));
this.btnAddController.FlatAppearance.BorderSize = 0;
this.btnAddController.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(125)))), ((int)(((byte)(52)))));
this.btnAddController.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(33)))), ((int)(((byte)(136)))), ((int)(((byte)(56)))));
this.btnAddController.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnAddController.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnAddController.ForeColor = System.Drawing.Color.White;
this.btnAddController.Location = new System.Drawing.Point(110, 200);
this.btnAddController.Name = "btnAddController";
this.btnAddController.Size = new System.Drawing.Size(100, 38);
this.btnAddController.TabIndex = 8;
this.btnAddController.Text = "添加";
this.btnAddController.UseVisualStyleBackColor = false;
this.btnAddController.Click += new System.EventHandler(this.btnAddController_Click);
//
// labelType
//
this.labelType.AutoSize = true;
this.labelType.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelType.Location = new System.Drawing.Point(28, 168);
this.labelType.Name = "labelType";
this.labelType.Size = new System.Drawing.Size(65, 24);
this.labelType.TabIndex = 7;
this.labelType.Text = "类型:";
//
// comboBoxType
//
this.comboBoxType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxType.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.comboBoxType.FormattingEnabled = true;
this.comboBoxType.Location = new System.Drawing.Point(110, 165);
this.comboBoxType.Name = "comboBoxType";
this.comboBoxType.Size = new System.Drawing.Size(320, 32);
this.comboBoxType.TabIndex = 6;
//
// labelControllerIndex
//
this.labelControllerIndex.AutoSize = true;
this.labelControllerIndex.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelControllerIndex.Location = new System.Drawing.Point(28, 48);
this.labelControllerIndex.Name = "labelControllerIndex";
this.labelControllerIndex.Size = new System.Drawing.Size(65, 24);
this.labelControllerIndex.TabIndex = 1;
this.labelControllerIndex.Text = "编码:";
//
// textBoxControllerIndex
//
this.textBoxControllerIndex.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxControllerIndex.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxControllerIndex.Location = new System.Drawing.Point(110, 45);
this.textBoxControllerIndex.Name = "textBoxControllerIndex";
this.textBoxControllerIndex.Size = new System.Drawing.Size(320, 30);
this.textBoxControllerIndex.TabIndex = 0;
//
// labelIp
//
this.labelIp.AutoSize = true;
this.labelIp.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelIp.Location = new System.Drawing.Point(18, 88);
this.labelIp.Name = "labelIp";
this.labelIp.Size = new System.Drawing.Size(85, 24);
this.labelIp.TabIndex = 3;
this.labelIp.Text = "IP地址:";
//
// textBoxIp
//
this.textBoxIp.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxIp.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxIp.Location = new System.Drawing.Point(110, 85);
this.textBoxIp.Name = "textBoxIp";
this.textBoxIp.Size = new System.Drawing.Size(320, 30);
this.textBoxIp.TabIndex = 2;
this.textBoxIp.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(255)))));
//
// labelPort
//
this.labelPort.AutoSize = true;
this.labelPort.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelPort.Location = new System.Drawing.Point(28, 128);
this.labelPort.Name = "labelPort";
this.labelPort.Size = new System.Drawing.Size(65, 24);
this.labelPort.TabIndex = 5;
this.labelPort.Text = "端口:";
//
// textBoxPort
//
this.textBoxPort.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxPort.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxPort.Location = new System.Drawing.Point(110, 125);
this.textBoxPort.Name = "textBoxPort";
this.textBoxPort.Size = new System.Drawing.Size(320, 30);
this.textBoxPort.TabIndex = 4;
//
// doorListView
//
this.doorListView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.doorListView.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.doorListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeaderDoorIndex,
this.columnHeaderControlAddress,
this.columnHeaderOpenStatusAddress});
this.doorListView.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.doorListView.FullRowSelect = true;
this.doorListView.GridLines = true;
this.doorListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
this.doorListView.HideSelection = false;
this.doorListView.Location = new System.Drawing.Point(483, 55);
this.doorListView.MultiSelect = false;
this.doorListView.Name = "doorListView";
this.doorListView.OwnerDraw = true;
this.doorListView.Size = new System.Drawing.Size(500, 290);
this.doorListView.TabIndex = 2;
this.doorListView.UseCompatibleStateImageBehavior = false;
this.doorListView.View = System.Windows.Forms.View.Details;
this.doorListView.SelectedIndexChanged += new System.EventHandler(this.doorListView_SelectedIndexChanged);
//
// columnHeaderDoorIndex
//
this.columnHeaderDoorIndex.Text = "编码";
this.columnHeaderDoorIndex.Width = 100;
//
// columnHeaderControlAddress
//
this.columnHeaderControlAddress.Text = "控制地址";
this.columnHeaderControlAddress.Width = 180;
//
// columnHeaderOpenStatusAddress
//
this.columnHeaderOpenStatusAddress.Text = "开到位地址";
this.columnHeaderOpenStatusAddress.Width = 180;
//
// groupBoxDoor
//
this.groupBoxDoor.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.checkBoxNoControl = new System.Windows.Forms.CheckBox();
this.groupBoxDoor.Controls.Add(this.checkBoxNoControl);
this.groupBoxDoor.Controls.Add(this.btnSaveDoor);
this.groupBoxDoor.Controls.Add(this.btnDeleteDoor);
this.groupBoxDoor.Controls.Add(this.btnAddDoor);
this.groupBoxDoor.Controls.Add(this.labelOpenStatusAddress);
this.groupBoxDoor.Controls.Add(this.textBoxOpenStatusAddress);
this.groupBoxDoor.Controls.Add(this.labelControlAddress);
this.groupBoxDoor.Controls.Add(this.textBoxControlAddress);
this.groupBoxDoor.Controls.Add(this.labelDoorIndex);
this.groupBoxDoor.Controls.Add(this.textBoxDoorIndex);
this.groupBoxDoor.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.groupBoxDoor.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(68)))), ((int)(((byte)(68)))), ((int)(((byte)(68)))));
this.groupBoxDoor.Location = new System.Drawing.Point(483, 360);
this.groupBoxDoor.Name = "groupBoxDoor";
this.groupBoxDoor.Padding = new System.Windows.Forms.Padding(12, 10, 12, 12);
this.groupBoxDoor.Size = new System.Drawing.Size(500, 250);
this.groupBoxDoor.TabIndex = 3;
this.groupBoxDoor.TabStop = false;
this.groupBoxDoor.Text = "门信息";
//
// btnSaveDoor
//
this.btnSaveDoor.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(122)))), ((int)(((byte)(204)))));
this.btnSaveDoor.FlatAppearance.BorderSize = 0;
this.btnSaveDoor.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(92)))), ((int)(((byte)(153)))));
this.btnSaveDoor.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(102)))), ((int)(((byte)(170)))));
this.btnSaveDoor.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnSaveDoor.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnSaveDoor.ForeColor = System.Drawing.Color.White;
this.btnSaveDoor.Location = new System.Drawing.Point(380, 200);
this.btnSaveDoor.Name = "btnSaveDoor";
this.btnSaveDoor.Size = new System.Drawing.Size(100, 38);
this.btnSaveDoor.TabIndex = 7;
this.btnSaveDoor.Text = "保存";
this.btnSaveDoor.UseVisualStyleBackColor = false;
this.btnSaveDoor.Click += new System.EventHandler(this.btnSaveDoor_Click);
//
// btnDeleteDoor
//
this.btnDeleteDoor.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(53)))), ((int)(((byte)(69)))));
this.btnDeleteDoor.FlatAppearance.BorderSize = 0;
this.btnDeleteDoor.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(165)))), ((int)(((byte)(40)))), ((int)(((byte)(52)))));
this.btnDeleteDoor.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(187)))), ((int)(((byte)(45)))), ((int)(((byte)(59)))));
this.btnDeleteDoor.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnDeleteDoor.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnDeleteDoor.ForeColor = System.Drawing.Color.White;
this.btnDeleteDoor.Location = new System.Drawing.Point(270, 200);
this.btnDeleteDoor.Name = "btnDeleteDoor";
this.btnDeleteDoor.Size = new System.Drawing.Size(100, 38);
this.btnDeleteDoor.TabIndex = 6;
this.btnDeleteDoor.Text = "删除";
this.btnDeleteDoor.UseVisualStyleBackColor = false;
this.btnDeleteDoor.Click += new System.EventHandler(this.btnDeleteDoor_Click);
//
// btnAddDoor
//
this.btnAddDoor.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(167)))), ((int)(((byte)(69)))));
this.btnAddDoor.FlatAppearance.BorderSize = 0;
this.btnAddDoor.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(125)))), ((int)(((byte)(52)))));
this.btnAddDoor.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(33)))), ((int)(((byte)(136)))), ((int)(((byte)(56)))));
this.btnAddDoor.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnAddDoor.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnAddDoor.ForeColor = System.Drawing.Color.White;
this.btnAddDoor.Location = new System.Drawing.Point(160, 200);
this.btnAddDoor.Name = "btnAddDoor";
this.btnAddDoor.Size = new System.Drawing.Size(100, 38);
this.btnAddDoor.TabIndex = 5;
this.btnAddDoor.Text = "添加";
this.btnAddDoor.UseVisualStyleBackColor = false;
this.btnAddDoor.Click += new System.EventHandler(this.btnAddDoor_Click);
//
// labelOpenStatusAddress
//
this.labelOpenStatusAddress.AutoSize = true;
this.labelOpenStatusAddress.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelOpenStatusAddress.Location = new System.Drawing.Point(18, 128);
this.labelOpenStatusAddress.Name = "labelOpenStatusAddress";
this.labelOpenStatusAddress.Size = new System.Drawing.Size(103, 24);
this.labelOpenStatusAddress.TabIndex = 4;
this.labelOpenStatusAddress.Text = "开到位地址:";
//
// textBoxOpenStatusAddress
//
this.textBoxOpenStatusAddress.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxOpenStatusAddress.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxOpenStatusAddress.Location = new System.Drawing.Point(150, 125);
this.textBoxOpenStatusAddress.Name = "textBoxOpenStatusAddress";
this.textBoxOpenStatusAddress.Size = new System.Drawing.Size(330, 30);
this.textBoxOpenStatusAddress.TabIndex = 3;
//
// checkBoxNoControl
//
this.checkBoxNoControl.AutoSize = true;
this.checkBoxNoControl.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.checkBoxNoControl.Location = new System.Drawing.Point(150, 165);
this.checkBoxNoControl.Name = "checkBoxNoControl";
this.checkBoxNoControl.Size = new System.Drawing.Size(162, 28);
this.checkBoxNoControl.TabIndex = 4;
this.checkBoxNoControl.Text = "禁止门控发送指令";
this.checkBoxNoControl.UseVisualStyleBackColor = true;
//
// labelControlAddress
//
this.labelControlAddress.AutoSize = true;
this.labelControlAddress.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelControlAddress.Location = new System.Drawing.Point(18, 88);
this.labelControlAddress.Name = "labelControlAddress";
this.labelControlAddress.Size = new System.Drawing.Size(103, 24);
this.labelControlAddress.TabIndex = 2;
this.labelControlAddress.Text = "控制地址:";
//
// textBoxControlAddress
//
this.textBoxControlAddress.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxControlAddress.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxControlAddress.Location = new System.Drawing.Point(150, 85);
this.textBoxControlAddress.Name = "textBoxControlAddress";
this.textBoxControlAddress.Size = new System.Drawing.Size(330, 30);
this.textBoxControlAddress.TabIndex = 1;
//
// labelDoorIndex
//
this.labelDoorIndex.AutoSize = true;
this.labelDoorIndex.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelDoorIndex.Location = new System.Drawing.Point(28, 48);
this.labelDoorIndex.Name = "labelDoorIndex";
this.labelDoorIndex.Size = new System.Drawing.Size(65, 24);
this.labelDoorIndex.TabIndex = 0;
this.labelDoorIndex.Text = "编码:";
//
// textBoxDoorIndex
//
this.textBoxDoorIndex.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxDoorIndex.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxDoorIndex.Location = new System.Drawing.Point(150, 45);
this.textBoxDoorIndex.Name = "textBoxDoorIndex";
this.textBoxDoorIndex.Size = new System.Drawing.Size(330, 30);
this.textBoxDoorIndex.TabIndex = 0;
//
// labelTitle
//
this.labelTitle.AutoSize = true;
this.labelTitle.Font = new System.Drawing.Font("微软雅黑", 16F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelTitle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(51)))), ((int)(((byte)(51)))), ((int)(((byte)(51)))));
this.labelTitle.Location = new System.Drawing.Point(15, 12);
this.labelTitle.Name = "labelTitle";
this.labelTitle.Size = new System.Drawing.Size(150, 42);
this.labelTitle.TabIndex = 4;
this.labelTitle.Text = "门控制器管理";
//
// DoorManager
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(245)))), ((int)(((byte)(245)))), ((int)(((byte)(247)))));
this.ClientSize = new System.Drawing.Size(1000, 620);
this.Controls.Add(this.labelTitle);
this.Controls.Add(this.groupBoxDoor);
this.Controls.Add(this.doorListView);
this.Controls.Add(this.groupBoxController);
this.Controls.Add(this.doorControllerListView);
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.MinimumSize = new System.Drawing.Size(1000, 620);
this.Name = "DoorManager";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "门控制器管理";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.DoorManager_FormClosing);
this.Load += new System.EventHandler(this.DoorManager_Load);
this.groupBoxController.ResumeLayout(false);
this.groupBoxController.PerformLayout();
this.groupBoxDoor.ResumeLayout(false);
this.groupBoxDoor.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ListView doorControllerListView;
private System.Windows.Forms.ColumnHeader columnHeaderControllerIndex;
private System.Windows.Forms.ColumnHeader columnHeaderIp;
private System.Windows.Forms.ColumnHeader columnHeaderPort;
private System.Windows.Forms.ColumnHeader columnHeaderType;
private System.Windows.Forms.GroupBox groupBoxController;
private System.Windows.Forms.TextBox textBoxIp;
private System.Windows.Forms.Label labelIp;
private System.Windows.Forms.Label labelPort;
private System.Windows.Forms.TextBox textBoxPort;
private System.Windows.Forms.Label labelControllerIndex;
private System.Windows.Forms.TextBox textBoxControllerIndex;
private System.Windows.Forms.Label labelType;
private System.Windows.Forms.ComboBox comboBoxType;
private System.Windows.Forms.Button btnAddController;
private System.Windows.Forms.Button btnDeleteController;
private System.Windows.Forms.Button btnSaveController;
private System.Windows.Forms.ListView doorListView;
private System.Windows.Forms.ColumnHeader columnHeaderDoorIndex;
private System.Windows.Forms.ColumnHeader columnHeaderControlAddress;
private System.Windows.Forms.ColumnHeader columnHeaderOpenStatusAddress;
private System.Windows.Forms.GroupBox groupBoxDoor;
private System.Windows.Forms.Label labelDoorIndex;
private System.Windows.Forms.TextBox textBoxDoorIndex;
private System.Windows.Forms.Label labelControlAddress;
private System.Windows.Forms.TextBox textBoxControlAddress;
private System.Windows.Forms.Label labelOpenStatusAddress;
private System.Windows.Forms.TextBox textBoxOpenStatusAddress;
private System.Windows.Forms.Button btnAddDoor;
private System.Windows.Forms.Button btnDeleteDoor;
private System.Windows.Forms.Button btnSaveDoor;
private System.Windows.Forms.Label labelTitle;
private System.Windows.Forms.CheckBox checkBoxNoControl;
}
}
@@ -0,0 +1,961 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using StandardScene.Utils;
namespace StandardScene.ExtendDevice.Door
{
public partial class DoorManager : Form
{
private static DoorManager _instance = null;
private static readonly object _lock = new object();
private const string DataFileName = "DoorConfig.json";
private string _dataFilePath;
private List<DoorControllerModel> _doorControllers = new List<DoorControllerModel>();
private DoorControllerModel _currentController = null;
private DoorModel _currentDoor = null;
private int _controllerHoverIndex = -1;
private int _doorHoverIndex = -1;
/// <summary>
/// 获取单例实例
/// </summary>
public static DoorManager Instance
{
get
{
if (_instance == null || _instance.IsDisposed)
{
lock (_lock)
{
if (_instance == null || _instance.IsDisposed)
{
_instance = new DoorManager();
}
}
}
return _instance;
}
}
/// <summary>
/// 私有构造函数,确保单例模式
/// </summary>
private DoorManager()
{
InitializeComponent();
// 设置数据文件路径
_dataFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, DataFileName);
}
private void DoorManager_Load(object sender, EventArgs e)
{
// 设置ListView的视觉样式
SetupListViewStyles();
// 初始化类型下拉框
InitializeTypeComboBox();
LoadData();
RefreshControllerList();
}
/// <summary>
/// 初始化类型下拉框,显示 DoorTypeAttribute.Name
/// </summary>
private void InitializeTypeComboBox()
{
comboBoxType.Items.Clear();
try
{
// 获取当前命名空间下所有继承自BasicDoorController且带有DoorTypeAttribute特性的类
// 在插件/宿主环境下 GetExecutingAssembly 可能不是 StandardScene.dll
// 跨程序集发现:门控制器具体类型可能位于卫星插件 dllStandardScene.Devices.Door)。
var controllerTypes = SimpleLite.Utils.UiTypeDiscovery.AllTypes()
.Where(t => t.IsClass
&& !t.IsAbstract
&& t.Namespace == typeof(BasicDoorController).Namespace
&& t.IsSubclassOf(typeof(BasicDoorController))
&& t.IsDefined(typeof(DoorTypeAttribute), false))
.ToList();
var typeNames = new List<string>();
foreach (var type in controllerTypes)
{
var attr = type.GetCustomAttribute<DoorTypeAttribute>();
if (attr != null && !string.IsNullOrWhiteSpace(attr.Name))
{
typeNames.Add(attr.Name);
}
}
// 按名称排序
typeNames.Sort();
foreach (var typeName in typeNames)
{
comboBoxType.Items.Add(typeName);
}
// 如果没有找到任何类型,添加默认选项
if (comboBoxType.Items.Count == 0)
{
comboBoxType.Items.Add("ModbusDoorController");
}
}
catch (Exception ex)
{
MessageBox.Show($"初始化类型下拉框失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
comboBoxType.Items.Add("ModbusDoorController");
}
}
/// <summary>
/// 设置ListView的视觉样式
/// </summary>
private void SetupListViewStyles()
{
SetupListView(doorControllerListView,
ControllerListView_DrawItem,
ControllerListView_DrawSubItem,
ControllerListView_DrawColumnHeader,
ControllerListView_MouseMove,
ControllerListView_MouseLeave);
SetupListView(doorListView,
DoorListView_DrawItem,
DoorListView_DrawSubItem,
DoorListView_DrawColumnHeader,
DoorListView_MouseMove,
DoorListView_MouseLeave);
}
private void SetupListView(ListView listView,
DrawListViewItemEventHandler itemHandler,
DrawListViewSubItemEventHandler subItemHandler,
DrawListViewColumnHeaderEventHandler headerHandler,
MouseEventHandler mouseMoveHandler,
EventHandler mouseLeaveHandler)
{
listView.OwnerDraw = true;
listView.BackColor = Color.White;
listView.DrawItem += itemHandler;
listView.DrawSubItem += subItemHandler;
listView.DrawColumnHeader += headerHandler;
listView.MouseMove += mouseMoveHandler;
listView.MouseLeave += mouseLeaveHandler;
// 启用双缓冲
typeof(Control)?.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic)?
.SetValue(listView, true, null);
}
private static readonly Color RowEvenColor = Color.FromArgb(250, 250, 252);
private static readonly Color RowOddColor = Color.White;
private static readonly Color RowHighlightColor = Color.FromArgb(230, 240, 255);
private static readonly Color TextRegularColor = Color.FromArgb(68, 68, 68);
private static readonly Color TextHighlightColor = Color.FromArgb(51, 51, 51);
private void ControllerListView_MouseMove(object sender, MouseEventArgs e)
{
UpdateHoverIndex(doorControllerListView, e, true);
}
private void ControllerListView_MouseLeave(object sender, EventArgs e)
{
ResetHoverIndex(doorControllerListView, true);
}
private void DoorListView_MouseMove(object sender, MouseEventArgs e)
{
UpdateHoverIndex(doorListView, e, false);
}
private void DoorListView_MouseLeave(object sender, EventArgs e)
{
ResetHoverIndex(doorListView, false);
}
private void UpdateHoverIndex(ListView listView, MouseEventArgs e, bool isControllerList)
{
var hoveredItem = listView.GetItemAt(e.X, e.Y);
int newIndex = hoveredItem?.Index ?? -1;
if (isControllerList)
{
if (_controllerHoverIndex != newIndex)
{
_controllerHoverIndex = newIndex;
listView.Invalidate();
}
}
else
{
if (_doorHoverIndex != newIndex)
{
_doorHoverIndex = newIndex;
listView.Invalidate();
}
}
}
private void ResetHoverIndex(ListView listView, bool isControllerList)
{
if (isControllerList)
{
if (_controllerHoverIndex != -1)
{
_controllerHoverIndex = -1;
listView.Invalidate();
}
}
else
{
if (_doorHoverIndex != -1)
{
_doorHoverIndex = -1;
listView.Invalidate();
}
}
}
private void ControllerListView_DrawItem(object sender, DrawListViewItemEventArgs e)
{
var isHighlighted = e.Item.Selected
|| e.ItemIndex == _controllerHoverIndex
|| (e.State & ListViewItemStates.Focused) != 0;
var backColor = isHighlighted
? RowHighlightColor
: (e.ItemIndex % 2 == 0 ? RowEvenColor : RowOddColor);
using (var brush = new SolidBrush(backColor))
{
e.Graphics.FillRectangle(brush, e.Bounds);
}
var textColor = isHighlighted ? TextHighlightColor : TextRegularColor;
TextRenderer.DrawText(e.Graphics, e.Item.Text, e.Item.Font, e.Bounds,
textColor,
TextFormatFlags.VerticalCenter | TextFormatFlags.Left | TextFormatFlags.EndEllipsis);
e.DrawFocusRectangle();
}
private void ControllerListView_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
var isHighlighted = e.Item.Selected
|| e.ItemIndex == _controllerHoverIndex
|| (e.ItemState & ListViewItemStates.Focused) != 0;
var backColor = isHighlighted
? RowHighlightColor
: (e.ItemIndex % 2 == 0 ? RowEvenColor : RowOddColor);
using (var brush = new SolidBrush(backColor))
{
e.Graphics.FillRectangle(brush, e.Bounds);
}
var textColor = isHighlighted ? TextHighlightColor : TextRegularColor;
TextRenderer.DrawText(e.Graphics, e.SubItem.Text, e.SubItem.Font, e.Bounds,
textColor,
TextFormatFlags.VerticalCenter | TextFormatFlags.Left | TextFormatFlags.EndEllipsis);
}
private void ControllerListView_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(245, 247, 250)), e.Bounds);
e.Graphics.DrawLine(new Pen(Color.FromArgb(220, 220, 220)),
e.Bounds.Left, e.Bounds.Bottom - 1, e.Bounds.Right, e.Bounds.Bottom - 1);
TextRenderer.DrawText(e.Graphics, e.Header.Text,
new Font("微软雅黑", 10.5F, FontStyle.Bold),
e.Bounds, Color.FromArgb(68, 68, 68),
TextFormatFlags.VerticalCenter | TextFormatFlags.Left | TextFormatFlags.HorizontalCenter);
}
private void DoorListView_DrawItem(object sender, DrawListViewItemEventArgs e)
{
var isHighlighted = e.Item.Selected
|| e.ItemIndex == _doorHoverIndex
|| (e.State & ListViewItemStates.Focused) != 0;
var backColor = isHighlighted
? RowHighlightColor
: (e.ItemIndex % 2 == 0 ? RowEvenColor : RowOddColor);
using (var brush = new SolidBrush(backColor))
{
e.Graphics.FillRectangle(brush, e.Bounds);
}
var textColor = isHighlighted ? TextHighlightColor : TextRegularColor;
TextRenderer.DrawText(e.Graphics, e.Item.Text, e.Item.Font, e.Bounds,
textColor,
TextFormatFlags.VerticalCenter | TextFormatFlags.Left | TextFormatFlags.EndEllipsis);
e.DrawFocusRectangle();
}
private void DoorListView_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
var isHighlighted = e.Item.Selected
|| e.ItemIndex == _doorHoverIndex
|| (e.ItemState & ListViewItemStates.Focused) != 0;
var backColor = isHighlighted
? RowHighlightColor
: (e.ItemIndex % 2 == 0 ? RowEvenColor : RowOddColor);
using (var brush = new SolidBrush(backColor))
{
e.Graphics.FillRectangle(brush, e.Bounds);
}
var textColor = isHighlighted ? TextHighlightColor : TextRegularColor;
TextRenderer.DrawText(e.Graphics, e.SubItem.Text, e.SubItem.Font, e.Bounds,
textColor,
TextFormatFlags.VerticalCenter | TextFormatFlags.Left | TextFormatFlags.EndEllipsis);
}
private void DoorListView_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(245, 247, 250)), e.Bounds);
e.Graphics.DrawLine(new Pen(Color.FromArgb(220, 220, 220)),
e.Bounds.Left, e.Bounds.Bottom - 1, e.Bounds.Right, e.Bounds.Bottom - 1);
TextRenderer.DrawText(e.Graphics, e.Header.Text,
new Font("微软雅黑", 10.5F, FontStyle.Bold),
e.Bounds, Color.FromArgb(68, 68, 68),
TextFormatFlags.VerticalCenter | TextFormatFlags.Left | TextFormatFlags.HorizontalCenter);
}
/// <summary>
/// 刷新门控制器列表
/// </summary>
private void RefreshControllerList()
{
doorControllerListView.Items.Clear();
foreach (var controller in _doorControllers)
{
var item = new ListViewItem(controller.Index.ToString());
item.SubItems.Add(controller.Ip);
item.SubItems.Add(controller.Port.ToString());
item.SubItems.Add(controller.Type);
item.Tag = controller;
item.UseItemStyleForSubItems = false;
doorControllerListView.Items.Add(item);
}
}
/// <summary>
/// 刷新门列表
/// </summary>
private void RefreshDoorList()
{
doorListView.Items.Clear();
if (_currentController != null)
{
foreach (var door in _currentController.Doors)
{
var item = new ListViewItem(door.Index.ToString());
item.SubItems.Add(door.ControlAddress.ToString());
item.SubItems.Add(door.OpenStatusAddress.ToString());
item.Tag = door;
item.UseItemStyleForSubItems = false;
doorListView.Items.Add(item);
}
}
}
/// <summary>
/// 门控制器列表选择改变
/// </summary>
private void doorControllerListView_SelectedIndexChanged(object sender, EventArgs e)
{
if (doorControllerListView.SelectedItems.Count > 0)
{
_currentController = doorControllerListView.SelectedItems[0].Tag as DoorControllerModel;
if (_currentController != null)
{
// 填充门控制器编辑区域
textBoxIp.Text = _currentController.Ip;
textBoxPort.Text = _currentController.Port.ToString();
textBoxControllerIndex.Text = _currentController.Index.ToString();
// 设置类型下拉框
if (comboBoxType.Items.Contains(_currentController.Type))
{
comboBoxType.SelectedItem = _currentController.Type;
}
else
{
comboBoxType.SelectedIndex = comboBoxType.Items.Count > 0 ? 0 : -1;
}
// 刷新门列表
RefreshDoorList();
}
}
else
{
_currentController = null;
ClearControllerFields();
doorListView.Items.Clear();
}
}
/// <summary>
/// 门列表选择改变
/// </summary>
private void doorListView_SelectedIndexChanged(object sender, EventArgs e)
{
if (doorListView.SelectedItems.Count > 0)
{
_currentDoor = doorListView.SelectedItems[0].Tag as DoorModel;
if (_currentDoor != null)
{
// 填充门编辑区域
textBoxDoorIndex.Text = _currentDoor.Index.ToString();
textBoxControlAddress.Text = _currentDoor.ControlAddress.ToString();
textBoxOpenStatusAddress.Text = _currentDoor.OpenStatusAddress.ToString();
checkBoxNoControl.Checked = _currentDoor.NoControl;
}
}
else
{
_currentDoor = null;
ClearDoorFields();
}
}
/// <summary>
/// 添加门控制器
/// </summary>
private void btnAddController_Click(object sender, EventArgs e)
{
try
{
string ip = textBoxIp.Text.Trim();
string portText = textBoxPort.Text.Trim();
string indexText = textBoxControllerIndex.Text.Trim();
string type = comboBoxType.SelectedItem?.ToString() ?? string.Empty;
int newIndex;
if (!string.IsNullOrWhiteSpace(indexText))
{
if (!int.TryParse(indexText, out newIndex))
{
MessageBox.Show("编码必须是数字", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
else
{
newIndex = _doorControllers.Count > 0 ? _doorControllers.Max(c => c.Index) + 1 : 1;
}
string newIp;
if (!string.IsNullOrWhiteSpace(ip))
{
if (!IsValidIpAddress(ip))
{
MessageBox.Show("无效的IP地址,例如:192.168.1.100", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
newIp = ip;
}
else
{
newIp = "192.168.1.100";
}
int newPort;
if (!string.IsNullOrWhiteSpace(portText))
{
if (!int.TryParse(portText, out newPort))
{
MessageBox.Show("端口必须是数字", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
else
{
newPort = 502;
}
string newType;
if (!string.IsNullOrWhiteSpace(type))
{
newType = type;
}
else
{
newType = comboBoxType.Items.Count > 0 ? comboBoxType.Items[0].ToString() : "ModbusDoorController";
}
// 检查编码是否重复
if (_doorControllers.Any(c => c.Index == newIndex))
{
MessageBox.Show($"编码 {newIndex} 已存在,请使用其他编码", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 检查IP地址是否重复
if (_doorControllers.Any(c => c.Ip == newIp))
{
MessageBox.Show($"IP地址 {newIp} 已存在,请使用其他IP地址", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
var newController = new DoorControllerModel
{
Index = newIndex,
Ip = newIp,
Port = newPort,
Type = newType
};
_doorControllers.Add(newController);
RefreshControllerList();
SaveData();
// 选中新添加的门控制器
foreach (ListViewItem item in doorControllerListView.Items)
{
if (item.Tag == newController)
{
item.Selected = true;
item.EnsureVisible();
break;
}
}
}
catch (Exception ex)
{
MessageBox.Show($"添加门控制器失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 删除门控制器
/// </summary>
private void btnDeleteController_Click(object sender, EventArgs e)
{
if (_currentController == null)
{
MessageBox.Show("请选择要删除的门控制器", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
var result = MessageBox.Show($"删除编码为 {_currentController.Index} 的门控制器?", "确认删除",
MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
_doorControllers.Remove(_currentController);
_currentController = null;
ClearControllerFields();
RefreshControllerList();
doorListView.Items.Clear();
SaveData();
}
}
/// <summary>
/// 保存门控制器
/// </summary>
private void btnSaveController_Click(object sender, EventArgs e)
{
if (_currentController == null)
{
MessageBox.Show("请选择要保存的门控制器", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
try
{
string newIp = textBoxIp.Text.Trim();
if (!IsValidIpAddress(newIp))
{
MessageBox.Show("无效的IP地址,例如:192.168.1.100", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (!int.TryParse(textBoxPort.Text, out int port))
{
MessageBox.Show("端口必须是数字", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
_currentController.Port = port;
if (!int.TryParse(textBoxControllerIndex.Text, out int index))
{
MessageBox.Show("编码必须是数字", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 检查编码是否重复(排除当前项)
if (_doorControllers.Any(c => c.Index == index && c != _currentController))
{
MessageBox.Show($"编码 {index} 已存在,请使用其他编码", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 检查IP地址是否重复(排除当前项)
if (_doorControllers.Any(c => c.Ip == newIp && c != _currentController))
{
MessageBox.Show($"IP地址 {newIp} 已存在,请使用其他IP地址", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
_currentController.Index = index;
_currentController.Type = comboBoxType.SelectedItem?.ToString() ?? string.Empty;
_currentController.Ip = newIp;
RefreshControllerList();
SaveData();
MessageBox.Show("保存成功", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"保存失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 添加门
/// </summary>
private void btnAddDoor_Click(object sender, EventArgs e)
{
if (_currentController == null)
{
MessageBox.Show("请先选择门控制器", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
try
{
string indexText = textBoxDoorIndex.Text.Trim();
string controlAddressText = textBoxControlAddress.Text.Trim();
string openStatusAddressText = textBoxOpenStatusAddress.Text.Trim();
int newIndex;
if (!string.IsNullOrWhiteSpace(indexText))
{
if (!int.TryParse(indexText, out newIndex))
{
MessageBox.Show("门编码必须是数字", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
else
{
newIndex = _currentController.Doors.Count > 0
? _currentController.Doors.Max(d => d.Index) + 1
: 1;
}
// 检查门编码是否重复
if (_currentController.Doors.Any(d => d.Index == newIndex))
{
MessageBox.Show($"门编码 {newIndex} 已存在,请使用其他编码", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
ushort controlAddress = 0;
if (!string.IsNullOrWhiteSpace(controlAddressText))
{
if (!ushort.TryParse(controlAddressText, out controlAddress))
{
MessageBox.Show("控制地址必须是0-65535之间的数字", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
ushort openStatusAddress = 0;
if (!string.IsNullOrWhiteSpace(openStatusAddressText))
{
if (!ushort.TryParse(openStatusAddressText, out openStatusAddress))
{
MessageBox.Show("开到位地址必须是0-65535之间的数字", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
var newDoor = new DoorModel
{
Index = newIndex,
ControlAddress = controlAddress,
OpenStatusAddress = openStatusAddress,
NoControl = checkBoxNoControl.Checked
};
_currentController.Doors.Add(newDoor);
RefreshDoorList();
SaveData();
// 选中新添加的门
foreach (ListViewItem item in doorListView.Items)
{
if (item.Tag == newDoor)
{
item.Selected = true;
item.EnsureVisible();
break;
}
}
}
catch (Exception ex)
{
MessageBox.Show($"添加门失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 删除门
/// </summary>
private void btnDeleteDoor_Click(object sender, EventArgs e)
{
if (_currentController == null)
{
MessageBox.Show("请先选择门控制器", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
if (_currentDoor == null)
{
MessageBox.Show("请选择要删除的门", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
var result = MessageBox.Show($"删除编码为 {_currentDoor.Index} 的门?", "确认删除",
MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
_currentController.Doors.Remove(_currentDoor);
_currentDoor = null;
ClearDoorFields();
RefreshDoorList();
SaveData();
}
}
/// <summary>
/// 保存门
/// </summary>
private void btnSaveDoor_Click(object sender, EventArgs e)
{
if (_currentController == null)
{
MessageBox.Show("请先选择门控制器", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
if (_currentDoor == null)
{
MessageBox.Show("请选择要保存的门", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
try
{
if (!int.TryParse(textBoxDoorIndex.Text, out int index))
{
MessageBox.Show("门编码必须是数字", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 检查门编码是否重复(排除当前门)
if (_currentController.Doors.Any(d => d.Index == index && d != _currentDoor))
{
MessageBox.Show($"门编码 {index} 已存在,请使用其他编码", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (!ushort.TryParse(textBoxControlAddress.Text, out ushort controlAddress))
{
MessageBox.Show("控制地址必须是0-65535之间的数字", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (!ushort.TryParse(textBoxOpenStatusAddress.Text, out ushort openStatusAddress))
{
MessageBox.Show("开到位地址必须是0-65535之间的数字", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
_currentDoor.Index = index;
_currentDoor.ControlAddress = controlAddress;
_currentDoor.OpenStatusAddress = openStatusAddress;
_currentDoor.NoControl = checkBoxNoControl.Checked;
RefreshDoorList();
SaveData();
MessageBox.Show("保存成功", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"保存失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 清空门控制器字段
/// </summary>
private void ClearControllerFields()
{
textBoxIp.Text = string.Empty;
textBoxPort.Text = string.Empty;
textBoxControllerIndex.Text = string.Empty;
comboBoxType.SelectedIndex = -1;
}
/// <summary>
/// 清空门字段
/// </summary>
private void ClearDoorFields()
{
textBoxDoorIndex.Text = string.Empty;
textBoxControlAddress.Text = string.Empty;
textBoxOpenStatusAddress.Text = string.Empty;
checkBoxNoControl.Checked = false;
}
/// <summary>
/// 加载数据
/// </summary>
private void LoadData()
{
try
{
if (File.Exists(_dataFilePath))
{
var jsonContent = File.ReadAllText(_dataFilePath, Encoding.UTF8);
if (!string.IsNullOrWhiteSpace(jsonContent))
{
_doorControllers = jsonContent.JsonTo<List<DoorControllerModel>>();
if (_doorControllers == null)
{
_doorControllers = new List<DoorControllerModel>();
}
}
else
{
_doorControllers = new List<DoorControllerModel>();
}
}
else
{
_doorControllers = new List<DoorControllerModel>();
}
}
catch (Exception ex)
{
MessageBox.Show($"加载数据失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
_doorControllers = new List<DoorControllerModel>();
}
}
/// <summary>
/// 保存数据
/// </summary>
private void SaveData()
{
try
{
var jsonContent = _doorControllers.ToJson();
File.WriteAllText(_dataFilePath, jsonContent, Encoding.UTF8);
}
catch (Exception ex)
{
MessageBox.Show($"保存数据失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 验证IP地址格式
/// </summary>
private bool IsValidIpAddress(string ipAddress)
{
if (string.IsNullOrWhiteSpace(ipAddress))
{
return false;
}
string pattern = @"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$";
if (Regex.IsMatch(ipAddress, pattern))
{
IPAddress address;
return IPAddress.TryParse(ipAddress, out address) && address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork;
}
return false;
}
/// <summary>
/// 窗体关闭事件
/// </summary>
private void DoorManager_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
// 关闭前保存数据
SaveData();
e.Cancel = true;
this.Visible = false;
}
}
/// <summary>
/// 打开管理界面(静态方法)
/// </summary>
public static void OpenViewer()
{
try
{
var manager = Instance;
if (manager.Visible)
{
if (manager.WindowState == FormWindowState.Minimized)
{
manager.WindowState = FormWindowState.Normal;
}
manager.Activate();
manager.BringToFront();
}
else
{
manager.Show();
manager.Activate();
}
}
catch (Exception ex)
{
MessageBox.Show($"打开门控制器管理界面失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="timerRefresh.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
namespace StandardScene.ExtendDevice.Door
{
/// <summary>
/// 门控制器模型
/// </summary>
public class DoorControllerModel
{
/// <summary>
/// 控制器索引
/// </summary>
public int Index { get; set; } = 0;
/// <summary>
/// IP地址
/// </summary>
public string Ip { get; set; } = string.Empty;
/// <summary>
/// 端口
/// </summary>
public int Port { get; set; } = 502;
/// <summary>
/// 控制器类型(类名)
/// </summary>
public string Type { get; set; } = string.Empty;
/// <summary>
/// 门列表
/// </summary>
public List<DoorModel> Doors { get; set; } = new List<DoorModel>();
}
/// <summary>
/// 门模型
/// </summary>
public class DoorModel
{
/// <summary>
/// 门索引
/// </summary>
public int Index { get; set; } = 0;
/// <summary>
/// 开关控制信号地址(Modbus 线圈地址)
/// </summary>
public ushort ControlAddress { get; set; } = 0;
/// <summary>
/// 开到位信号地址(Modbus 线圈地址)
/// </summary>
public ushort OpenStatusAddress { get; set; } = 0;
/// <summary>
/// 禁止对该门下发任何控制指令(打开或关闭)。
/// 为 true 时,门控逻辑不会对该门调用 WriteDoorControl。
/// </summary>
public bool NoControl { get; set; } = false;
}
}
@@ -0,0 +1,263 @@
namespace StandardScene.ExtendDevice.Door
{
partial class DoorMonitor
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.doorListView = new System.Windows.Forms.ListView();
this.columnHeaderControllerIndex = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderDoorIndex = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderState = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderTarget = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderSource = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderManualRemain = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderCarsInArea = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderControlAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderOpenStatusAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.groupBoxControl = new System.Windows.Forms.GroupBox();
this.btnClose = new System.Windows.Forms.Button();
this.btnOpen = new System.Windows.Forms.Button();
this.btnClearCars = new System.Windows.Forms.Button();
this.labelDoorInfo = new System.Windows.Forms.Label();
this.labelTitle = new System.Windows.Forms.Label();
this.timerRefresh = new System.Windows.Forms.Timer();
this.groupBoxControl.SuspendLayout();
this.SuspendLayout();
//
// doorListView
//
this.doorListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.doorListView.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.doorListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeaderControllerIndex,
this.columnHeaderDoorIndex,
this.columnHeaderState,
this.columnHeaderTarget,
this.columnHeaderSource,
this.columnHeaderManualRemain,
this.columnHeaderCarsInArea,
this.columnHeaderControlAddress,
this.columnHeaderOpenStatusAddress});
this.doorListView.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.doorListView.FullRowSelect = true;
this.doorListView.GridLines = true;
this.doorListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
this.doorListView.HideSelection = false;
this.doorListView.Location = new System.Drawing.Point(15, 55);
this.doorListView.MultiSelect = false;
this.doorListView.Name = "doorListView";
this.doorListView.OwnerDraw = true;
this.doorListView.Size = new System.Drawing.Size(800, 400);
this.doorListView.TabIndex = 0;
this.doorListView.UseCompatibleStateImageBehavior = false;
this.doorListView.View = System.Windows.Forms.View.Details;
this.doorListView.SelectedIndexChanged += new System.EventHandler(this.doorListView_SelectedIndexChanged);
//
// columnHeaderControllerIndex
//
this.columnHeaderControllerIndex.Text = "控制器编码";
this.columnHeaderControllerIndex.Width = 120;
//
// columnHeaderDoorIndex
//
this.columnHeaderDoorIndex.Text = "门编码";
this.columnHeaderDoorIndex.Width = 100;
//
// columnHeaderState
//
this.columnHeaderState.Text = "状态";
this.columnHeaderState.Width = 100;
//
// columnHeaderTarget
//
this.columnHeaderTarget.Text = "控制目标";
this.columnHeaderTarget.Width = 100;
//
// columnHeaderSource
//
this.columnHeaderSource.Text = "控制来源";
this.columnHeaderSource.Width = 100;
//
// columnHeaderManualRemain
//
this.columnHeaderManualRemain.Text = "手动剩余(s)";
this.columnHeaderManualRemain.Width = 110;
//
// columnHeaderCarsInArea
//
this.columnHeaderCarsInArea.Text = "车辆占用";
this.columnHeaderCarsInArea.Width = 150;
//
// columnHeaderControlAddress
//
this.columnHeaderControlAddress.Text = "控制地址";
this.columnHeaderControlAddress.Width = 120;
//
// columnHeaderOpenStatusAddress
//
this.columnHeaderOpenStatusAddress.Text = "开到位地址";
this.columnHeaderOpenStatusAddress.Width = 120;
//
// groupBoxControl
//
this.groupBoxControl.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupBoxControl.Controls.Add(this.btnClose);
this.groupBoxControl.Controls.Add(this.btnOpen);
this.groupBoxControl.Controls.Add(this.btnClearCars);
this.groupBoxControl.Controls.Add(this.labelDoorInfo);
this.groupBoxControl.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.groupBoxControl.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(68)))), ((int)(((byte)(68)))), ((int)(((byte)(68)))));
this.groupBoxControl.Location = new System.Drawing.Point(15, 470);
this.groupBoxControl.Name = "groupBoxControl";
this.groupBoxControl.Padding = new System.Windows.Forms.Padding(12, 10, 12, 12);
this.groupBoxControl.Size = new System.Drawing.Size(800, 120);
this.groupBoxControl.TabIndex = 1;
this.groupBoxControl.TabStop = false;
this.groupBoxControl.Text = "手动控制";
//
// btnClose
//
this.btnClose.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(53)))), ((int)(((byte)(69)))));
this.btnClose.FlatAppearance.BorderSize = 0;
this.btnClose.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(165)))), ((int)(((byte)(40)))), ((int)(((byte)(52)))));
this.btnClose.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(187)))), ((int)(((byte)(45)))), ((int)(((byte)(59)))));
this.btnClose.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnClose.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnClose.ForeColor = System.Drawing.Color.White;
this.btnClose.Location = new System.Drawing.Point(450, 50);
this.btnClose.Name = "btnClose";
this.btnClose.Size = new System.Drawing.Size(120, 50);
this.btnClose.TabIndex = 2;
this.btnClose.Text = "关闭";
this.btnClose.UseVisualStyleBackColor = false;
this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
//
// btnOpen
//
this.btnOpen.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(167)))), ((int)(((byte)(69)))));
this.btnOpen.FlatAppearance.BorderSize = 0;
this.btnOpen.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(125)))), ((int)(((byte)(52)))));
this.btnOpen.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(33)))), ((int)(((byte)(136)))), ((int)(((byte)(56)))));
this.btnOpen.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnOpen.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnOpen.ForeColor = System.Drawing.Color.White;
this.btnOpen.Location = new System.Drawing.Point(300, 50);
this.btnOpen.Name = "btnOpen";
this.btnOpen.Size = new System.Drawing.Size(120, 50);
this.btnOpen.TabIndex = 1;
this.btnOpen.Text = "打开";
this.btnOpen.UseVisualStyleBackColor = false;
this.btnOpen.Click += new System.EventHandler(this.btnOpen_Click);
//
// btnClearCars
//
this.btnClearCars.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(108)))), ((int)(((byte)(117)))), ((int)(((byte)(125)))));
this.btnClearCars.FlatAppearance.BorderSize = 0;
this.btnClearCars.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnClearCars.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnClearCars.ForeColor = System.Drawing.Color.White;
this.btnClearCars.Location = new System.Drawing.Point(600, 50);
this.btnClearCars.Name = "btnClearCars";
this.btnClearCars.Size = new System.Drawing.Size(140, 50);
this.btnClearCars.TabIndex = 3;
this.btnClearCars.Text = "清空占用";
this.btnClearCars.UseVisualStyleBackColor = false;
this.btnClearCars.Click += new System.EventHandler(this.btnClearCars_Click);
//
// labelDoorInfo
//
this.labelDoorInfo.AutoSize = true;
this.labelDoorInfo.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelDoorInfo.Location = new System.Drawing.Point(20, 35);
this.labelDoorInfo.Name = "labelDoorInfo";
this.labelDoorInfo.Size = new System.Drawing.Size(200, 24);
this.labelDoorInfo.TabIndex = 0;
this.labelDoorInfo.Text = "请选择要控制的门";
//
// labelTitle
//
this.labelTitle.AutoSize = true;
this.labelTitle.Font = new System.Drawing.Font("微软雅黑", 16F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelTitle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(51)))), ((int)(((byte)(51)))), ((int)(((byte)(51)))));
this.labelTitle.Location = new System.Drawing.Point(15, 12);
this.labelTitle.Name = "labelTitle";
this.labelTitle.Size = new System.Drawing.Size(150, 42);
this.labelTitle.TabIndex = 2;
this.labelTitle.Text = "门控监控";
//
// timerRefresh
//
this.timerRefresh.Interval = 1000;
this.timerRefresh.Tick += new System.EventHandler(this.timerRefresh_Tick);
//
// DoorMonitor
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(245)))), ((int)(((byte)(245)))), ((int)(((byte)(247)))));
this.ClientSize = new System.Drawing.Size(830, 600);
this.Controls.Add(this.labelTitle);
this.Controls.Add(this.groupBoxControl);
this.Controls.Add(this.doorListView);
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.MinimumSize = new System.Drawing.Size(830, 600);
this.Name = "DoorMonitor";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "门控监控";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.DoorMonitor_FormClosing);
this.Load += new System.EventHandler(this.DoorMonitor_Load);
this.groupBoxControl.ResumeLayout(false);
this.groupBoxControl.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ListView doorListView;
private System.Windows.Forms.ColumnHeader columnHeaderControllerIndex;
private System.Windows.Forms.ColumnHeader columnHeaderDoorIndex;
private System.Windows.Forms.ColumnHeader columnHeaderState;
private System.Windows.Forms.ColumnHeader columnHeaderTarget;
private System.Windows.Forms.ColumnHeader columnHeaderSource;
private System.Windows.Forms.ColumnHeader columnHeaderManualRemain;
private System.Windows.Forms.ColumnHeader columnHeaderCarsInArea;
private System.Windows.Forms.ColumnHeader columnHeaderControlAddress;
private System.Windows.Forms.ColumnHeader columnHeaderOpenStatusAddress;
private System.Windows.Forms.GroupBox groupBoxControl;
private System.Windows.Forms.Label labelDoorInfo;
private System.Windows.Forms.Button btnOpen;
private System.Windows.Forms.Button btnClose;
private System.Windows.Forms.Button btnClearCars;
private System.Windows.Forms.Label labelTitle;
private System.Windows.Forms.Timer timerRefresh;
}
}
@@ -0,0 +1,447 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using SimpleLite;
namespace StandardScene.ExtendDevice.Door
{
public partial class DoorMonitor : Form
{
private static DoorMonitor _instance = null;
private static readonly object _lock = new object();
private int _doorHoverIndex = -1;
private (int ControllerIndex, int DoorIndex)? _selectedDoor = null;
private static readonly Color RowEvenColor = Color.FromArgb(250, 250, 252);
private static readonly Color RowOddColor = Color.White;
private static readonly Color RowHighlightColor = Color.FromArgb(230, 240, 255);
private static readonly Color TextRegularColor = Color.FromArgb(68, 68, 68);
private static readonly Color TextHighlightColor = Color.FromArgb(51, 51, 51);
private static readonly Color StateOpenColor = Color.FromArgb(40, 167, 69);
private static readonly Color StateClosedColor = Color.FromArgb(220, 53, 69);
/// <summary>
/// 获取单例实例
/// </summary>
public static DoorMonitor Instance
{
get
{
if (_instance == null || _instance.IsDisposed)
{
lock (_lock)
{
if (_instance == null || _instance.IsDisposed)
{
_instance = new DoorMonitor();
}
}
}
return _instance;
}
}
/// <summary>
/// 私有构造函数,确保单例模式
/// </summary>
private DoorMonitor()
{
InitializeComponent();
}
/// <summary>
/// 确保刷新定时器处于激活状态,并立即刷新一次
/// </summary>
public void EnsureRefreshActive()
{
if (IsDisposed)
{
return;
}
if (!timerRefresh.Enabled)
{
timerRefresh.Start();
}
RefreshDoorList();
}
private void DoorMonitor_Load(object sender, EventArgs e)
{
SetupListViewStyles();
// 禁用系统的悬停/热跟踪高亮,避免鼠标移动时短暂出现默认遮罩
doorListView.HoverSelection = false;
doorListView.HotTracking = false;
EnsureRefreshActive();
}
/// <summary>
/// 设置ListView的视觉样式
/// </summary>
private void SetupListViewStyles()
{
doorListView.OwnerDraw = true;
doorListView.BackColor = Color.White;
doorListView.DrawItem += DoorListView_DrawItem;
doorListView.DrawSubItem += DoorListView_DrawSubItem;
doorListView.DrawColumnHeader += DoorListView_DrawColumnHeader;
doorListView.MouseMove += DoorListView_MouseMove;
doorListView.MouseLeave += DoorListView_MouseLeave;
// 启用双缓冲
typeof(Control)?.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic)?
.SetValue(doorListView, true, null);
}
private void DoorListView_MouseMove(object sender, MouseEventArgs e)
{
var hoveredItem = doorListView.GetItemAt(e.X, e.Y);
int newIndex = hoveredItem?.Index ?? -1;
if (_doorHoverIndex != newIndex)
{
_doorHoverIndex = newIndex;
doorListView.Invalidate();
}
}
private void DoorListView_MouseLeave(object sender, EventArgs e)
{
if (_doorHoverIndex != -1)
{
_doorHoverIndex = -1;
doorListView.Invalidate();
}
}
private void DoorListView_DrawItem(object sender, DrawListViewItemEventArgs e)
{
var isHighlighted = e.Item.Selected
|| e.ItemIndex == _doorHoverIndex
|| (doorListView.Focused && (e.State & ListViewItemStates.Focused) != 0);
var backColor = isHighlighted
? RowHighlightColor
: (e.ItemIndex % 2 == 0 ? RowEvenColor : RowOddColor);
using (var brush = new SolidBrush(backColor))
{
e.Graphics.FillRectangle(brush, e.Bounds);
}
var textColor = isHighlighted ? TextHighlightColor : TextRegularColor;
TextRenderer.DrawText(e.Graphics, e.Item.Text, e.Item.Font, e.Bounds,
textColor,
TextFormatFlags.VerticalCenter | TextFormatFlags.Left | TextFormatFlags.EndEllipsis);
e.DrawFocusRectangle();
}
private void DoorListView_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
var isHighlighted = e.Item.Selected
|| e.ItemIndex == _doorHoverIndex
|| (doorListView.Focused && (e.ItemState & ListViewItemStates.Focused) != 0);
var backColor = isHighlighted
? RowHighlightColor
: (e.ItemIndex % 2 == 0 ? RowEvenColor : RowOddColor);
using (var brush = new SolidBrush(backColor))
{
e.Graphics.FillRectangle(brush, e.Bounds);
}
Color textColor = TextRegularColor;
// 如果是状态列,根据状态设置颜色
if (e.ColumnIndex == 2) // 状态列
{
var stateText = e.SubItem.Text;
if (stateText == "打开")
{
textColor = StateOpenColor;
}
else if (stateText == "关闭")
{
textColor = StateClosedColor;
}
}
// 如果是目标控制列,按目标状态着色
else if (e.ColumnIndex == 3) // 控制目标列
{
var targetText = e.SubItem.Text;
if (targetText == "开")
{
textColor = StateOpenColor;
}
else
{
textColor = StateClosedColor;
}
}
// 其他列使用默认颜色
else
{
textColor = isHighlighted ? TextHighlightColor : TextRegularColor;
}
TextRenderer.DrawText(e.Graphics, e.SubItem.Text, e.SubItem.Font, e.Bounds,
textColor,
TextFormatFlags.VerticalCenter | TextFormatFlags.Left | TextFormatFlags.EndEllipsis);
}
private void DoorListView_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(245, 247, 250)), e.Bounds);
e.Graphics.DrawLine(new Pen(Color.FromArgb(220, 220, 220)),
e.Bounds.Left, e.Bounds.Bottom - 1, e.Bounds.Right, e.Bounds.Bottom - 1);
TextRenderer.DrawText(e.Graphics, e.Header.Text,
new Font("微软雅黑", 10.5F, FontStyle.Bold),
e.Bounds, Color.FromArgb(68, 68, 68),
TextFormatFlags.VerticalCenter | TextFormatFlags.Left | TextFormatFlags.HorizontalCenter);
}
/// <summary>
/// 刷新门列表
/// </summary>
private void RefreshDoorList()
{
doorListView.Items.Clear();
// 保存当前选中的门
(int ControllerIndex, int DoorIndex)? previousSelected = _selectedDoor;
_selectedDoor = null;
labelDoorInfo.Text = "请选择要控制的门";
// 获取所有门控制器
var mission = SimpleProject.proj?.Missions?.OfType<DoorMission>().FirstOrDefault();
if (mission == null)
{
return;
}
var doorSnapshot = mission.GetDoorMonitorSnapshot();
if (doorSnapshot.Count == 0)
{
return;
}
ListViewItem selectedItem = null;
foreach (var door in doorSnapshot)
{
var stateText = door.State == DoorState.Open ? "打开" : door.State == DoorState.Closed ? "关闭" : "未知";
var targetText = door.Target ? "开" : "关";
var sourceText = door.Source == DoorMission.ControlSource.Manual ? "手动" : "自动";
var remainText = door.Source == DoorMission.ControlSource.Manual && door.ManualRemainingSeconds.HasValue
? Math.Ceiling(door.ManualRemainingSeconds.Value).ToString()
: "-";
var carsText = door.CarsInArea.Count > 0 ? string.Join(", ", door.CarsInArea) : "无";
var item = new ListViewItem(door.ControllerIndex.ToString());
item.SubItems.Add(door.DoorIndex.ToString());
item.SubItems.Add(stateText);
item.SubItems.Add(targetText);
item.SubItems.Add(sourceText);
item.SubItems.Add(remainText);
item.SubItems.Add(carsText);
item.SubItems.Add(door.ControlAddress.ToString());
item.SubItems.Add(door.OpenStatusAddress.ToString());
item.Tag = (door.ControllerIndex, door.DoorIndex);
item.UseItemStyleForSubItems = false;
doorListView.Items.Add(item);
// 如果之前选中的门存在,恢复选中状态
if (previousSelected.HasValue &&
previousSelected.Value.ControllerIndex == door.ControllerIndex &&
previousSelected.Value.DoorIndex == door.DoorIndex)
{
selectedItem = item;
}
}
// 恢复选中状态
if (selectedItem != null)
{
selectedItem.Selected = true;
selectedItem.EnsureVisible();
doorListView_SelectedIndexChanged(doorListView, EventArgs.Empty);
}
}
/// <summary>
/// 门列表选择改变
/// </summary>
private void doorListView_SelectedIndexChanged(object sender, EventArgs e)
{
if (doorListView.SelectedItems.Count > 0)
{
var tag = doorListView.SelectedItems[0].Tag;
if (tag != null && tag is ValueTuple<int, int>)
{
var doorInfo = (ValueTuple<int, int>)tag;
_selectedDoor = doorInfo;
labelDoorInfo.Text = $"控制器编码: {doorInfo.Item1}, 门编码: {doorInfo.Item2}";
// 根据占用状态决定关闭按钮是否可用
var mission = SimpleProject.proj?.Missions?.OfType<DoorMission>().FirstOrDefault();
var carsInArea = mission?.GetCarsInArea(doorInfo.Item1, doorInfo.Item2) ?? Array.Empty<int>();
btnClose.Enabled = carsInArea.Count == 0;
}
else
{
_selectedDoor = null;
labelDoorInfo.Text = "请选择要控制的门";
btnClose.Enabled = true;
}
}
else
{
_selectedDoor = null;
labelDoorInfo.Text = "请选择要控制的门";
btnClose.Enabled = true;
}
}
/// <summary>
/// 打开门
/// </summary>
private void btnOpen_Click(object sender, EventArgs e)
{
if (!_selectedDoor.HasValue)
{
MessageBox.Show("请先选择要控制的门", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
try
{
var mission = SimpleProject.proj?.Missions?.OfType<DoorMission>().FirstOrDefault();
if (mission == null)
{
MessageBox.Show("未找到门控进程", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
var (controllerIndex, doorIndex) = _selectedDoor.Value;
// 手动控制:默认保持10秒
mission.SetManualDoorControl(controllerIndex, doorIndex, true);
MessageBox.Show($"控制器 {controllerIndex} 门 {doorIndex} 已设置手动打开(10秒)", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"设置门打开目标失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 关闭门
/// </summary>
private void btnClose_Click(object sender, EventArgs e)
{
if (!_selectedDoor.HasValue)
{
MessageBox.Show("请先选择要控制的门", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
try
{
var mission = SimpleProject.proj?.Missions?.OfType<DoorMission>().FirstOrDefault();
if (mission == null)
{
MessageBox.Show("未找到门控进程", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
var (controllerIndex, doorIndex) = _selectedDoor.Value;
// 车辆占用时禁止手动关闭
var success = mission.SetManualDoorControl(controllerIndex, doorIndex, false);
if (!success)
{
MessageBox.Show("门存在车辆占用,禁止手动关闭。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
MessageBox.Show($"控制器 {controllerIndex} 门 {doorIndex} 已设置手动关闭(10秒)", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"设置门关闭目标失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 清空车辆占用
/// </summary>
private void btnClearCars_Click(object sender, EventArgs e)
{
if (!_selectedDoor.HasValue)
{
MessageBox.Show("请先选择要清空占用的门", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
try
{
var mission = SimpleProject.proj?.Missions?.OfType<DoorMission>().FirstOrDefault();
if (mission == null)
{
MessageBox.Show("未找到门控进程", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
var (controllerIndex, doorIndex) = _selectedDoor.Value;
mission.ClearCarsInArea(controllerIndex, doorIndex);
MessageBox.Show($"控制器 {controllerIndex} 门 {doorIndex} 已清空占用", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
RefreshDoorList();
}
catch (Exception ex)
{
MessageBox.Show($"清空占用失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 定时刷新
/// </summary>
private void timerRefresh_Tick(object sender, EventArgs e)
{
RefreshDoorList();
}
/// <summary>
/// 窗体关闭事件
/// </summary>
private void DoorMonitor_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
timerRefresh.Stop();
e.Cancel = true;
this.Visible = false;
}
}
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
if (Visible)
{
EnsureRefreshActive();
}
else
{
timerRefresh.Stop();
}
}
}
}
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="timerRefresh.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>
@@ -0,0 +1,25 @@
using System;
namespace StandardScene.ExtendDevice.Door
{
/// <summary>
/// 门控制器类型特性,用于标记门控制器类型
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class DoorTypeAttribute : Attribute
{
/// <summary>
/// 类型名称
/// </summary>
public string Name { get; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="name">类型名称</param>
public DoorTypeAttribute(string name)
{
Name = name ?? throw new ArgumentNullException(nameof(name));
}
}
}