Files
StandardSence/StandardScene.Core/ExtendDevice/ButtonBox/ButtonBoxManager.cs
T

1001 lines
37 KiB
C#
Raw Normal View History

2026-06-14 11:19:15 +08:00
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using StandardScene.Utils;
namespace StandardScene.ExtendDevice.ButtonBox
{
public partial class ButtonBoxManager : Form
{
private static ButtonBoxManager _instance = null;
private static readonly object _lock = new object();
private const string DataFileName = "ButtonBoxConfig.json";
private string _dataFilePath;
private List<ButtonBoxModel> _buttonBoxes = new List<ButtonBoxModel>();
private ButtonBoxModel _currentButtonBox = null;
private ButtonModel _currentButton = null;
/// <summary>
/// 获取单例实例
/// </summary>
public static ButtonBoxManager Instance
{
get
{
if (_instance == null || _instance.IsDisposed)
{
lock (_lock)
{
if (_instance == null || _instance.IsDisposed)
{
_instance = new ButtonBoxManager();
}
}
}
return _instance;
}
}
/// <summary>
/// 私有构造函数,确保单例模式
/// </summary>
private ButtonBoxManager()
{
InitializeComponent();
// 设置数据文件路径
_dataFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, DataFileName);
}
private void ButtonBoxManager_Load(object sender, EventArgs e)
{
// 设置ListView的视觉样式
SetupListViewStyles();
// 设置按钮的鼠标悬停效果
SetupButtonHoverEffects();
// 初始化类型下拉框
InitializeTypeComboBox();
// 初始化触发状态下拉框
InitializeTriggerStateComboBox();
LoadData();
RefreshButtonBoxList();
}
/// <summary>
/// 初始化触发状态下拉框
/// </summary>
private void InitializeTriggerStateComboBox()
{
comboBoxTriggerState.Items.Clear();
// 添加ButtonState枚举的所有值
foreach (ButtonState state in Enum.GetValues(typeof(ButtonState)))
{
comboBoxTriggerState.Items.Add(state.ToString());
}
// 如果没有选中项,默认选择第一个
if (comboBoxTriggerState.Items.Count > 0 && comboBoxTriggerState.SelectedIndex == -1)
{
comboBoxTriggerState.SelectedIndex = 0;
}
}
/// <summary>
/// 初始化类型下拉框
/// </summary>
private void InitializeTypeComboBox()
{
comboBoxType.Items.Clear();
try
{
// 获取当前命名空间下所有继承自BasicButtonBox的类
// 跨程序集发现:按钮盒具体类型可能位于卫星插件 dllStandardScene.Devices.ButtonBox),
// 用内核同款全域类型发现替代仅扫当前程序集的 GetExecutingAssembly。
var buttonBoxTypes = SimpleLite.Utils.UiTypeDiscovery.AllTypes()
.Where(t => t.IsClass
&& !t.IsAbstract
&& t.Namespace == typeof(BasicButtonBox).Namespace
&& t.IsSubclassOf(typeof(BasicButtonBox)))
.OrderBy(t => t.Name)
.ToList();
foreach (var type in buttonBoxTypes)
{
comboBoxType.Items.Add(type.Name);
}
// 如果没有找到任何类型,添加默认选项
if (comboBoxType.Items.Count == 0)
{
comboBoxType.Items.Add("BasicButtonBox");
}
}
catch (Exception ex)
{
MessageBox.Show($"Failed to init type dropdown: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
comboBoxType.Items.Add("BasicButtonBox");
}
}
private int _buttonBoxHoverIndex = -1;
private int _buttonHoverIndex = -1;
/// <summary>
/// 设置ListView的视觉样式
/// </summary>
private void SetupListViewStyles()
{
SetupListView(buttonBoxListView,
ButtonBoxListView_DrawItem,
ButtonBoxListView_DrawSubItem,
ButtonBoxListView_DrawColumnHeader,
ButtonBoxListView_MouseMove,
ButtonBoxListView_MouseLeave);
SetupListView(buttonListView,
ButtonListView_DrawItem,
ButtonListView_DrawSubItem,
ButtonListView_DrawColumnHeader,
ButtonListView_MouseMove,
ButtonListView_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 ButtonBoxListView_MouseMove(object sender, MouseEventArgs e)
{
UpdateHoverIndex(buttonBoxListView, e, true);
}
private void ButtonBoxListView_MouseLeave(object sender, EventArgs e)
{
ResetHoverIndex(buttonBoxListView, true);
}
private void ButtonListView_MouseMove(object sender, MouseEventArgs e)
{
UpdateHoverIndex(buttonListView, e, false);
}
private void ButtonListView_MouseLeave(object sender, EventArgs e)
{
ResetHoverIndex(buttonListView, false);
}
private void UpdateHoverIndex(ListView listView, MouseEventArgs e, bool isButtonBoxList)
{
var hoveredItem = listView.GetItemAt(e.X, e.Y);
int newIndex = hoveredItem?.Index ?? -1;
if (isButtonBoxList)
{
if (_buttonBoxHoverIndex != newIndex)
{
_buttonBoxHoverIndex = newIndex;
listView.Invalidate();
}
}
else
{
if (_buttonHoverIndex != newIndex)
{
_buttonHoverIndex = newIndex;
listView.Invalidate();
}
}
}
private void ResetHoverIndex(ListView listView, bool isButtonBoxList)
{
if (isButtonBoxList)
{
if (_buttonBoxHoverIndex != -1)
{
_buttonBoxHoverIndex = -1;
listView.Invalidate();
}
}
else
{
if (_buttonHoverIndex != -1)
{
_buttonHoverIndex = -1;
listView.Invalidate();
}
}
}
/// <summary>
/// 按钮盒ListView绘制项
/// </summary>
private void ButtonBoxListView_DrawItem(object sender, DrawListViewItemEventArgs e)
{
var isHighlighted = e.Item.Selected
|| e.ItemIndex == _buttonBoxHoverIndex
|| (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();
}
/// <summary>
/// 按钮盒ListView绘制子项
/// </summary>
private void ButtonBoxListView_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
var isHighlighted = e.Item.Selected
|| e.ItemIndex == _buttonBoxHoverIndex
|| (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);
}
/// <summary>
/// 按钮盒ListView绘制列标题
/// </summary>
private void ButtonBoxListView_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>
/// 按钮ListView绘制项
/// </summary>
private void ButtonListView_DrawItem(object sender, DrawListViewItemEventArgs e)
{
var isHighlighted = e.Item.Selected
|| e.ItemIndex == _buttonHoverIndex
|| (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();
}
/// <summary>
/// 按钮ListView绘制子项
/// </summary>
private void ButtonListView_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
var isHighlighted = e.Item.Selected
|| e.ItemIndex == _buttonHoverIndex
|| (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);
}
/// <summary>
/// 按钮ListView绘制列标题
/// </summary>
private void ButtonListView_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 SetupButtonHoverEffects()
{
// 按钮的悬停效果现在通过FlatAppearance属性在Designer中设置
// 这里可以添加其他额外的效果,如工具提示等
}
/// <summary>
/// 刷新按钮盒列表
/// </summary>
private void RefreshButtonBoxList()
{
buttonBoxListView.Items.Clear();
foreach (var box in _buttonBoxes)
{
var item = new ListViewItem(box.Index.ToString());
item.SubItems.Add(box.Ip);
item.SubItems.Add(box.Port.ToString());
item.SubItems.Add(box.Type);
item.Tag = box;
item.UseItemStyleForSubItems = false;
buttonBoxListView.Items.Add(item);
}
}
/// <summary>
/// 刷新按钮列表
/// </summary>
private void RefreshButtonList()
{
buttonListView.Items.Clear();
if (_currentButtonBox != null)
{
foreach (var button in _currentButtonBox.Buttons)
{
var item = new ListViewItem(button.Index.ToString());
item.SubItems.Add(button.TriggerState);
item.SubItems.Add(button.TriggerDelay.ToString());
item.SubItems.Add(button.TriggerMission);
item.SubItems.Add(button.TriggerMethod);
item.SubItems.Add(button.TriggerMethodParams);
item.Tag = button;
item.UseItemStyleForSubItems = false;
buttonListView.Items.Add(item);
}
}
}
/// <summary>
/// 按钮盒列表选择改变
/// </summary>
private void buttonBoxListView_SelectedIndexChanged(object sender, EventArgs e)
{
if (buttonBoxListView.SelectedItems.Count > 0)
{
_currentButtonBox = buttonBoxListView.SelectedItems[0].Tag as ButtonBoxModel;
if (_currentButtonBox != null)
{
// 填充按钮盒编辑区域
textBoxIp.Text = _currentButtonBox.Ip;
textBoxPort.Text = _currentButtonBox.Port.ToString();
textBoxBoxIndex.Text = _currentButtonBox.Index.ToString();
// 设置类型下拉框
if (comboBoxType.Items.Contains(_currentButtonBox.Type))
{
comboBoxType.SelectedItem = _currentButtonBox.Type;
}
else
{
comboBoxType.SelectedIndex = comboBoxType.Items.Count > 0 ? 0 : -1;
}
// 刷新按钮列表
RefreshButtonList();
}
}
else
{
_currentButtonBox = null;
ClearButtonBoxFields();
buttonListView.Items.Clear();
}
}
/// <summary>
/// 按钮列表选择改变
/// </summary>
private void buttonListView_SelectedIndexChanged(object sender, EventArgs e)
{
if (buttonListView.SelectedItems.Count > 0)
{
_currentButton = buttonListView.SelectedItems[0].Tag as ButtonModel;
if (_currentButton != null)
{
// 填充按钮编辑区域
textBoxButtonIndex.Text = _currentButton.Index.ToString();
textBoxTriggerMission.Text = _currentButton.TriggerMission;
textBoxTriggerMethod.Text = _currentButton.TriggerMethod;
textBoxTriggerMethodParams.Text = _currentButton.TriggerMethodParams;
// 设置触发状态下拉框
if (comboBoxTriggerState.Items.Contains(_currentButton.TriggerState))
{
comboBoxTriggerState.SelectedItem = _currentButton.TriggerState;
}
else
{
comboBoxTriggerState.SelectedIndex = comboBoxTriggerState.Items.Count > 0 ? 0 : -1;
}
textBoxTriggerDelay.Text = _currentButton.TriggerDelay.ToString();
}
}
else
{
_currentButton = null;
ClearButtonFields();
}
}
/// <summary>
/// 添加按钮盒
/// </summary>
private void btnAddButtonBox_Click(object sender, EventArgs e)
{
try
{
// 获取输入框的值
string ip = textBoxIp.Text.Trim();
string portText = textBoxPort.Text.Trim();
string indexText = textBoxBoxIndex.Text.Trim();
string type = comboBoxType.SelectedItem?.ToString() ?? string.Empty;
// 确定要使用的值:如果输入框不为空则使用输入值,否则使用默认值
int newIndex;
if (!string.IsNullOrWhiteSpace(indexText))
{
if (!int.TryParse(indexText, out newIndex))
{
MessageBox.Show("Index must be numeric", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
else
{
newIndex = _buttonBoxes.Count > 0 ? _buttonBoxes.Max(b => b.Index) + 1 : 1;
}
string newIp;
if (!string.IsNullOrWhiteSpace(ip))
{
// 验证IP地址格式
if (!IsValidIpAddress(ip))
{
MessageBox.Show("Invalid IP address, e.g. 192.168.1.100", "Error", 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("Port must be numeric", "Error", 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() : "BasicButtonBox";
}
// 检查编码是否重复
if (_buttonBoxes.Any(b => b.Index == newIndex))
{
MessageBox.Show($"Index {newIndex} already exists, use another", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 检查IP地址是否重复
if (_buttonBoxes.Any(b => b.Ip == newIp))
{
MessageBox.Show($"IP {newIp} already exists, use another", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
var newBox = new ButtonBoxModel
{
Index = newIndex,
Ip = newIp,
Port = newPort,
Type = newType
};
_buttonBoxes.Add(newBox);
RefreshButtonBoxList();
SaveData();
// 选中新添加的按钮盒
foreach (ListViewItem item in buttonBoxListView.Items)
{
if (item.Tag == newBox)
{
item.Selected = true;
item.EnsureVisible();
break;
}
}
}
catch (Exception ex)
{
MessageBox.Show($"Failed to add button box: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 删除按钮盒
/// </summary>
private void btnDeleteButtonBox_Click(object sender, EventArgs e)
{
if (_currentButtonBox == null)
{
MessageBox.Show("Please select a button box to delete", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
var result = MessageBox.Show($"Delete button box with index {_currentButtonBox.Index}?", "Confirm delete",
MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
_buttonBoxes.Remove(_currentButtonBox);
_currentButtonBox = null;
ClearButtonBoxFields();
RefreshButtonBoxList();
buttonListView.Items.Clear();
SaveData();
}
}
/// <summary>
/// 保存按钮盒
/// </summary>
private void btnSaveButtonBox_Click(object sender, EventArgs e)
{
if (_currentButtonBox == null)
{
MessageBox.Show("Please select a button box to save", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
try
{
string newIp = textBoxIp.Text.Trim();
// 验证IP地址格式
if (!IsValidIpAddress(newIp))
{
MessageBox.Show("Invalid IP address, e.g. 192.168.1.100", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (!int.TryParse(textBoxPort.Text, out int port))
{
MessageBox.Show("Port must be numeric", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
_currentButtonBox.Port = port;
if (!int.TryParse(textBoxBoxIndex.Text, out int index))
{
MessageBox.Show("Index must be numeric", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 检查编码是否重复(排除当前项)
if (_buttonBoxes.Any(b => b.Index == index && b != _currentButtonBox))
{
MessageBox.Show($"Index {index} already exists, use another", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 检查IP地址是否重复(排除当前项)
if (_buttonBoxes.Any(b => b.Ip == newIp && b != _currentButtonBox))
{
MessageBox.Show($"IP {newIp} already exists, use another", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
_currentButtonBox.Index = index;
_currentButtonBox.Type = comboBoxType.SelectedItem?.ToString() ?? string.Empty;
_currentButtonBox.Ip = newIp;
RefreshButtonBoxList();
SaveData();
MessageBox.Show("Saved", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"Save failed: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 添加按钮
/// </summary>
private void btnAddButton_Click(object sender, EventArgs e)
{
if (_currentButtonBox == null)
{
MessageBox.Show("Please select a button box first", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
try
{
// 获取输入框的值
string indexText = textBoxButtonIndex.Text.Trim();
string triggerMission = textBoxTriggerMission.Text.Trim();
string triggerMethod = textBoxTriggerMethod.Text.Trim();
string triggerMethodParams = textBoxTriggerMethodParams.Text.Trim();
string triggerState = comboBoxTriggerState.SelectedItem?.ToString() ?? string.Empty;
string triggerDelayText = textBoxTriggerDelay.Text.Trim();
// 确定要使用的值:如果输入框不为空则使用输入值,否则使用默认值
int newIndex;
if (!string.IsNullOrWhiteSpace(indexText))
{
if (!int.TryParse(indexText, out newIndex))
{
MessageBox.Show("Button index must be numeric", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
else
{
newIndex = _currentButtonBox.Buttons.Count > 0
? _currentButtonBox.Buttons.Max(b => b.Index) + 1
: 1;
}
// 检查按钮编码是否重复
if (_currentButtonBox.Buttons.Any(b => b.Index == newIndex))
{
MessageBox.Show($"Button index {newIndex} already exists, use another", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 解析触发延迟(必须是ushort类型,范围0-65535
ushort triggerDelay = 0;
if (!string.IsNullOrWhiteSpace(triggerDelayText))
{
if (!ushort.TryParse(triggerDelayText, out triggerDelay))
{
MessageBox.Show("Trigger delay must be 0-65535", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
var newButton = new ButtonModel
{
Index = newIndex,
TriggerMission = triggerMission,
TriggerMethod = triggerMethod,
TriggerMethodParams = triggerMethodParams,
TriggerState = triggerState,
TriggerDelay = triggerDelay
};
_currentButtonBox.Buttons.Add(newButton);
RefreshButtonList();
SaveData();
// 选中新添加的按钮
foreach (ListViewItem item in buttonListView.Items)
{
if (item.Tag == newButton)
{
item.Selected = true;
item.EnsureVisible();
break;
}
}
}
catch (Exception ex)
{
MessageBox.Show($"Failed to add button: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 删除按钮
/// </summary>
private void btnDeleteButton_Click(object sender, EventArgs e)
{
if (_currentButtonBox == null)
{
MessageBox.Show("Please select a button box first", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
if (_currentButton == null)
{
MessageBox.Show("Please select a button to delete", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
var result = MessageBox.Show($"Delete button with index {_currentButton.Index}?", "Confirm delete",
MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
_currentButtonBox.Buttons.Remove(_currentButton);
_currentButton = null;
ClearButtonFields();
RefreshButtonList();
SaveData();
}
}
/// <summary>
/// 保存按钮
/// </summary>
private void btnSaveButton_Click(object sender, EventArgs e)
{
if (_currentButtonBox == null)
{
MessageBox.Show("Please select a button box first", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
if (_currentButton == null)
{
MessageBox.Show("Please select a button to save", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
try
{
if (!int.TryParse(textBoxButtonIndex.Text, out int index))
{
MessageBox.Show("Button index must be numeric", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 检查按钮编码是否重复(排除当前按钮)
if (_currentButtonBox.Buttons.Any(b => b.Index == index && b != _currentButton))
{
MessageBox.Show($"Button index {index} already exists, use another", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 验证触发延迟(必须是ushort类型,范围0-65535
if (!ushort.TryParse(textBoxTriggerDelay.Text, out ushort triggerDelay))
{
MessageBox.Show("Trigger delay must be 0-65535", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
_currentButton.Index = index;
_currentButton.TriggerMission = textBoxTriggerMission.Text;
_currentButton.TriggerMethod = textBoxTriggerMethod.Text;
_currentButton.TriggerMethodParams = textBoxTriggerMethodParams.Text;
_currentButton.TriggerState = comboBoxTriggerState.SelectedItem?.ToString() ?? string.Empty;
_currentButton.TriggerDelay = triggerDelay;
RefreshButtonList();
SaveData();
MessageBox.Show("Saved", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"Save failed: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 清空按钮盒字段
/// </summary>
private void ClearButtonBoxFields()
{
textBoxIp.Text = string.Empty;
textBoxPort.Text = string.Empty;
textBoxBoxIndex.Text = string.Empty;
comboBoxType.SelectedIndex = -1;
}
/// <summary>
/// 清空按钮字段
/// </summary>
private void ClearButtonFields()
{
textBoxButtonIndex.Text = string.Empty;
textBoxTriggerMission.Text = string.Empty;
textBoxTriggerMethod.Text = string.Empty;
textBoxTriggerMethodParams.Text = string.Empty;
comboBoxTriggerState.SelectedIndex = comboBoxTriggerState.Items.Count > 0 ? 0 : -1;
textBoxTriggerDelay.Text = string.Empty;
}
/// <summary>
/// 加载数据
/// </summary>
private void LoadData()
{
try
{
if (File.Exists(_dataFilePath))
{
var jsonContent = File.ReadAllText(_dataFilePath, Encoding.UTF8);
if (!string.IsNullOrWhiteSpace(jsonContent))
{
_buttonBoxes = jsonContent.JsonTo<List<ButtonBoxModel>>();
if (_buttonBoxes == null)
{
_buttonBoxes = new List<ButtonBoxModel>();
}
}
else
{
_buttonBoxes = new List<ButtonBoxModel>();
}
}
else
{
_buttonBoxes = new List<ButtonBoxModel>();
}
}
catch (Exception ex)
{
MessageBox.Show($"Load data failed: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
_buttonBoxes = new List<ButtonBoxModel>();
}
}
/// <summary>
/// 保存数据
/// </summary>
private void SaveData()
{
try
{
var jsonContent = _buttonBoxes.ToJson();
File.WriteAllText(_dataFilePath, jsonContent, Encoding.UTF8);
}
catch (Exception ex)
{
MessageBox.Show($"Save data failed: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 验证IP地址格式
/// </summary>
/// <param name="ipAddress">IP地址字符串</param>
/// <returns>如果格式正确返回true,否则返回false</returns>
private bool IsValidIpAddress(string ipAddress)
{
if (string.IsNullOrWhiteSpace(ipAddress))
{
return false;
}
// 使用正则表达式验证IP地址格式(IPv4)
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))
{
// 使用System.Net.IPAddress.TryParse进行二次验证
IPAddress address;
return IPAddress.TryParse(ipAddress, out address) && address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork;
}
return false;
}
/// <summary>
/// 窗体关闭事件
/// </summary>
private void ButtonBoxManager_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
// 关闭前保存数据
SaveData();
e.Cancel = true;
this.Visible = false;
}
}
}
}