first commit
This commit is contained in:
@@ -0,0 +1,881 @@
|
||||
|
||||
|
||||
using JinYuan.Helper;
|
||||
using JinYuan.Models;
|
||||
using Language;
|
||||
using MiniExcelLibs;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace LargeSquareOne
|
||||
{
|
||||
public partial class VariableEditForm : MultiLanguageForm
|
||||
{
|
||||
|
||||
|
||||
private string variableConfigPath = Application.StartupPath + "\\Config\\Variable.xlsx";
|
||||
private string groupConfigPath = Application.StartupPath + "\\Config\\Group.xlsx";
|
||||
private List<string> groupNames = new List<string>();
|
||||
|
||||
private List<VariableConfig> Variables = new List<VariableConfig>();
|
||||
private VariableConfig editingConfig;
|
||||
private int PlcNum;
|
||||
|
||||
public VariableEditForm(int plcNum)
|
||||
{
|
||||
PlcNum = plcNum;
|
||||
InitializeComponent();
|
||||
|
||||
InitializeDataGridView();
|
||||
groupNames = GetGroupNames(PlcNum);
|
||||
Variables = GetALLVariables();
|
||||
LoadVariables();
|
||||
}
|
||||
|
||||
private void InitializeDataGridView()
|
||||
{
|
||||
variableTable.AutoGenerateColumns = false;
|
||||
variableTable.AllowUserToAddRows = false;
|
||||
variableTable.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
|
||||
variableTable.MultiSelect = false;
|
||||
variableTable.ReadOnly = false;
|
||||
|
||||
// 添加列
|
||||
variableTable.Columns.AddRange(new DataGridViewColumn[]
|
||||
{
|
||||
new DataGridViewTextBoxColumn
|
||||
{
|
||||
Name = "PlcNum",
|
||||
HeaderText = "PLC编号",
|
||||
Width = 80,
|
||||
ReadOnly = true,
|
||||
DataPropertyName = "PlcNum"
|
||||
},
|
||||
new DataGridViewComboBoxColumn
|
||||
{
|
||||
Name = "GroupName",
|
||||
HeaderText = "组名",
|
||||
Width = 100,
|
||||
DataPropertyName = "GroupName",
|
||||
DataSource = new List<string>(groupNames), // 使用新列表避免引用问题
|
||||
ValueType = typeof(string),
|
||||
ReadOnly = false,
|
||||
DefaultCellStyle = new DataGridViewCellStyle
|
||||
{
|
||||
BackColor = Color.FromArgb(14, 23, 38), // 深色背景
|
||||
ForeColor = Color.White, // 白色文字
|
||||
SelectionBackColor = Color.FromArgb(0, 122, 204), // 选中时的背景色
|
||||
SelectionForeColor = Color.White, // 选中时的文字颜色
|
||||
Font = new Font("微软雅黑", 9F) // 字体设置
|
||||
}
|
||||
},
|
||||
new DataGridViewTextBoxColumn
|
||||
{
|
||||
Name = "VarName",
|
||||
HeaderText = "变量名称",
|
||||
Width = 200,
|
||||
DataPropertyName = "VarName"
|
||||
},
|
||||
new DataGridViewTextBoxColumn
|
||||
{
|
||||
Name = "VarAddress",
|
||||
HeaderText = "变量地址",
|
||||
Width = 100,
|
||||
DataPropertyName = "VarAddress"
|
||||
},
|
||||
new DataGridViewTextBoxColumn
|
||||
{
|
||||
Name = "Start",
|
||||
HeaderText = "起始地址",
|
||||
Width = 100,
|
||||
DataPropertyName = "Start"
|
||||
},
|
||||
new DataGridViewComboBoxColumn
|
||||
{
|
||||
Name = "DataType",
|
||||
HeaderText = "数据类型",
|
||||
Width = 150,
|
||||
DataPropertyName = "DataType",
|
||||
Items = { "Short", "ByteArray" },
|
||||
DefaultCellStyle = new DataGridViewCellStyle
|
||||
{
|
||||
BackColor = Color.FromArgb(14, 23, 38), // 深色背景
|
||||
ForeColor = Color.White, // 白色文字
|
||||
SelectionBackColor = Color.FromArgb(0, 122, 204), // 选中时的背景色
|
||||
SelectionForeColor = Color.White, // 选中时的文字颜色
|
||||
Font = new Font("微软雅黑", 9F) // 字体设置
|
||||
}
|
||||
},
|
||||
new DataGridViewTextBoxColumn
|
||||
{
|
||||
Name = "OffsetOrLength",
|
||||
HeaderText = "长度偏移",
|
||||
Width = 80,
|
||||
DataPropertyName = "OffsetOrLength"
|
||||
},
|
||||
|
||||
new DataGridViewTextBoxColumn
|
||||
{
|
||||
Name = "Remark",
|
||||
HeaderText = "备注",
|
||||
Width = 120,
|
||||
DataPropertyName = "Remark",
|
||||
Visible = false
|
||||
},
|
||||
new DataGridViewButtonColumn
|
||||
{
|
||||
Name = "Edit",
|
||||
HeaderText = "操作",
|
||||
Width = 60,
|
||||
Text = "修改".Translated(),
|
||||
UseColumnTextForButtonValue = true
|
||||
},
|
||||
new DataGridViewButtonColumn
|
||||
{
|
||||
Name = "Delete",
|
||||
HeaderText = "",
|
||||
Width = 60,
|
||||
Text = "删除".Translated(),
|
||||
UseColumnTextForButtonValue = true
|
||||
}
|
||||
});
|
||||
|
||||
// 添加事件处理
|
||||
variableTable.CellBeginEdit += DataGridView_CellBeginEdit;
|
||||
variableTable.CellEndEdit += DataGridView_CellEndEdit;
|
||||
variableTable.CellContentClick += DataGridView_CellContentClick;
|
||||
//variableTable.RowPostPaint += DataGridView_RowPostPaint;
|
||||
}
|
||||
|
||||
|
||||
// 添加此方法从 Group.xlsx 获取组名称
|
||||
private List<string> GetGroupNames(int plcNum) // 添加 plcNum 参数
|
||||
{
|
||||
try
|
||||
{
|
||||
var groups = MiniExcel.Query<PlcGroupConfig>(groupConfigPath).ToList();
|
||||
// 根据 PLC 编号筛选,然后获取组名
|
||||
return groups.Where(g => g.PlcNum == plcNum)
|
||||
.Select(g => g.GroupName)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return new List<string> { "默认组".Translated() }; // 发生错误时返回默认组
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有通信组
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private List<VariableConfig> GetALLVariables()
|
||||
{
|
||||
try
|
||||
{
|
||||
var variables = MiniExcel.Query<VariableConfig>(variableConfigPath).ToList();
|
||||
|
||||
// 确保所有变量的组名都在groupNames列表中
|
||||
foreach (var variable in variables)
|
||||
{
|
||||
if (!groupNames.Contains(variable.GroupName))
|
||||
{
|
||||
variable.GroupName = groupNames[0]; // 如果组名无效,使用第一个有效的组名
|
||||
}
|
||||
}
|
||||
|
||||
return variables;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return new List<VariableConfig>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void LoadVariables()
|
||||
{
|
||||
try
|
||||
{
|
||||
var plcGroups = Variables.Where(g => g.PlcNum == PlcNum).ToList();
|
||||
|
||||
// 在设置DataSource之前清除原有的绑定
|
||||
variableTable.DataSource = null;
|
||||
|
||||
// 确保ComboBox列已经设置好数据源
|
||||
if (variableTable.Columns["GroupName"] is DataGridViewComboBoxColumn groupColumn)
|
||||
{
|
||||
groupColumn.DataSource = new List<string>(groupNames);
|
||||
}
|
||||
|
||||
// 设置新的数据源
|
||||
variableTable.DataSource = plcGroups;
|
||||
|
||||
// 刷新表格
|
||||
variableTable.Refresh();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ShowError($"加载变量失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void DataGridView_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
|
||||
{
|
||||
if (e.RowIndex < 0) return;
|
||||
|
||||
editingConfig = Variables[e.RowIndex];
|
||||
|
||||
// 禁止编辑PLC编号和组名列
|
||||
if (variableTable.Columns[e.ColumnIndex].Name == "PlcNum")
|
||||
{
|
||||
e.Cancel = true;
|
||||
}
|
||||
//if (variableTable.Columns[e.ColumnIndex].Name == "PlcNum" ||
|
||||
// variableTable.Columns[e.ColumnIndex].Name == "GroupName")
|
||||
//{
|
||||
// e.Cancel = true;
|
||||
//}
|
||||
}
|
||||
|
||||
private void DataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
|
||||
{
|
||||
if (e.RowIndex < 0 || e.RowIndex >= Variables.Count) return;
|
||||
|
||||
var config = Variables[e.RowIndex];
|
||||
var value = variableTable[e.ColumnIndex, e.RowIndex].Value;
|
||||
|
||||
try
|
||||
{
|
||||
UpdateConfigValue(config, variableTable.Columns[e.ColumnIndex].Name, value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ShowError($"更新数据失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateConfigValue(VariableConfig config, string columnName, object value)
|
||||
{
|
||||
switch (columnName)
|
||||
{
|
||||
case "GroupName":
|
||||
if (value != null && groupNames.Contains(value.ToString()))
|
||||
{
|
||||
config.GroupName = value.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("无效的组名".Translated());
|
||||
}
|
||||
break;
|
||||
|
||||
case "VarName":
|
||||
if (string.IsNullOrWhiteSpace(value?.ToString()))
|
||||
{
|
||||
throw new Exception("变量名不能为空".Translated());
|
||||
}
|
||||
if (Variables.Any(v => v != config &&
|
||||
v.PlcNum == config.PlcNum &&
|
||||
v.VarName.Equals(value.ToString(), StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
throw new Exception("变量名已存在".Translated());
|
||||
}
|
||||
config.VarName = value.ToString();
|
||||
break;
|
||||
|
||||
case "VarAddress":
|
||||
if (!ValidateVariableAddress(value?.ToString()))
|
||||
{
|
||||
throw new Exception("地址格式不正确,应以'D'开头后跟数字".Translated());
|
||||
}
|
||||
if (columnName == "VarAddress")
|
||||
{
|
||||
config.VarAddress = value.ToString();
|
||||
}
|
||||
|
||||
break;
|
||||
case "Start":
|
||||
if (!ValidateStartAddress(value?.ToString()))
|
||||
{
|
||||
throw new Exception("地址格式不正确,应是纯数字".Translated());
|
||||
}
|
||||
if (columnName == "Start")
|
||||
{
|
||||
config.Start = value.ToString();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "DataType":
|
||||
if (!ValidateDataType(value?.ToString()))
|
||||
{
|
||||
throw new Exception("不支持的数据类型".Translated());
|
||||
}
|
||||
config.DataType = value.ToString();
|
||||
break;
|
||||
|
||||
case "OffsetOrLength":
|
||||
if (!int.TryParse(value?.ToString(), out int length) || length <= 0)
|
||||
{
|
||||
throw new Exception("长度必须是大于0的数字".Translated());
|
||||
}
|
||||
config.OffsetOrLength = length;
|
||||
break;
|
||||
|
||||
case "Remark":
|
||||
config.Remark = value?.ToString() ?? string.Empty;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void DataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
|
||||
{
|
||||
if (e.RowIndex < 0) return;
|
||||
|
||||
// 获取当前行显示的数据
|
||||
var currentRow = variableTable.Rows[e.RowIndex];
|
||||
var config = (VariableConfig)currentRow.DataBoundItem;
|
||||
|
||||
// 找到在 TotalGroups 中的真实索引
|
||||
var realIndex = Variables.FindIndex(g =>
|
||||
g.PlcNum == config.PlcNum &&
|
||||
g.GroupName == config.GroupName &&
|
||||
g.Start == config.Start);
|
||||
|
||||
// 编辑按钮
|
||||
if (variableTable.Columns[e.ColumnIndex] is DataGridViewButtonColumn &&
|
||||
variableTable.Columns[e.ColumnIndex].Name == "Edit")
|
||||
{
|
||||
// 传递真实的索引,而不是显示的行索引
|
||||
HandleEdit(config, realIndex);
|
||||
}
|
||||
// 删除按钮
|
||||
else if (variableTable.Columns[e.ColumnIndex] is DataGridViewButtonColumn &&
|
||||
variableTable.Columns[e.ColumnIndex].Name == "Delete")
|
||||
{
|
||||
HandleDelete(config);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void HandleEdit(VariableConfig config, int rowIndex)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = MessageBox.Show("是否保存修改的配置?".Translated(), "确认保存".Translated(), MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
||||
|
||||
if (result != DialogResult.Yes) return;
|
||||
|
||||
if (!ValidateConfigAll(config)) return;
|
||||
|
||||
SaveConfigToExcel();
|
||||
LoadVariables();
|
||||
|
||||
ShowSuccess("配置保存成功".Translated());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ShowError($"保存失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleDelete(VariableConfig config)
|
||||
{
|
||||
var result = MessageBox.Show($"确定要删除该变量吗?\n PLC编号: [{config.PlcNum}],通信组: [{config.GroupName}],变量名: [{config.VarName}]", "确认删除", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
||||
|
||||
if (result == DialogResult.Yes)
|
||||
{
|
||||
try
|
||||
{
|
||||
Variables.Remove(config);
|
||||
SaveConfigToExcel();
|
||||
LoadVariables();
|
||||
ShowSuccess("删除成功".Translated());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ShowError($"删除失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveConfigToExcel()
|
||||
{
|
||||
try
|
||||
{
|
||||
string tempFilePath = Path.Combine(
|
||||
Path.GetDirectoryName(variableConfigPath),
|
||||
$"temp_{Path.GetFileName(variableConfigPath)}");
|
||||
|
||||
// 先保存到临时文件
|
||||
MiniExcel.SaveAs(tempFilePath, Variables);
|
||||
|
||||
if (!File.Exists(tempFilePath))
|
||||
{
|
||||
throw new Exception("创建临时文件失败".Translated());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (File.Exists(variableConfigPath))
|
||||
{
|
||||
File.Delete(variableConfigPath);
|
||||
}
|
||||
|
||||
File.Move(tempFilePath, variableConfigPath);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (File.Exists(tempFilePath))
|
||||
{
|
||||
File.Delete(tempFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"保存Excel文件时发生错误: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void BtnAdd_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 确保有可用的组名
|
||||
if (groupNames == null || groupNames.Count == 0)
|
||||
{
|
||||
ShowError("没有可用的组名,请先在Group.xlsx中添加组".Translated());
|
||||
return;
|
||||
}
|
||||
|
||||
string VarName = GenerateNewVarName();
|
||||
string VarAddress = FindNextAvailableAddress();
|
||||
|
||||
|
||||
var newVariable = new VariableConfig
|
||||
{
|
||||
VarName = VarName,
|
||||
VarAddress = VarAddress,
|
||||
Start = VarAddress.Substring(1, VarAddress.Length-1),
|
||||
DataType = "Short",
|
||||
OffsetOrLength = 1,
|
||||
PlcNum = PlcNum,
|
||||
GroupName = groupNames[0], // 使用第一个可用的组名
|
||||
Remark = ""
|
||||
};
|
||||
|
||||
if (!ValidateConfigAll(newVariable))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Variables.Add(newVariable);
|
||||
SaveConfigToExcel();
|
||||
LoadVariables();
|
||||
ShowSuccess("新建变量成功".Translated());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ShowError($"添加变量失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private string GenerateNewVarName()
|
||||
{
|
||||
int index = 1;
|
||||
string baseName = "新变量".Translated();
|
||||
string newName = baseName;
|
||||
|
||||
while (Variables.Any(v =>
|
||||
v.PlcNum == PlcNum &&
|
||||
v.VarName.Equals(newName, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
index++;
|
||||
newName = $"{baseName}{index}";
|
||||
}
|
||||
|
||||
return newName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取地址
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
private string FindNextAvailableAddress()
|
||||
{
|
||||
var plcVariables = Variables.Where(v => v.PlcNum == PlcNum).ToList();
|
||||
|
||||
if (!plcVariables.Any())
|
||||
{
|
||||
return "D0";
|
||||
}
|
||||
|
||||
int maxAddress = plcVariables.Max(v =>
|
||||
{
|
||||
int startAddr = int.Parse(v.VarAddress.Substring(1));
|
||||
return startAddr + v.OffsetOrLength;
|
||||
});
|
||||
|
||||
if (maxAddress >= 32675)
|
||||
{
|
||||
throw new Exception("没有可用的地址空间".Translated());
|
||||
}
|
||||
|
||||
return $"D{maxAddress}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证变量配置
|
||||
/// </summary>
|
||||
private bool ValidateConfigAll(VariableConfig config)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 基础验证
|
||||
if (string.IsNullOrWhiteSpace(config.VarName))
|
||||
{
|
||||
ShowError("变量名不能为空".Translated());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ValidateVariableAddress(config.VarAddress))
|
||||
{
|
||||
ShowError("变量地址格式不正确".Translated());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ValidateStartAddress(config.Start))
|
||||
{
|
||||
ShowError("起始地址格式不正确".Translated());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ValidateDataType(config.DataType))
|
||||
{
|
||||
ShowError("不支持的数据类型".Translated());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (config.OffsetOrLength <= 0)
|
||||
{
|
||||
ShowError("长度必须大于0".Translated());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 如果Variables为null,先初始化
|
||||
if (Variables == null)
|
||||
{
|
||||
Variables = new List<VariableConfig>();
|
||||
return true;
|
||||
}
|
||||
|
||||
// 获取同一PLC的其他变量
|
||||
var otherVariables = Variables.Where(v => v != config && v.PlcNum == config.PlcNum).ToList();
|
||||
|
||||
// 如果没有其他变量,则直接返回true
|
||||
if (!otherVariables.Any())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查重复
|
||||
if (otherVariables.Any(v => v.VarName.Equals(config.VarName, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
ShowError($"变量名 {config.VarName} 已存在");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (otherVariables.Any(v => v.VarAddress.Equals(config.VarAddress, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
ShowError($"变量地址 {config.VarAddress} 已存在");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 地址范围验证
|
||||
int startAddress;
|
||||
if (!int.TryParse(config.Start, out startAddress))
|
||||
{
|
||||
ShowError("无效的起始地址".Translated());
|
||||
return false;
|
||||
}
|
||||
|
||||
int endAddress = startAddress + config.OffsetOrLength - 1;
|
||||
if (endAddress > 32767)
|
||||
{
|
||||
ShowError($"地址范围超出限制,结束地址不能超过32767".Translated());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查地址范围冲突
|
||||
foreach (var other in otherVariables)
|
||||
{
|
||||
int otherStart;
|
||||
if (!int.TryParse(other.Start, out otherStart))
|
||||
{
|
||||
continue; // 跳过无效的地址
|
||||
}
|
||||
|
||||
int otherEnd = otherStart + other.OffsetOrLength - 1;
|
||||
if (!(endAddress < otherStart || startAddress > otherEnd))
|
||||
{
|
||||
ShowError($"地址范围与变量 \"{other.VarName}\" 冲突");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Instance.WriteError($"验证变量配置时发生错误: {ex}"); // 假设有日志记录器
|
||||
ShowError($"验证配置时发生错误,请检查输入是否正确".Translated());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 增强版的地址验证(支持多种地址格式)
|
||||
/// </summary>
|
||||
/// <param name="address">要验证的地址字符串</param>
|
||||
/// <returns>是否是有效的地址</returns>
|
||||
private bool ValidateVariableAddress(string address)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 检查地址是否为空
|
||||
if (string.IsNullOrWhiteSpace(address))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 使用正则表达式匹配地址格式
|
||||
// 支持的格式:
|
||||
// D0-D32767
|
||||
// M0-M8191
|
||||
// DB1.DBX0.0
|
||||
// 等其他格式
|
||||
var pattern = @"^([DMdm]\d+|DB\d+\.DBX\d+\.\d+)$";
|
||||
if (!System.Text.RegularExpressions.Regex.IsMatch(address, pattern))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 根据不同地址类型进行验证
|
||||
if (address.StartsWith("D", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// D区地址验证
|
||||
string numberPart = address.Substring(1);
|
||||
if (!int.TryParse(numberPart, out int dAddress) || dAddress < 0 || dAddress > 32767)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (address.StartsWith("M", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// M区地址验证
|
||||
string numberPart = address.Substring(1);
|
||||
if (!int.TryParse(numberPart, out int mAddress) || mAddress < 0 || mAddress > 8191)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (address.StartsWith("DB", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// DB块地址验证
|
||||
var parts = address.Split('.');
|
||||
if (parts.Length != 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证DB块号
|
||||
string dbNumberPart = parts[0].Substring(2);
|
||||
if (!int.TryParse(dbNumberPart, out int dbNumber) || dbNumber < 1 || dbNumber > 65535)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证偏移地址
|
||||
string offsetPart = parts[1].Substring(3);
|
||||
if (!int.TryParse(offsetPart, out int offset) || offset < 0 || offset > 65535)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证位地址
|
||||
string bitPart = parts[2];
|
||||
if (!int.TryParse(bitPart, out int bit) || bit < 0 || bit > 7)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 验证起始地址(纯数字格式)
|
||||
/// </summary>
|
||||
/// <param name="startAddress">要验证的起始地址字符串</param>
|
||||
/// <returns>是否是有效的起始地址</returns>
|
||||
private bool ValidateStartAddress(string startAddress)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 检查地址是否为空
|
||||
if (string.IsNullOrWhiteSpace(startAddress))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证是否为纯数字
|
||||
if (!int.TryParse(startAddress, out int addressNum))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查地址范围(根据实际需求调整范围)
|
||||
if (addressNum < 0 || addressNum > 32767)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 验证数据类型
|
||||
/// </summary>
|
||||
private bool ValidateDataType(string dataType)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dataType))
|
||||
return false;
|
||||
|
||||
// 根据实际支持的数据类型列表进行验证
|
||||
string[] validTypes = new[] { "Bit", "Byte", "ByteArray", "Short", "Arrshort", "Word", "DWord", "Int", "DInt", "Real", "String" };
|
||||
return validTypes.Contains(dataType, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private string FindAddressGap(int requiredLength = 1)
|
||||
{
|
||||
// 获取当前PLC的所有变量,并按起始地址排序
|
||||
var plcVariables = Variables
|
||||
.Where(v => v.PlcNum == PlcNum)
|
||||
.Select(v => new
|
||||
{
|
||||
Start = int.Parse(v.VarAddress.Substring(1)),
|
||||
End = int.Parse(v.VarAddress.Substring(1)) + v.OffsetOrLength - 1
|
||||
})
|
||||
.OrderBy(v => v.Start)
|
||||
.ToList();
|
||||
|
||||
// 如果没有变量,返回起始地址
|
||||
if (!plcVariables.Any())
|
||||
{
|
||||
return "D0";
|
||||
}
|
||||
|
||||
// 检查第一个变量之前是否有足够空间
|
||||
if (plcVariables.First().Start >= requiredLength)
|
||||
{
|
||||
return "D0";
|
||||
}
|
||||
|
||||
// 检查变量之间的间隔
|
||||
for (int i = 0; i < plcVariables.Count - 1; i++)
|
||||
{
|
||||
int gapStart = plcVariables[i].End + 1;
|
||||
int gapEnd = plcVariables[i + 1].Start - 1;
|
||||
|
||||
if (gapEnd - gapStart + 1 >= requiredLength)
|
||||
{
|
||||
return $"D{gapStart}";
|
||||
}
|
||||
}
|
||||
|
||||
// 检查最后一个变量之后是否有足够空间
|
||||
int lastEnd = plcVariables.Last().End;
|
||||
if (lastEnd + requiredLength <= 32675)
|
||||
{
|
||||
return $"D{lastEnd + 1}";
|
||||
}
|
||||
|
||||
throw new Exception("没有找到足够大的地址空间".Translated());
|
||||
}
|
||||
|
||||
// 错误提示
|
||||
private void ShowError(string message)
|
||||
{
|
||||
MessageBox.Show(message, "验证错误".Translated(), MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
|
||||
// 成功提示
|
||||
private void ShowSuccess(string message)
|
||||
{
|
||||
MessageBox.Show(message, "成功".Translated(), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
private void btn_Close_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
|
||||
#region 减少闪烁
|
||||
protected override CreateParams CreateParams
|
||||
{
|
||||
get
|
||||
{
|
||||
CreateParams cp = base.CreateParams;
|
||||
cp.ExStyle |= 0x02000000;
|
||||
return cp;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 无边框拖动
|
||||
private Point mPoint;
|
||||
private void Panel_MouseDown(object sender, MouseEventArgs e)
|
||||
{
|
||||
mPoint = new Point(e.X, e.Y);
|
||||
}
|
||||
|
||||
private void Panel_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.Button == MouseButtons.Left)
|
||||
{
|
||||
this.Location = new Point(this.Location.X + e.X - mPoint.X, this.Location.Y + e.Y - mPoint.Y);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user