using Modbus.Device; using System; using System.Collections.Generic; using System.Drawing; using System.Globalization; using System.IO; using System.Linq; using System.Net.Sockets; using System.Resources; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using 全自动水压检测仪; using 全自动水压检测仪.Data; namespace P_RTU_TEST_WinForm { public partial class MainForm : Form { // 设备通信相关 private IModbusMaster _master; private TcpClient _client = new TcpClient(); // 在类开头部分添加 private string _productModel = ""; // 存储产品批号 private TextBox txtProductModel; // 产品批号输入框 // 在类开头部分添加 private int _calculationCount = 1; // 默认计算1次 private TextBox txtCalcCount; // 计算次数输入框 private Button btnStartCalc; // 开始计算按钮 private List> _allTestResults = new List>(); // 存储所有测试结果 private TcpClient _tcpClient => ModbusResourceManager.Instance.TcpClient; private IModbusMaster _modbusMaster => ModbusResourceManager.Instance.ModbusMaster; Function ma; DataChange c; // 测试相关 private Thread _testThread; private bool _isTesting = false; private List _distanceValues = new List(); private Label label5; private DateTime _testStartTime; // UI更新委托 delegate void UpdateUIDelegate(string message); delegate void UpdateStatsDelegate(); public MainForm() { InitializeComponent(); // 添加产品批号标签和输入框 Label lblProductModel = new Label() { Text = "产品批号:", Location = new Point(366, 15), Size = new Size(68, 15) }; txtProductModel = new TextBox() { Location = new Point(366, 31), Size = new Size(100, 25), TabIndex = 6 }; // 添加计算次数标签和输入框 Label lblCalcCount = new Label() { Text = "计算次数:", Location = new Point(472, 15), Size = new Size(68, 15) }; txtCalcCount = new TextBox() { Location = new Point(472, 31), Size = new Size(60, 25), TabIndex = 7, Text = "1" // 默认值 }; // 添加开始计算按钮 btnStartCalc = new Button() { Text = "开始计算", Location = new Point(538, 29), Size = new Size(75, 23), TabIndex = 8, Enabled = true }; // 添加到窗体 this.Controls.Add(lblProductModel); this.Controls.Add(txtProductModel); this.Controls.Add(lblCalcCount); this.Controls.Add(txtCalcCount); this.Controls.Add(btnStartCalc); InitializeDataGridView(); SetupEventHandlers(); // 设置默认值 txtIP.Text = "192.168.1.210"; txtPort.Text = "502"; txtTestTime.Text = "10"; } private void InitializeDataGridView() { // 设置DataGridView的列 dataGridView1.Columns.Clear(); dataGridView1.Columns.Add("Timestamp", "时间戳"); dataGridView1.Columns.Add("speed", "转速"); dataGridView1.Columns.Add("Distance", "距离值 (mm)"); // 设置列宽度 dataGridView1.Columns["Timestamp"].Width = 150; dataGridView1.Columns["speed"].Width = 130; dataGridView1.Columns["Distance"].Width = 140; // 设置只读 dataGridView1.ReadOnly = true; // 允许排序 dataGridView1.AllowUserToOrderColumns = false; // 设置选择模式 dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect; dataGridView1.MultiSelect = false; } private void SetupEventHandlers() { btnConnect.Click += BtnConnect_Click; btnDisconnect.Click += BtnDisconnect_Click; btnStartTest.Click += BtnStartTest_Click; btnStopTest.Click += BtnStopTest_Click; btnExportData.Click += BtnExportData_Click; btnClearData.Click += BtnClearData_Click; btnStartCalc.Click += BtnStartCalc_Click; // 添加开始计算事件 // 窗体关闭事件 this.FormClosing += MainForm_FormClosing; } private void BtnStartCalc_Click(object sender, EventArgs e) { if (!_client.Connected || _master == null) { MessageBox.Show("请先连接设备!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } int testTime; if (!int.TryParse(txtTestTime.Text, out testTime) || testTime <= 0) { MessageBox.Show("请输入有效的测试时间(秒)!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // 获取计算次数 if (!int.TryParse(txtCalcCount.Text, out _calculationCount) || _calculationCount <= 0) { MessageBox.Show("请输入有效的计算次数!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // 清空之前的数据 ClearData(); _allTestResults.Clear(); // 清空历史结果 // 开始计算 StartMultipleTests(testTime); } private void StartMultipleTests(int testTimeSeconds) { if (_isTesting) return; _isTesting = true; _testStartTime = DateTime.Now; // 设置控件状态 btnStartTest.Enabled = false; btnStartCalc.Enabled = false; btnStopTest.Enabled = true; btnExportData.Enabled = false; btnClearData.Enabled = false; txtTestTime.Enabled = false; txtCalcCount.Enabled = false; LogMessage($"开始计算,总共 {_calculationCount} 次测试"); // 启动计算线程 _testThread = new Thread(() => RunMultipleTests(testTimeSeconds)); _testThread.Start(); } private void RunMultipleTests(int testTimeSeconds) { try { for (int i = 0; i < _calculationCount && _isTesting; i++) { LogMessage($"第 {i + 1}/{_calculationCount} 次测试开始..."); // 执行单次测试 List singleTestResults = RunSingleTest(testTimeSeconds, i + 1); if (singleTestResults.Count > 0) { _allTestResults.Add(singleTestResults); // 显示本次测试的统计结果 double min = GetMinDistanceFromList(singleTestResults); double max = GetMaxDistanceFromList(singleTestResults); double jitter = max - min; LogMessage($"第 {i + 1} 次测试结果: 最小值={min:F6}mm, 最大值={max:F6}mm, 抖动值={jitter:F6}mm"); } // 如果不是最后一次,弹出确认对话框,用户选择“是”继续下一次,“否”停止后续测试 if (i < _calculationCount - 1 && _isTesting) { bool userWantsContinue = true; // 在UI线程上显示对话框并获取选择 if (this.InvokeRequired) { this.Invoke(new Action(() => { var dr = MessageBox.Show($"第 {i + 1} 次测试已完成。是否继续进行第 {i + 2} 次测试?", "继续测试确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question); userWantsContinue = (dr == DialogResult.Yes); })); } else { var dr = MessageBox.Show($"第 {i + 1} 次测试已完成。是否继续进行第 {i + 2} 次测试?", "继续测试确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question); userWantsContinue = (dr == DialogResult.Yes); } if (!userWantsContinue) { LogMessage("用户选择停止后续测试"); _isTesting = false; break; } // 可选短暂停顿 Thread.Sleep(1000); // 测试间隔1秒 } } // 所有测试完成后,在主线程中停止测试并生成报表 if (InvokeRequired) { Invoke(new Action(() => { StopTest(); GenerateMultipleTestReport(); // 生成多次测试报表 })); } else { StopTest(); GenerateMultipleTestReport(); } } catch (Exception ex) { LogMessage($"多次测试过程中发生错误: {ex.Message}"); } } private List RunSingleTest(int testTimeSeconds, int testNumber) { List testDistances = new List(); DateTime endTime = DateTime.Now.AddSeconds(testTimeSeconds); try { // 配置设备为输出位置1 _master.WriteSingleRegister(1, 24, 0); while (_isTesting && DateTime.Now < endTime) { // 读取距离数据 ushort[] data = _master.ReadInputRegisters(1, 0, 2); // PLC连接和读取转速 try { string plcIp = "192.168.1.5"; bool initSuccess = ModbusResourceManager.Instance.Init(plcIp, 502); if (initSuccess && _tcpClient != null && _tcpClient.Connected) { c = new DataChange(); var registers = _modbusMaster.ReadHoldingRegisters(1, 118, 2); float floatValue1 = c.UshortToFloat(registers[1], registers[0]); this.Invoke(new Action(() => { label5.Text = $"第{testNumber}次转速: {floatValue1:F2} RPM"; })); } } catch { } if (data.Length >= 2) { double distance = MergeUShortToInt(data[0], data[1]) / 1000.0 / 1000; testDistances.Add(distance); // 更新UI UpdateUIWithDistance(DateTime.Now, distance, $"第{testNumber}次测试"); } Thread.Sleep(10); } } catch (Exception ex) { LogMessage($"第{testNumber}次测试错误: {ex.Message}"); } return testDistances; } private double GetMinDistanceFromList(List distances) { if (distances.Count == 0) return 0; double min = distances[0]; foreach (double value in distances) { if (value < min) min = value; } return min; } private double GetMaxDistanceFromList(List distances) { if (distances.Count == 0) return 0; double max = distances[0]; foreach (double value in distances) { if (value > max) max = value; } return max; } private void BtnConnect_Click(object sender, EventArgs e) { try { string ipAddress = txtIP.Text.Trim(); int port; if (!int.TryParse(txtPort.Text, out port)) { MessageBox.Show("端口号格式不正确!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } LogMessage($"正在连接设备 {ipAddress}:{port}..."); // 连接设备 _client = new TcpClient(); _client.Connect(ipAddress, port); _master = ModbusIpMaster.CreateIp(_client); LogMessage("设备连接成功!"); // 设置控件状态 btnConnect.Enabled = false; btnDisconnect.Enabled = true; btnStartTest.Enabled = true; txtIP.Enabled = false; txtPort.Enabled = false; } catch (Exception ex) { LogMessage($"连接失败: {ex.Message}"); MessageBox.Show($"连接失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void BtnDisconnect_Click(object sender, EventArgs e) { try { if (_isTesting) { StopTest(); } if (_client != null && _client.Connected) { _client.Close(); LogMessage("设备已断开连接"); } // 重置控件状态 btnConnect.Enabled = true; btnDisconnect.Enabled = false; btnStartTest.Enabled = false; txtIP.Enabled = true; txtPort.Enabled = true; } catch (Exception ex) { LogMessage($"断开连接时发生错误: {ex.Message}"); } } private void BtnStartTest_Click(object sender, EventArgs e) { if (!_client.Connected || _master == null) { MessageBox.Show("请先连接设备!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } int testTime; if (!int.TryParse(txtTestTime.Text, out testTime) || testTime <= 0) { MessageBox.Show("请输入有效的测试时间(秒)!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // 清空之前的数据 ClearData(); // 开始测试 StartTest(testTime); } private void BtnStopTest_Click(object sender, EventArgs e) { StopTest(); } private void BtnExportData_Click(object sender, EventArgs e) { if (_distanceValues.Count == 0 || dataGridView1.Rows.Count == 0) { MessageBox.Show("没有数据可以导出!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } SaveFileDialog saveFileDialog = new SaveFileDialog { Filter = "CSV文件 (*.csv)|*.csv|文本文件 (*.txt)|*.txt|所有文件 (*.*)|*.*", Title = "导出测试数据", FileName = $"距离测试数据_{DateTime.Now:yyyyMMdd_HHmmss}.csv" }; if (saveFileDialog.ShowDialog() == DialogResult.OK) { try { using (StreamWriter sw = new StreamWriter(saveFileDialog.FileName, false, System.Text.Encoding.UTF8)) { // 写入标题行 - 修改为包含转速 sw.WriteLine("序号,时间戳,转速(RPM),距离值(mm)"); // 写入数据 - 修改这里 for (int i = 0; i < dataGridView1.Rows.Count; i++) { if (i < _distanceValues.Count) { string timestamp = dataGridView1.Rows[i].Cells["Timestamp"].Value?.ToString() ?? ""; string speed = dataGridView1.Rows[i].Cells["speed"].Value?.ToString() ?? "--"; // 只写入数据,不需要其他修改 sw.WriteLine($"{i + 1},{timestamp},{speed},{_distanceValues[i]:F6}"); } } // 写入统计信息 - 这部分可以保持原样,或者选择性添加 sw.WriteLine(); sw.WriteLine("统计信息"); sw.WriteLine($"测试开始时间,{_testStartTime:yyyy-MM-dd HH:mm:ss}"); sw.WriteLine($"测试持续时间,{txtTestTime.Text}秒"); sw.WriteLine($"数据总数,{_distanceValues.Count}"); sw.WriteLine($"最小距离,{GetMinDistance():F6} mm"); sw.WriteLine($"最大距离,{GetMaxDistance():F6} mm"); sw.WriteLine($"距离抖动值,{GetJitter():F6} mm"); } LogMessage($"数据已成功导出到: {saveFileDialog.FileName}"); MessageBox.Show("数据导出成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { MessageBox.Show($"导出失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } private void BtnClearData_Click(object sender, EventArgs e) { if (_isTesting) { MessageBox.Show("请先停止测试!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } ClearData(); LogMessage("数据已清空"); } private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { StopTest(); if (_client != null && _client.Connected) { _client.Close(); } } private void StartTest(int testTimeSeconds) { if (_isTesting) return; _isTesting = true; _testStartTime = DateTime.Now; // 设置控件状态 btnStartTest.Enabled = false; btnStopTest.Enabled = true; btnExportData.Enabled = false; btnClearData.Enabled = false; txtTestTime.Enabled = false; // 启动测试线程 _testThread = new Thread(() => RunTest(testTimeSeconds)); _testThread.Start(); LogMessage($"测试开始,持续时间: {testTimeSeconds}秒"); } private void StopTest() { if (!_isTesting) return; _isTesting = false; if (_testThread != null && _testThread.IsAlive) { _testThread.Join(1000); // 等待线程结束 } ModbusResourceManager.Instance.ReleaseResource(); // 计算并显示统计信息 CalculateAndDisplayStats(); // 重置控件状态 btnStartTest.Enabled = true; btnStartCalc.Enabled = true; btnStopTest.Enabled = false; btnExportData.Enabled = true; btnClearData.Enabled = true; txtTestTime.Enabled = true; txtCalcCount.Enabled = true; LogMessage("测试已停止"); } private void AutoExportReport() { // 如果是多次测试,不调用自动报表,由GenerateMultipleTestReport生成 if (_calculationCount > 1) { LogMessage("多次测试已完成,将生成综合报表"); return; } // 以下是原有的单次测试报表代码 try { if (_distanceValues.Count == 0) { LogMessage("没有测试数据,跳过自动导出"); return; } // 获取产品批号 string productModel = string.IsNullOrWhiteSpace(txtProductModel.Text) ? "未命名产品" : txtProductModel.Text.Trim(); // 获取转速 string speedValue = "--"; if (dataGridView1.Rows.Count > 0) { var lastRow = dataGridView1.Rows[dataGridView1.Rows.Count - 1]; speedValue = lastRow.Cells["speed"].Value?.ToString() ?? "--"; } // 计算统计数据 double minDistance = GetMinDistance(); double maxDistance = GetMaxDistance(); double jitter = GetJitter(); // 生成文件名 string fileName = $"测试报表_{productModel}_{DateTime.Now:yyyyMMdd_HHmmss}.txt"; string filePath = Path.Combine(Application.StartupPath, "测试报表", fileName); // 确保目录存在 Directory.CreateDirectory(Path.GetDirectoryName(filePath)); // 写入报表 using (StreamWriter sw = new StreamWriter(filePath, false, System.Text.Encoding.UTF8)) { sw.WriteLine("=== 测试报表 ==="); sw.WriteLine($"生成时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}"); sw.WriteLine($"产品批号: {productModel}"); sw.WriteLine($"测试时间: {txtTestTime.Text} 秒"); sw.WriteLine($"计算次数: 1 次"); sw.WriteLine($"数据总数: {_distanceValues.Count}"); sw.WriteLine(""); sw.WriteLine("=== 测试结果 ==="); sw.WriteLine($"距离最大值: {maxDistance:F6} mm"); sw.WriteLine($"距离最小值: {minDistance:F6} mm"); sw.WriteLine($"抖动值: {jitter:F6} mm"); sw.WriteLine($"转速: {speedValue}"); } LogMessage($"报表已自动导出到: {filePath}"); } catch (Exception ex) { LogMessage($"自动导出报表失败: {ex.Message}"); } } private void GenerateMultipleTestReport() { try { if (_allTestResults.Count == 0) { LogMessage("没有测试数据,无法生成报表"); return; } // 获取产品批号 string productModel = string.IsNullOrWhiteSpace(txtProductModel.Text) ? "未命名产品" : txtProductModel.Text.Trim(); // 生成文件名 string fileName = $"多次测试报表_{productModel}_{DateTime.Now:yyyyMMdd_HHmmss}.txt"; string filePath = Path.Combine(Application.StartupPath, "测试报表", fileName); // 确保目录存在 Directory.CreateDirectory(Path.GetDirectoryName(filePath)); // 获取转速 - 从label5获取最后显示的转速值 string speedValue = label5.Text; // 如果转速显示包含"转速:",提取纯数值 if (speedValue.Contains("转速:")) { speedValue = speedValue.Replace("转速:", "").Replace("RPM", "").Trim(); } // 写入报表 using (StreamWriter sw = new StreamWriter(filePath, false, System.Text.Encoding.UTF8)) { sw.WriteLine("=== 多次测试报表 ==="); sw.WriteLine($"生成时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}"); sw.WriteLine($"产品批号: {productModel}"); sw.WriteLine($"单次测试时间: {txtTestTime.Text} 秒"); sw.WriteLine($"计算次数: {_calculationCount} 次"); sw.WriteLine($"总数据量: {_allTestResults.Sum(list => list.Count)}"); sw.WriteLine($"转速: {label5.Text}"); sw.WriteLine(""); // 写入每次测试的详细结果 for (int i = 0; i < _allTestResults.Count; i++) { var testData = _allTestResults[i]; if (testData.Count == 0) continue; double min = GetMinDistanceFromList(testData); double max = GetMaxDistanceFromList(testData); double jitter = max - min; sw.WriteLine($"第 {i + 1} 次测试:"); sw.WriteLine($" 距离最大值: {max:F6} mm"); sw.WriteLine($" 距离最小值: {min:F6} mm"); sw.WriteLine($" 抖动值: {jitter:F6} mm"); sw.WriteLine($" 数据量: {testData.Count}"); sw.WriteLine(); } // 写入综合统计信息 sw.WriteLine("=== 综合统计结果 ==="); // 计算所有测试的最大值、最小值、平均值 List allMins = new List(); List allMaxs = new List(); List allJitters = new List(); foreach (var testData in _allTestResults) { if (testData.Count == 0) continue; double min = GetMinDistanceFromList(testData); double max = GetMaxDistanceFromList(testData); double jitter = max - min; allMins.Add(min); allMaxs.Add(max); allJitters.Add(jitter); } if (allMins.Count > 0) { sw.WriteLine($"所有测试距离最大值: {allMaxs.Max():F6} mm"); sw.WriteLine($"所有测试距离最小值: {allMins.Min():F6} mm"); sw.WriteLine($"距离最大值平均值: {allMaxs.Average():F6} mm"); sw.WriteLine($"距离最小值平均值: {allMins.Average():F6} mm"); sw.WriteLine($"抖动值平均值: {allJitters.Average():F6} mm"); sw.WriteLine($"抖动值最大偏差: {allJitters.Max() - allJitters.Min():F6} mm"); } } LogMessage($"多次测试报表已生成: {filePath}"); // 弹出提示 if (MessageBox.Show($"计算完成,报表已导出到:\n{filePath}\n\n是否要打开报表文件?", "计算完成", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes) { System.Diagnostics.Process.Start(filePath); } } catch (Exception ex) { LogMessage($"生成多次测试报表失败: {ex.Message}"); } } private void RunTest(int testTimeSeconds) { DateTime endTime = DateTime.Now.AddSeconds(testTimeSeconds); try { // 配置设备为输出位置1 _master.WriteSingleRegister(1, 24, 0); while (_isTesting && DateTime.Now < endTime) { // 读取距离数据(距离1,地址0开始的两个寄存器) ushort[] data = _master.ReadInputRegisters(1, 0, 2); string plcIp = "192.168.1.5"; //string plcIp = "127.0.0.1"; bool initSuccess = ModbusResourceManager.Instance.Init(plcIp, 502); if (!initSuccess) { MessageBox.Show("连接Modbus服务器失败!", "错误"); this.Close(); return; } // 检查连接状态 if (_tcpClient == null || !_tcpClient.Connected) { MessageBox.Show("Modbus连接异常!", "错误"); this.Close(); return; } c = new DataChange(); var registers = _modbusMaster.ReadHoldingRegisters(1, 118, 2); this.Invoke(new Action(() => { float floatValue1 = c.UshortToFloat(registers[1], registers[0]); // 方式2: 直接合并为32位整数 int intValue = (registers[0] << 16) | registers[1]; int intValue2 = (registers[1] << 16) | registers[0]; // 交换顺序 // 显示所有可能的结果 label5.Text = $@"转速: {floatValue1:F2}"; })); if (data.Length >= 2) { // 合并两个寄存器的数据并转换为距离值(单位:mm) double distance = MergeUShortToInt(data[0], data[1]) / 1000.0 / 1000; // 添加到数据列表 _distanceValues.Add(distance); // 更新UI UpdateUIWithDistance(DateTime.Now, distance); } // 控制读取频率(例如10ms一次) Thread.Sleep(10); } } catch (Exception ex) { LogMessage($"测试过程中发生错误: {ex.Message}"); } finally { // 测试结束后,在主线程中停止测试 if (InvokeRequired) { Invoke(new Action(StopTest)); } else { StopTest(); } } } private int MergeUShortToInt(ushort hData, ushort lData) { return (hData << 16) | lData; } private void UpdateUIWithDistance(DateTime timestamp, double distance, string testInfo = "") { if (dataGridView1.InvokeRequired) { AddDataRowDelegate d = new AddDataRowDelegate(UpdateUIWithDistance); dataGridView1.Invoke(d, new object[] { timestamp, distance, testInfo }); } else { // 添加新行到DataGridView int rowIndex = dataGridView1.Rows.Add(); dataGridView1.Rows[rowIndex].Cells["Timestamp"].Value = timestamp.ToString("yyyy-MM-dd HH:mm:ss.fff"); dataGridView1.Rows[rowIndex].Cells["speed"].Value = label5.Text + " " + testInfo; dataGridView1.Rows[rowIndex].Cells["Distance"].Value = distance.ToString("F6", CultureInfo.InvariantCulture); // 自动滚动到最后一行 dataGridView1.FirstDisplayedScrollingRowIndex = rowIndex; } } // 同时修改委托定义 delegate void AddDataRowDelegate(DateTime timestamp, double distance, string testInfo); private void CalculateAndDisplayStats() { if (_distanceValues.Count == 0) return; double min = GetMinDistance(); double max = GetMaxDistance(); double jitter = GetJitter(); if (lblMin.InvokeRequired) { UpdateStatsDelegate d = new UpdateStatsDelegate(CalculateAndDisplayStats); lblMin.Invoke(d); } else { lblMin.Text = $"最小值: {min:F6} mm"; lblMax.Text = $"最大值: {max:F6} mm"; lblJitter.Text = $"抖动值: {jitter:F6} mm"; // 在日志中显示统计信息 LogMessage($"测试完成 - 数据总数: {_distanceValues.Count}"); LogMessage($"最小值: {min:F6} mm, 最大值: {max:F6} mm, 抖动值: {jitter:F6} mm"); } } private double GetMinDistance() { if (_distanceValues.Count == 0) return 0; double min = _distanceValues[0]; foreach (double value in _distanceValues) { if (value < min) min = value; } return min; } private double GetMaxDistance() { if (_distanceValues.Count == 0) return 0; double max = _distanceValues[0]; foreach (double value in _distanceValues) { if (value > max) max = value; } return max; } private double GetJitter() { if (_distanceValues.Count == 0) return 0; return GetMaxDistance() - GetMinDistance(); } private void ClearData() { _distanceValues.Clear(); _allTestResults.Clear(); dataGridView1.Rows.Clear(); lblMin.Text = "最小值: --"; lblMax.Text = "最大值: --"; lblJitter.Text = "抖动值: --"; } private void LogMessage(string message) { if (txtLog.InvokeRequired) { UpdateUIDelegate d = new UpdateUIDelegate(LogMessage); txtLog.Invoke(d, new object[] { message }); } else { string timestamp = DateTime.Now.ToString("HH:mm:ss.fff"); txtLog.AppendText($"[{timestamp}] {message}{Environment.NewLine}"); // 自动滚动到最后一行 txtLog.SelectionStart = txtLog.TextLength; txtLog.ScrollToCaret(); } } // 以下是窗体设计器生成的代码 private System.ComponentModel.IContainer components = null; private TextBox txtIP; private Label label1; private Label label2; private TextBox txtPort; private Button btnConnect; private Button btnDisconnect; private GroupBox groupBox1; private DataGridView dataGridView1; private GroupBox groupBox2; private Label label3; private TextBox txtTestTime; private Button btnStartTest; private Button btnStopTest; private GroupBox groupBox3; private Label lblMin; private Label lblMax; private Label lblJitter; private Button btnExportData; private Button btnClearData; private TextBox txtLog; private Label label4; protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } private void InitializeComponent() { this.txtIP = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label(); this.txtPort = new System.Windows.Forms.TextBox(); this.btnConnect = new System.Windows.Forms.Button(); this.btnDisconnect = new System.Windows.Forms.Button(); this.groupBox1 = new System.Windows.Forms.GroupBox(); this.dataGridView1 = new System.Windows.Forms.DataGridView(); this.groupBox2 = new System.Windows.Forms.GroupBox(); this.btnClearData = new System.Windows.Forms.Button(); this.btnExportData = new System.Windows.Forms.Button(); this.btnStopTest = new System.Windows.Forms.Button(); this.btnStartTest = new System.Windows.Forms.Button(); this.txtTestTime = new System.Windows.Forms.TextBox(); this.label3 = new System.Windows.Forms.Label(); this.groupBox3 = new System.Windows.Forms.GroupBox(); this.label5 = new System.Windows.Forms.Label(); this.lblJitter = new System.Windows.Forms.Label(); this.lblMax = new System.Windows.Forms.Label(); this.lblMin = new System.Windows.Forms.Label(); this.txtLog = new System.Windows.Forms.TextBox(); this.label4 = new System.Windows.Forms.Label(); this.groupBox1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit(); this.groupBox2.SuspendLayout(); this.groupBox3.SuspendLayout(); this.SuspendLayout(); // // txtIP // this.txtIP.Location = new System.Drawing.Point(12, 31); this.txtIP.Name = "txtIP"; this.txtIP.Size = new System.Drawing.Size(120, 25); this.txtIP.TabIndex = 0; // // label1 // this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(12, 15); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(68, 15); this.label1.TabIndex = 1; this.label1.Text = "IP地址:"; // // label2 // this.label2.AutoSize = true; this.label2.Location = new System.Drawing.Point(138, 15); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(67, 15); this.label2.TabIndex = 3; this.label2.Text = "端口号:"; // // txtPort // this.txtPort.Location = new System.Drawing.Point(138, 31); this.txtPort.Name = "txtPort"; this.txtPort.Size = new System.Drawing.Size(60, 25); this.txtPort.TabIndex = 2; // // btnConnect // this.btnConnect.Location = new System.Drawing.Point(204, 29); this.btnConnect.Name = "btnConnect"; this.btnConnect.Size = new System.Drawing.Size(75, 23); this.btnConnect.TabIndex = 4; this.btnConnect.Text = "连接"; this.btnConnect.UseVisualStyleBackColor = true; // // btnDisconnect // this.btnDisconnect.Enabled = false; this.btnDisconnect.Location = new System.Drawing.Point(285, 29); this.btnDisconnect.Name = "btnDisconnect"; this.btnDisconnect.Size = new System.Drawing.Size(75, 23); this.btnDisconnect.TabIndex = 5; this.btnDisconnect.Text = "断开"; this.btnDisconnect.UseVisualStyleBackColor = true; // // groupBox1 // this.groupBox1.Controls.Add(this.dataGridView1); this.groupBox1.Location = new System.Drawing.Point(12, 70); this.groupBox1.Name = "groupBox1"; this.groupBox1.Size = new System.Drawing.Size(534, 300); this.groupBox1.TabIndex = 6; this.groupBox1.TabStop = false; this.groupBox1.Text = "实时数据"; // // dataGridView1 // this.dataGridView1.AllowUserToAddRows = false; this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.dataGridView1.Location = new System.Drawing.Point(3, 21); this.dataGridView1.Name = "dataGridView1"; this.dataGridView1.ReadOnly = true; this.dataGridView1.RowHeadersWidth = 51; this.dataGridView1.Size = new System.Drawing.Size(525, 276); this.dataGridView1.TabIndex = 0; // // groupBox2 // this.groupBox2.Controls.Add(this.btnClearData); this.groupBox2.Controls.Add(this.btnExportData); this.groupBox2.Controls.Add(this.btnStopTest); this.groupBox2.Controls.Add(this.btnStartTest); this.groupBox2.Controls.Add(this.txtTestTime); this.groupBox2.Controls.Add(this.label3); this.groupBox2.Location = new System.Drawing.Point(552, 69); this.groupBox2.Name = "groupBox2"; this.groupBox2.Size = new System.Drawing.Size(200, 150); this.groupBox2.TabIndex = 7; this.groupBox2.TabStop = false; this.groupBox2.Text = "测试控制"; // // btnClearData // this.btnClearData.Location = new System.Drawing.Point(105, 115); this.btnClearData.Name = "btnClearData"; this.btnClearData.Size = new System.Drawing.Size(75, 23); this.btnClearData.TabIndex = 5; this.btnClearData.Text = "清空数据"; this.btnClearData.UseVisualStyleBackColor = true; // // btnExportData // this.btnExportData.Location = new System.Drawing.Point(24, 115); this.btnExportData.Name = "btnExportData"; this.btnExportData.Size = new System.Drawing.Size(75, 23); this.btnExportData.TabIndex = 4; this.btnExportData.Text = "导出数据"; this.btnExportData.UseVisualStyleBackColor = true; // // btnStopTest // this.btnStopTest.Enabled = false; this.btnStopTest.Location = new System.Drawing.Point(105, 75); this.btnStopTest.Name = "btnStopTest"; this.btnStopTest.Size = new System.Drawing.Size(75, 23); this.btnStopTest.TabIndex = 3; this.btnStopTest.Text = "停止测试"; this.btnStopTest.UseVisualStyleBackColor = true; // // btnStartTest // this.btnStartTest.Enabled = false; this.btnStartTest.Location = new System.Drawing.Point(24, 75); this.btnStartTest.Name = "btnStartTest"; this.btnStartTest.Size = new System.Drawing.Size(75, 23); this.btnStartTest.TabIndex = 2; this.btnStartTest.Text = "开始测试"; this.btnStartTest.UseVisualStyleBackColor = true; // // txtTestTime // this.txtTestTime.Location = new System.Drawing.Point(65, 35); this.txtTestTime.Name = "txtTestTime"; this.txtTestTime.Size = new System.Drawing.Size(60, 25); this.txtTestTime.TabIndex = 1; // // label3 // this.label3.AutoSize = true; this.label3.Location = new System.Drawing.Point(21, 38); this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(61, 15); this.label3.TabIndex = 0; this.label3.Text = "时间(s)"; // // groupBox3 // this.groupBox3.Controls.Add(this.label5); this.groupBox3.Controls.Add(this.lblJitter); this.groupBox3.Controls.Add(this.lblMax); this.groupBox3.Controls.Add(this.lblMin); this.groupBox3.Location = new System.Drawing.Point(552, 225); this.groupBox3.Name = "groupBox3"; this.groupBox3.Size = new System.Drawing.Size(200, 144); this.groupBox3.TabIndex = 8; this.groupBox3.TabStop = false; this.groupBox3.Text = "统计信息"; // // label5 // this.label5.AutoSize = true; this.label5.Location = new System.Drawing.Point(21, 30); this.label5.Name = "label5"; this.label5.Size = new System.Drawing.Size(69, 15); this.label5.TabIndex = 3; this.label5.Text = "转速: --"; // // lblJitter // this.lblJitter.AutoSize = true; this.lblJitter.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.lblJitter.ForeColor = System.Drawing.Color.Red; this.lblJitter.Location = new System.Drawing.Point(21, 111); this.lblJitter.Name = "lblJitter"; this.lblJitter.Size = new System.Drawing.Size(78, 18); this.lblJitter.TabIndex = 2; this.lblJitter.Text = "抖动值: --"; // // lblMax // this.lblMax.AutoSize = true; this.lblMax.Location = new System.Drawing.Point(21, 86); this.lblMax.Name = "lblMax"; this.lblMax.Size = new System.Drawing.Size(84, 15); this.lblMax.TabIndex = 1; this.lblMax.Text = "最大值: --"; // // lblMin // this.lblMin.AutoSize = true; this.lblMin.Location = new System.Drawing.Point(21, 58); this.lblMin.Name = "lblMin"; this.lblMin.Size = new System.Drawing.Size(84, 15); this.lblMin.TabIndex = 0; this.lblMin.Text = "最小值: --"; // // txtLog // this.txtLog.Location = new System.Drawing.Point(12, 400); this.txtLog.Multiline = true; this.txtLog.Name = "txtLog"; this.txtLog.ReadOnly = true; this.txtLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; this.txtLog.Size = new System.Drawing.Size(554, 150); this.txtLog.TabIndex = 9; // // label4 // this.label4.AutoSize = true; this.label4.Location = new System.Drawing.Point(12, 384); this.label4.Name = "label4"; this.label4.Size = new System.Drawing.Size(52, 15); this.label4.TabIndex = 10; this.label4.Text = "日志:"; // // MainForm // this.ClientSize = new System.Drawing.Size(776, 561); this.Controls.Add(this.label4); this.Controls.Add(this.txtLog); this.Controls.Add(this.groupBox3); this.Controls.Add(this.groupBox2); this.Controls.Add(this.groupBox1); this.Controls.Add(this.btnDisconnect); this.Controls.Add(this.btnConnect); this.Controls.Add(this.label2); this.Controls.Add(this.txtPort); this.Controls.Add(this.label1); this.Controls.Add(this.txtIP); this.Name = "MainForm"; this.Text = "激光位移传感器测试程序"; this.Load += new System.EventHandler(this.MainForm_Load); this.groupBox1.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit(); this.groupBox2.ResumeLayout(false); this.groupBox2.PerformLayout(); this.groupBox3.ResumeLayout(false); this.groupBox3.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); } private void MainForm_Load(object sender, EventArgs e) { } } static class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm()); } } }