diff --git a/WindowsFormsApp6/MainForm.cs b/WindowsFormsApp6/MainForm.cs index 25914a9..0c20ee1 100644 --- a/WindowsFormsApp6/MainForm.cs +++ b/WindowsFormsApp6/MainForm.cs @@ -21,7 +21,7 @@ namespace WindowsFormsApp6 private Form2 form2Instance; private Form3 form3Instance; private System.Windows.Forms.Timer timeUpdateTimer; - + // 串口和Modbus相关 private SerialPort _serialPort; private IModbusMaster _modbusMaster; @@ -29,10 +29,10 @@ namespace WindowsFormsApp6 // Form1历史数据缓存(用于累积显示) private List form1TimeValues = new List(); - + // Form2历史数据缓存(用于累积显示) private List form2SampleDataList = new List(); - + // Form2单个试样数据结构 private class Form2SampleData { @@ -52,7 +52,7 @@ namespace WindowsFormsApp6 InitializeSerialPortAndModbus(); CenterInfoControls(); CenterBottomButtons(); - + // 监听窗体大小变化以重新居中按钮 this.Resize += (s, e) => CenterBottomButtons(); } @@ -62,7 +62,7 @@ namespace WindowsFormsApp6 // 初始化时间显示 textBox7.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); textBox7.ReadOnly = true; // 设置为只读 - + // 创建计时器,每秒更新一次 timeUpdateTimer = new System.Windows.Forms.Timer(); timeUpdateTimer.Interval = 1000; @@ -118,16 +118,16 @@ namespace WindowsFormsApp6 // 打开串口 _serialPort.Open(); - + // 创建Modbus RTU主站 _modbusMaster = ModbusSerialMaster.CreateRtu(_serialPort); _modbusMaster.Transport.WaitToRetryMilliseconds = 200; _modbusMaster.Transport.Retries = 1; _modbusMaster.Transport.ReadTimeout = 500; - + // 启动定时读取 _readTimer.Start(); - + ShowInfoMsg($"串口 {portName} 初始化成功"); return true; } @@ -251,7 +251,7 @@ namespace WindowsFormsApp6 // 读取三个信号量(M103, M252, M310) // Modbus地址:M103 = 103, M252 = 252, M310 = 310 // 使用ReadCoils读取线圈状态(M区) - + bool signalM103 = ReadCoil(slaveId, 103); // Form1信号量 bool signalM252 = ReadCoil(slaveId, 252); // Form2 数据采集信号量 bool signalM253 = ReadCoil(slaveId, 253); // Form2 设备停止信号量 @@ -335,10 +335,10 @@ namespace WindowsFormsApp6 // 使用反射获取Form1的私有字段 var sampleDataTableField = form1Instance.GetType() .GetField("sampleDataTable", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); - + var currentSampleCountField = form1Instance.GetType() .GetField("currentSampleCount", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); - + if (sampleDataTableField == null || currentSampleCountField == null) { System.Diagnostics.Debug.WriteLine("无法获取Form1的私有字段"); @@ -347,7 +347,7 @@ namespace WindowsFormsApp6 DataTable dataTable = sampleDataTableField.GetValue(form1Instance) as DataTable; int currentSampleCount = (int)currentSampleCountField.GetValue(form1Instance); - + if (dataTable == null) { System.Diagnostics.Debug.WriteLine("DataTable为空"); @@ -356,7 +356,7 @@ namespace WindowsFormsApp6 // 转换寄存器值为实际时间(秒) double timeValue = registers[0]; - + // 检查NaN if (double.IsNaN(timeValue) || double.IsInfinity(timeValue)) { @@ -366,7 +366,7 @@ namespace WindowsFormsApp6 // 添加到历史数据 form1TimeValues.Add(timeValue); - + // 新试样的索引 int newSampleIndex = form1TimeValues.Count; @@ -378,11 +378,11 @@ namespace WindowsFormsApp6 { dataTable.Columns.Add($"试样{newSampleIndex}", typeof(double)); } - + // 更新currentSampleCount currentSampleCount = newSampleIndex; currentSampleCountField.SetValue(form1Instance, currentSampleCount); - + // 重新初始化DataGridView以显示新列 this.Invoke(new Action(() => { @@ -390,7 +390,7 @@ namespace WindowsFormsApp6 .GetMethod("InitializeDataGridView", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); initMethod?.Invoke(form1Instance, null); })); - + // 重新获取DataTable(可能已重新绑定) dataTable = sampleDataTableField.GetValue(form1Instance) as DataTable; } @@ -401,7 +401,7 @@ namespace WindowsFormsApp6 // 创建时间行 DataRow timeRow = dataTable.NewRow(); timeRow["序号"] = "时间(s)"; - + // 填充所有历史数据 for (int i = 0; i < form1TimeValues.Count; i++) { @@ -410,7 +410,7 @@ namespace WindowsFormsApp6 timeRow[$"试样{i + 1}"] = form1TimeValues[i]; } } - + // 其余列设为空 for (int i = form1TimeValues.Count + 1; i <= currentSampleCount; i++) { @@ -419,13 +419,13 @@ namespace WindowsFormsApp6 timeRow[$"试样{i}"] = DBNull.Value; } } - + dataTable.Rows.Add(timeRow); // 计算并添加平均值行:每5个试样一组 int totalSamples = form1TimeValues.Count; int groupCount = (int)Math.Ceiling((double)totalSamples / 5.0); - + for (int groupIndex = 0; groupIndex < groupCount; groupIndex++) { int startSample = groupIndex * 5 + 1; @@ -444,7 +444,7 @@ namespace WindowsFormsApp6 if (validCount > 0) { double groupAvg = groupSum / validCount; - + // 检查NaN if (double.IsNaN(groupAvg) || double.IsInfinity(groupAvg)) { @@ -454,7 +454,7 @@ namespace WindowsFormsApp6 // 创建平均值行 DataRow avgRow = dataTable.NewRow(); avgRow["序号"] = $"平均时间(s) 试样{startSample}-{endSample}"; - + // 只在该组第一个试样列显示平均值,其他列设置为DBNull for (int i = 1; i <= currentSampleCount; i++) { @@ -471,7 +471,7 @@ namespace WindowsFormsApp6 } } } - + dataTable.Rows.Add(avgRow); } } @@ -484,7 +484,7 @@ namespace WindowsFormsApp6 .GetMethod("RefreshDataGridView", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); refreshMethod?.Invoke(form1Instance, null); })); - + System.Diagnostics.Debug.WriteLine($"Form1数据读取成功:试样{newSampleIndex},时间={timeValue:F2}秒,累计{totalSamples}个试样"); } catch (Exception ex) @@ -506,30 +506,33 @@ namespace WindowsFormsApp6 // 读取初始重量(D420,2个寄存器,浮点数,单位:g,精度0.01g) ushort[] initialWeightReg = _modbusMaster.ReadHoldingRegisters(slaveId, 420, 2); double initialWeight = ConvertRegistersToDouble(initialWeightReg); - + initialWeight = ModbusUshortToFloat(initialWeightReg[1], initialWeightReg[0]); + // 读取浸润后重量(D422,2个寄存器,浮点数,单位:g,精度0.01g) ushort[] afterWeightReg = _modbusMaster.ReadHoldingRegisters(slaveId, 422, 2); double afterWeight = ConvertRegistersToDouble(afterWeightReg); - + afterWeight = ModbusUshortToFloat(afterWeightReg[1], afterWeightReg[0]); + // 读取浸润时间(D402,1个寄存器,整数,单位:秒) ushort[] soakTimeReg = _modbusMaster.ReadHoldingRegisters(slaveId, 402, 1); int soakTime = ConvertSingleRegisterToInt(soakTimeReg[0]); - + // 读取悬挂时间(D406,1个寄存器,整数,单位:秒) ushort[] hangTimeReg = _modbusMaster.ReadHoldingRegisters(slaveId, 406, 1); int hangTime = ConvertSingleRegisterToInt(hangTimeReg[0]); - + // 读取运行速度(D410,1个寄存器,整数,单位:mm/min) - ushort[] runSpeedReg = _modbusMaster.ReadHoldingRegisters(slaveId, 410, 1); - int runSpeed = ConvertSingleRegisterToInt(runSpeedReg[0]); + ushort[] runSpeedReg = _modbusMaster.ReadHoldingRegisters(slaveId, 310, 2); + double runSpeed = ConvertRegistersToDouble(runSpeedReg); + runSpeed = ModbusUshortToFloat(runSpeedReg[1], runSpeedReg[0]); // 使用反射获取Form2的私有字段 var sampleDataTableField = form2Instance.GetType() .GetField("sampleDataTable", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); - + var currentSampleCountField = form2Instance.GetType() .GetField("currentSampleCount", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); - + if (sampleDataTableField == null || currentSampleCountField == null) { System.Diagnostics.Debug.WriteLine("无法获取Form2的私有字段"); @@ -538,7 +541,7 @@ namespace WindowsFormsApp6 DataTable dataTable = sampleDataTableField.GetValue(form2Instance) as DataTable; int currentSampleCount = (int)currentSampleCountField.GetValue(form2Instance); - + if (dataTable == null) { System.Diagnostics.Debug.WriteLine("DataTable为空"); @@ -552,7 +555,7 @@ namespace WindowsFormsApp6 AfterWeight = afterWeight, SoakTime = soakTime, HangTime = hangTime, - RunSpeed = runSpeed + RunSpeed = (int)runSpeed }); // 新试样的索引 @@ -566,11 +569,11 @@ namespace WindowsFormsApp6 { dataTable.Columns.Add($"试样{newSampleIndex}", typeof(object)); } - + // 更新currentSampleCount currentSampleCount = newSampleIndex; currentSampleCountField.SetValue(form2Instance, currentSampleCount); - + // 重新初始化DataGridView以显示新列 this.Invoke(new Action(() => { @@ -578,7 +581,7 @@ namespace WindowsFormsApp6 .GetMethod("InitializeDataGridView", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); initMethod?.Invoke(form2Instance, null); })); - + // 重新获取DataTable(可能已重新绑定) dataTable = sampleDataTableField.GetValue(form2Instance) as DataTable; } @@ -634,9 +637,9 @@ namespace WindowsFormsApp6 { if (form2SampleDataList[i].InitialWeight > 0) { - absorptions[i] = ((form2SampleDataList[i].AfterWeight - form2SampleDataList[i].InitialWeight) + absorptions[i] = ((form2SampleDataList[i].AfterWeight - form2SampleDataList[i].InitialWeight) / form2SampleDataList[i].InitialWeight) * 100; - + // 检查NaN if (double.IsNaN(absorptions[i]) || double.IsInfinity(absorptions[i])) { @@ -720,7 +723,7 @@ namespace WindowsFormsApp6 // 计算并添加统计行:每5个试样一组 int groupCount = (int)Math.Ceiling((double)totalSamples / 5.0); - + for (int groupIndex = 0; groupIndex < groupCount; groupIndex++) { int startSample = groupIndex * 5 + 1; @@ -739,13 +742,13 @@ namespace WindowsFormsApp6 DataRow avgRow = dataTable.NewRow(); avgRow["序号"] = $"液体吸收量平均值(%) 试样{startSample}-{endSample}"; double avgAbsorption = groupAbsorptions.Average(); - + // 检查NaN if (double.IsNaN(avgAbsorption) || double.IsInfinity(avgAbsorption)) { avgAbsorption = 0; } - + // 只在该组第一个试样列显示平均值,其他列设置为DBNull for (int i = 1; i <= currentSampleCount; i++) { @@ -768,13 +771,13 @@ namespace WindowsFormsApp6 DataRow maxRow = dataTable.NewRow(); maxRow["序号"] = $"液体吸收量最大值(%) 试样{startSample}-{endSample}"; double maxAbsorption = groupAbsorptions.Max(); - + // 检查NaN if (double.IsNaN(maxAbsorption) || double.IsInfinity(maxAbsorption)) { maxAbsorption = 0; } - + // 只在该组第一个试样列显示最大值,其他列设置为DBNull for (int i = 1; i <= currentSampleCount; i++) { @@ -797,13 +800,13 @@ namespace WindowsFormsApp6 DataRow stdDevRow = dataTable.NewRow(); stdDevRow["序号"] = $"标准偏差 试样{startSample}-{endSample}"; double stdDev = groupAbsorptions.Count > 1 ? CalculateStandardDeviation(groupAbsorptions.ToArray()) : 0; - + // 检查NaN if (double.IsNaN(stdDev) || double.IsInfinity(stdDev)) { stdDev = 0; } - + // 只在该组第一个试样列显示标准偏差,其他列设置为DBNull for (int i = 1; i <= currentSampleCount; i++) { @@ -847,17 +850,17 @@ namespace WindowsFormsApp6 private double ConvertRegistersToDouble(ushort[] registers) { if (registers == null || registers.Length < 2) return 0.0; - + // 组合两个寄存器为32位整数(高位在前) uint value = ((uint)registers[0] << 16) | registers[1]; double result = value / 100.0; - + // 检查NaN if (double.IsNaN(result) || double.IsInfinity(result)) { return 0.0; } - + return result; } @@ -867,7 +870,7 @@ namespace WindowsFormsApp6 private int ConvertRegistersToInt(ushort[] registers) { if (registers == null || registers.Length < 2) return 0; - + // 组合两个寄存器为32位整数(高位在前) return (registers[0] << 16) | registers[1]; } @@ -897,7 +900,7 @@ namespace WindowsFormsApp6 for (int i = 0; i < currentSampleCount; i++) { var value = initialRow[$"试样{i + 1}"]; - if (value == null || value == DBNull.Value || + if (value == null || value == DBNull.Value || (value is double d && d == 0.0)) { return i; @@ -995,7 +998,7 @@ namespace WindowsFormsApp6 if (initialWeights[i] > 0) { absorptions[i] = ((afterWeights[i] - initialWeights[i]) / initialWeights[i]) * 100; - + // 检查NaN if (double.IsNaN(absorptions[i]) || double.IsInfinity(absorptions[i])) { @@ -1047,13 +1050,13 @@ namespace WindowsFormsApp6 DataRow avgRow = dataTable.NewRow(); avgRow["序号"] = "液体吸收量平均值(%)"; double avgAbsorption = validCount > 0 ? validAbsorptions.Average() : 0; - + // 检查NaN if (double.IsNaN(avgAbsorption) || double.IsInfinity(avgAbsorption)) { avgAbsorption = 0; } - + avgRow["试样1"] = avgAbsorption; for (int i = 2; i <= count; i++) { @@ -1065,13 +1068,13 @@ namespace WindowsFormsApp6 DataRow maxRow = dataTable.NewRow(); maxRow["序号"] = "液体吸收量最大值(%)"; double maxAbsorption = validCount > 0 ? validAbsorptions.Max() : 0; - + // 检查NaN if (double.IsNaN(maxAbsorption) || double.IsInfinity(maxAbsorption)) { maxAbsorption = 0; } - + maxRow["试样1"] = maxAbsorption; for (int i = 2; i <= count; i++) { @@ -1111,21 +1114,21 @@ namespace WindowsFormsApp6 try { // 读取吸水时间(D200,1个寄存器,整数,单位:秒) - ushort[] timeRegisters = _modbusMaster.ReadHoldingRegisters(slaveId, 200, 1); - + ushort[] timeRegisters = _modbusMaster.ReadHoldingRegisters(slaveId, 212, 2); + // 读取吸芯高度(D454,2个寄存器,浮点数,单位:mm,精度0.01mm) ushort[] heightRegisters = _modbusMaster.ReadHoldingRegisters(slaveId, 454, 2); // 使用反射获取Form3的私有字段 var sampleDataTableField = form3Instance.GetType() .GetField("sampleDataTable", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); - + var currentSampleCountField = form3Instance.GetType() .GetField("currentSampleCount", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); - + var isVerticalLayoutField = form3Instance.GetType() .GetField("isVerticalLayout", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); - + if (sampleDataTableField == null || currentSampleCountField == null || isVerticalLayoutField == null) { System.Diagnostics.Debug.WriteLine("无法获取Form3的私有字段"); @@ -1135,7 +1138,7 @@ namespace WindowsFormsApp6 DataTable dataTable = sampleDataTableField.GetValue(form3Instance) as DataTable; int currentSampleCount = (int)currentSampleCountField.GetValue(form3Instance); bool isVerticalLayout = (bool)isVerticalLayoutField.GetValue(form3Instance); - + if (dataTable == null || dataTable.Rows.Count == 0) { System.Diagnostics.Debug.WriteLine("DataTable为空或没有行"); @@ -1144,11 +1147,11 @@ namespace WindowsFormsApp6 // 将寄存器值转换为实际数据 // 吸水时间:单个寄存器,整数,单位:秒 - int wickingTime = ConvertSingleRegisterToInt(timeRegisters[0]); - + int wickingTime = timeRegisters[0]; + //wickingTime = ModbusUshortToInt(timeRegisters[1], timeRegisters[0]); // 吸芯高度:2个寄存器,浮点数,单位:mm,精度0.01mm double wickingHeight = ConvertRegistersToDouble(heightRegisters); - + wickingHeight = ModbusUshortToFloat(heightRegisters[1], heightRegisters[0]); // 检查数据有效性 if (wickingTime <= 0 || double.IsNaN(wickingHeight) || double.IsInfinity(wickingHeight)) { @@ -1163,14 +1166,14 @@ namespace WindowsFormsApp6 // Form3限制:最多5组试样(15次测试) const int MAX_FORM3_SAMPLES = 5; - + // 如果超过最大试样数量,显示警告并停止 if (sampleIndex > MAX_FORM3_SAMPLES) { this.Invoke(new Action(() => { MessageBox.Show($"Form3已达到最大试样数量限制({MAX_FORM3_SAMPLES}组,共{MAX_FORM3_SAMPLES * 3}次测试)\n" + - "无法继续添加数据。", + "无法继续添加数据。", "数据已满", MessageBoxButtons.OK, MessageBoxIcon.Warning); })); return; @@ -1181,7 +1184,7 @@ namespace WindowsFormsApp6 { currentSampleCount = sampleIndex; currentSampleCountField.SetValue(form3Instance, currentSampleCount); - + // 重新初始化DataTable和DataGridView this.Invoke(new Action(() => { @@ -1189,7 +1192,7 @@ namespace WindowsFormsApp6 .GetMethod("SetSampleCount", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); setSampleCountMethod?.Invoke(form3Instance, new object[] { currentSampleCount }); })); - + // 重新获取更新后的DataTable dataTable = sampleDataTableField.GetValue(form3Instance) as DataTable; } @@ -1203,13 +1206,13 @@ namespace WindowsFormsApp6 DataRow timeRow = dataTable.Rows[0]; DataRow heightRow = dataTable.Rows[1]; string columnName = $"试样{sampleIndex}_{testIndex}"; - + // 填充吸水时间 if (timeRow.Table.Columns.Contains(columnName)) { timeRow[columnName] = wickingTime; } - + // 填充吸芯高度 if (heightRow.Table.Columns.Contains(columnName)) { @@ -1222,21 +1225,21 @@ namespace WindowsFormsApp6 // 横向布局:每行是一个试样的一次测试 // 计算行索引:(sampleIndex-1) * 3 + (testIndex-1) int rowIndex = (sampleIndex - 1) * 3 + (testIndex - 1); - + if (rowIndex < dataTable.Rows.Count) { DataRow row = dataTable.Rows[rowIndex]; string rowName = $"试样{sampleIndex}_{testIndex}"; - + // 确保序号正确 row["序号"] = rowName; - + // 填充吸水时间列 if (row.Table.Columns.Contains("吸水时间(s)")) { row["吸水时间(s)"] = wickingTime; } - + // 填充吸芯高度列 if (row.Table.Columns.Contains("吸芯高度(mm)")) { @@ -1265,6 +1268,39 @@ namespace WindowsFormsApp6 } } + private float ModbusUshortToFloat(ushort highReg, ushort lowReg) + { + byte[] floatBytes = new byte[4]; + // 高寄存器→高2字节,低寄存器→低2字节(与读取时的顺序一致) + floatBytes[0] = (byte)(highReg >> 8); + floatBytes[1] = (byte)highReg; + floatBytes[2] = (byte)(lowReg >> 8); + floatBytes[3] = (byte)lowReg; + + if (BitConverter.IsLittleEndian) + { + Array.Reverse(floatBytes); + } + + return BitConverter.ToSingle(floatBytes, 0); + } + + private int ModbusUshortToInt(ushort highReg, ushort lowReg) + { + byte[] floatBytes = new byte[4]; + // 高寄存器→高2字节,低寄存器→低2字节(与读取时的顺序一致) + floatBytes[0] = (byte)(highReg >> 8); + floatBytes[1] = (byte)highReg; + floatBytes[2] = (byte)(lowReg >> 8); + floatBytes[3] = (byte)lowReg; + + if (BitConverter.IsLittleEndian) + { + Array.Reverse(floatBytes); + } + + return BitConverter.ToInt32(floatBytes, 0); + } /// /// 获取Form3下一个要填充的位置(试样索引和测试次数) /// 返回:(试样索引, 测试次数) - 都是1-based @@ -1277,7 +1313,7 @@ namespace WindowsFormsApp6 if (dataTable.Rows.Count > 0) { DataRow timeRow = dataTable.Rows[0]; - + // 遍历所有试样的所有测试次数,找到第一个空位 for (int i = 1; i <= currentSampleCount; i++) { @@ -1287,7 +1323,7 @@ namespace WindowsFormsApp6 if (timeRow.Table.Columns.Contains(columnName)) { var value = timeRow[columnName]; - if (value == null || value == DBNull.Value || + if (value == null || value == DBNull.Value || (value is double d && Math.Abs(d) < 0.001)) { return Tuple.Create(i, j); @@ -1295,7 +1331,7 @@ namespace WindowsFormsApp6 } } } - + // 所有位置都已填充,返回下一个试样的第1次测试 return Tuple.Create(currentSampleCount + 1, 1); } @@ -1308,15 +1344,15 @@ namespace WindowsFormsApp6 for (int j = 1; j <= 3; j++) { int rowIndex = (i - 1) * 3 + (j - 1); - + if (rowIndex < dataTable.Rows.Count) { DataRow row = dataTable.Rows[rowIndex]; - + if (row.Table.Columns.Contains("吸水时间(s)")) { var value = row["吸水时间(s)"]; - if (value == null || value == DBNull.Value || + if (value == null || value == DBNull.Value || (value is double d && Math.Abs(d) < 0.001)) { return Tuple.Create(i, j); @@ -1325,11 +1361,11 @@ namespace WindowsFormsApp6 } } } - + // 所有位置都已填充,返回下一个试样的第1次测试 return Tuple.Create(currentSampleCount + 1, 1); } - + // 默认返回第1个试样的第1次测试 return Tuple.Create(1, 1); } @@ -1340,22 +1376,22 @@ namespace WindowsFormsApp6 private double CalculateStandardDeviation(double[] values) { if (values == null || values.Length <= 1) return 0; - + // 过滤掉NaN和Infinity值 var validValues = values.Where(v => !double.IsNaN(v) && !double.IsInfinity(v)).ToArray(); - + if (validValues.Length <= 1) return 0; - + double avg = validValues.Average(); double sumOfSquares = validValues.Sum(val => Math.Pow(val - avg, 2)); double result = Math.Sqrt(sumOfSquares / (validValues.Length - 1)); - + // 检查结果是否为NaN if (double.IsNaN(result) || double.IsInfinity(result)) { return 0; } - + return result; } @@ -1383,11 +1419,11 @@ namespace WindowsFormsApp6 private void TabControl1_SelectedIndexChanged(object sender, EventArgs e) { UpdateTitleForCurrentTab(); - + // 根据选中的 Tab 显示/隐藏切换布局按钮 // 只有在 Form3 (Tab 2, index=2) 时显示切换按钮 buttonToggleLayout.Visible = (tabControl1.SelectedIndex == 2); - + // 更新切换按钮的文本 if (tabControl1.SelectedIndex == 2 && form3Instance != null) { @@ -1417,7 +1453,7 @@ namespace WindowsFormsApp6 form1Instance.TopLevel = false; form1Instance.FormBorderStyle = FormBorderStyle.None; form1Instance.Dock = DockStyle.Fill; - + Panel panel1 = new Panel(); panel1.Dock = DockStyle.Fill; panel1.Controls.Add(form1Instance.Controls["tableLayoutPanel1"].Controls["panel3"]); @@ -1428,7 +1464,7 @@ namespace WindowsFormsApp6 form2Instance.TopLevel = false; form2Instance.FormBorderStyle = FormBorderStyle.None; form2Instance.Dock = DockStyle.Fill; - + Panel panel2 = new Panel(); panel2.Dock = DockStyle.Fill; panel2.Controls.Add(form2Instance.Controls["tableLayoutPanel1"].Controls["panel3"]); @@ -1439,7 +1475,7 @@ namespace WindowsFormsApp6 form3Instance.TopLevel = false; form3Instance.FormBorderStyle = FormBorderStyle.None; form3Instance.Dock = DockStyle.Fill; - + Panel panel3 = new Panel(); panel3.Dock = DockStyle.Fill; panel3.Controls.Add(form3Instance.Controls["tableLayoutPanel1"].Controls["panel3"]); @@ -1463,56 +1499,56 @@ namespace WindowsFormsApp6 int col3InputWidth = 140; int col4LabelWidth = 75; // 测试时间/数据文件 int col4InputWidth = 140; - + int gap = 15; // 列之间的间距 - + // 计算总宽度 int totalWidth = col1LabelWidth + col1InputWidth + gap + col2LabelWidth + col2InputWidth + gap + col3LabelWidth + col3InputWidth + gap + col4LabelWidth + col4InputWidth; - + int startX = (panelInfo.Width - totalWidth) / 2; - + // 第一行 Y 坐标 int y1 = 10; int labelOffsetY = 3; // 标签相对输入框的垂直偏移 - + // 第一列:样品名称 int col1X = startX; label3.Location = new Point(col1X, y1 + labelOffsetY); textBox1.Location = new Point(col1X + col1LabelWidth, y1); - + // 第二列:物料编码 int col2X = col1X + col1LabelWidth + col1InputWidth + gap; label4.Location = new Point(col2X, y1 + labelOffsetY); textBox2.Location = new Point(col2X + col2LabelWidth, y1); - + // 第三列:批号 int col3X = col2X + col2LabelWidth + col2InputWidth + gap; label5.Location = new Point(col3X, y1 + labelOffsetY); textBox3.Location = new Point(col3X + col3LabelWidth, y1); - + // 第四列:测试时间 int col4X = col3X + col3LabelWidth + col3InputWidth + gap; label9.Location = new Point(col4X, y1 + labelOffsetY); textBox7.Location = new Point(col4X + col4LabelWidth, y1); - + // 第二行 Y 坐标 int y2 = 43; - + // 第一列:仪器 label6.Location = new Point(col1X, y2 + labelOffsetY); textBox4.Location = new Point(col1X + col1LabelWidth, y2); - + // 第二列:设备编号 label7.Location = new Point(col2X, y2 + labelOffsetY); textBox5.Location = new Point(col2X + col2LabelWidth, y2); - + // 第三列:操作人员 label8.Location = new Point(col3X, y2 + labelOffsetY); textBox6.Location = new Point(col3X + col3LabelWidth, y2); - + // 第四列:数据文件 label10.Location = new Point(col4X, y2 + labelOffsetY); textBox8.Location = new Point(col4X + col4LabelWidth, y2); @@ -1525,25 +1561,25 @@ namespace WindowsFormsApp6 { // 收集所有可见的按钮 List