using Modbus.Device; using Sunny.UI; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using 鲁尔圆锥接头测试仪.Data; using static 鲁尔圆锥接头测试仪.EasyassemblyTest; namespace 鲁尔圆锥接头测试仪 { public partial class LeakageTest : UIForm { private TestScreen _TestScreen; private WeepingTest _WeepingTest; private LeakageTest _LeakageTest; private LeakageReport _LeakageReport; private SeparatTest _SeparartTest; private UnsrewtorqueTest _UnsrewtorqueTest; private EasyassemblyTest _EasyassembleTest; private OverloadresTest _OverloadresTest; private StresscrackTest _StresscrackTest; private UncrewseptorqueTest _UncrewseptorqueTest; protected List leakageReports = new List(); Timer Timer; private Timer _longPressTimer; private int _currentButtonId = -1; // 记录触摸按下的起始时间,用于区分单击和长按(可选) private DateTime _touchDownTime; // 长按判定阈值(毫秒),可调整 private const int LongPressThreshold = 200; private TcpClient _tcpClient => ModbusResourceManager.Instance.TcpClient; private IModbusMaster _modbusMaster => ModbusResourceManager.Instance.ModbusMaster; Function ma; DataChange c; public LeakageTest() { InitializeComponent(); Timer = new Timer(); Timer.Tick += Timer_Tick; Timer.Interval = 300; Timer.Start(); _longPressTimer = new Timer(); _longPressTimer.Interval = 100; // 长按持续触发间隔 _longPressTimer.Tick += LongPressTimer_Tick; // 绑定适配触摸的按钮事件 BindTouchCompatibleEvents(uiButton11, 10); BindTouchCompatibleEvents(uiButton12, 11); BindTouchCompatibleEvents(uiButton13, 12); BindTouchCompatibleEvents(uiButton14, 13); } private void BindTouchCompatibleEvents(UIButton button, int buttonId) { // 核心:使用 MouseDown/MouseUp(触摸会自动触发),并优化触摸体验 button.MouseDown += (sender, e) => { if (e.Button == MouseButtons.Left) { _touchDownTime = DateTime.Now; _currentButtonId = buttonId; // 触摸/鼠标按下时,先启动一个短延迟再触发定时器(避免单击误触发长按) var delayTimer = new Timer { Interval = LongPressThreshold }; delayTimer.Tick += (s, args) => { delayTimer.Stop(); delayTimer.Dispose(); // 判定为长按,启动持续触发 _longPressTimer.Start(); }; delayTimer.Start(); } }; // 触摸抬起/离开均停止触发 button.MouseUp += (sender, e) => StopLongPress(); button.MouseLeave += (sender, e) => StopLongPress(); // 额外:屏蔽默认的Click事件重复触发(触摸可能导致Click和MouseDown双重触发) button.Click += (sender, e) => { // 只有按下时间短于长按阈值,才执行Click(避免重复) var pressDuration = (DateTime.Now - _touchDownTime).TotalMilliseconds; if (pressDuration < LongPressThreshold) { ma?.BtnClickFunctionForNew(Function.ButtonType.复归型, 10); } }; } /// /// 停止长按触发的统一方法 /// private void StopLongPress() { if (_currentButtonId == 10) { _modbusMaster.WriteSingleCoil(1, 10, false); } if (_currentButtonId == 11) { _modbusMaster.WriteSingleCoil(1, 11, false); } if (_currentButtonId == 12) { _modbusMaster.WriteSingleCoil(1, 12, false); } if (_currentButtonId == 13) { _modbusMaster.WriteSingleCoil(1, 13, false); } _longPressTimer.Stop(); _currentButtonId = -1; } private void LongPressTimer_Tick(object sender, EventArgs e) { if (_currentButtonId != -1) { if (_currentButtonId == 10) _modbusMaster.WriteSingleCoil(1, 10, true); if (_currentButtonId == 11) _modbusMaster.WriteSingleCoil(1, 11, true); if (_currentButtonId == 12) _modbusMaster.WriteSingleCoil(1, 12, true); if (_currentButtonId == 13) _modbusMaster.WriteSingleCoil(1, 13, true); } } private void Timer_Tick(object sender, EventArgs e) { //时间显示 Lab_time.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); //装夹轴向力D ushort[] force = _modbusMaster?.ReadHoldingRegisters(1, 1130, 2); var value = c.UshortToFloat(force[1], force[0]); lb_axclampforce.Text = value.ToString("F2"); //装配扭矩D ushort[] torque = _modbusMaster?.ReadHoldingRegisters(1, 1180, 2); var value1 = c.UshortToFloat(torque[1], torque[0]); lb_assemblytorque.Text = value1.ToString("F3"); //气体压力D ushort[] gaspressure = _modbusMaster?.ReadHoldingRegisters(1, 1230, 2); var value2 = c.UshortToFloat(gaspressure[1], gaspressure[0]); lb_gaspressure.Text = value2.ToString("F1"); //漏气持续时间D ushort[] airleakagetime = _modbusMaster?.ReadHoldingRegisters(1, 112, 1); float value3 = airleakagetime[0]; lb_airleagelengthtime.Text = value3.ToString("F0"); //泄漏率D ushort[] leakrate = _modbusMaster?.ReadHoldingRegisters(1, 118, 2); var value4 = c.UshortToFloat(leakrate[1], leakrate[0]); lb_leakagerate.Text = value4.ToString("F6"); //初始压力 ushort[] startpressure = _modbusMaster?.ReadHoldingRegisters(1, 114, 2); var value7 = c.UshortToFloat(startpressure[1], startpressure[0]); lb_startpressure.Text = value7.ToString("F1"); //结束压力 ushort[] endpressure = _modbusMaster?.ReadHoldingRegisters(1, 116, 2); var value8 = c.UshortToFloat(endpressure[1], endpressure[0]); lb_endpressure.Text = value8.ToString("F1"); //角度D ushort[] angle = _modbusMaster?.ReadHoldingRegisters(1, 42, 2); var value9 = c.UshortToFloat(angle[1], angle[0]); lb_angle.Text = value9.ToString("F1"); //滑台D ushort[] slipway = _modbusMaster?.ReadHoldingRegisters(1, 46, 2); var value10 = c.UshortToFloat(slipway[1], slipway[0]); lb_slip.Text = value10.ToString("F1"); //正负压切换 bool[] buttonStatus = _modbusMaster?.ReadCoils(1, 62, 1); if (buttonStatus[0]) { btn_dsqh.Active = true; } else { btn_dsqh.Active = false; } //测试按钮 bool[] testStatus = _modbusMaster?.ReadCoils(1, 110, 1); if (testStatus[0]) { uiButton18.Text = "测试中"; uiButton18.ForeColor = System.Drawing.Color.Green; } else { uiButton18.Text = "测试"; uiButton18.ForeColor = System.Drawing.Color.Black; } //计时按钮 bool[] timeStatus = _modbusMaster?.ReadCoils(1, 114, 1); if (timeStatus[0]) { uiButton16.Text = "计时中"; uiButton16.ForeColor = System.Drawing.Color.Green; } else { uiButton16.Text = "计时"; uiButton16.ForeColor = System.Drawing.Color.Black; } //是否合格 bool[] isOk = _modbusMaster?.ReadCoils(1, 116, 2); if (isOk[0]) { lb_ok.Visible = true; _modbusMaster?.ReadCoils(1, 116, 1); lb_ok.Text = "合格"; lb_ok.ForeColor = System.Drawing.Color.Green; } else { lb_ok.Visible = false; } if (isOk[1]) { lb_notok.Visible = true; lb_notok.Text = "不合格"; lb_notok.ForeColor = System.Drawing.Color.Green; } else { lb_notok.Visible = false; } //复位灯 bool[] resetStatus = _modbusMaster?.ReadCoils(1, 92, 1); if (resetStatus[0]) { uiLight2.OnColor = System.Drawing.Color.Green; } else { uiLight2.OnColor = System.Drawing.Color.Red; } //实验灯 bool[] conditionStatus = _modbusMaster?.ReadCoils(1, 82, 1); if (conditionStatus[0]) { uiLight1.OnColor = System.Drawing.Color.Green; } else { uiLight1.OnColor = System.Drawing.Color.Red; } bool[] result = _modbusMaster.ReadCoils(1, 112, 1); { if (result[0]) { ushort[] location = _modbusMaster.ReadHoldingRegisters(1, 1080, 12); float leakageforce = c.UshortToFloat(location[1], location[0]);//f float leakagetorque = c.UshortToFloat(location[3], location[2]);//f int leakagekeepingtime = location[4]; float leakagestartpressure = c.UshortToFloat(location[7], location[6]);//f float leakageendpressure = c.UshortToFloat(location[9], location[8]);//f float leakagerate = c.UshortToFloat(location[11], location[10]);//f LeakageReportRecord r = new LeakageReportRecord() { Num = leakageReports.Count + 1, Createtime = DateTime.Now, Force = leakageforce, Torque = leakagetorque, Keeppressuretime = leakagekeepingtime, Startpressure = leakagestartpressure, Endpressure = leakageendpressure, Leakrate = leakagerate, }; AddLeakage(r); } } } //返回 private void Btn_return_Click(object sender, EventArgs e) { SwitchWindow(ref _TestScreen, () => new TestScreen()); } private void AddLeakage(LeakageReportRecord report) { leakageReports.Add(report); } private void LeakageTest_Load(object sender, EventArgs e) { string plcIp = "192.168.1.10"; bool initSuccess = Data.ModbusResourceManager.Instance.Init(plcIp, 502); if (!initSuccess) { MessageBox.Show("连接Modbus服务器失败!", "错误"); this.Close(); return; } // 检查连接状态 if (_tcpClient == null || !_tcpClient.Connected) { MessageBox.Show("Modbus连接异常!", "错误"); this.Close(); return; } ma = new Function(_modbusMaster); c = new DataChange(); //_readTimer.Start(); MessageBox.Show( "此界面包含三项实验\n分别为:GB/T1962.2标准要求测漏气实验\nYY0916.7标准要求正压衰减实验、负压衰减实验\nISO080369-7标准要求测正、负压衰减\n请通过选择测试项目选择页面选择测试标准。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information ); } private bool TryReconnect() { try { string plcIp = "192.168.1.10"; bool initSuccess = Data.ModbusResourceManager.Instance.Init(plcIp, 502); if (initSuccess) { ma = new Function(_modbusMaster); return true; } } catch (Exception ex) { //ShowErrorMsg($"重新连接失败:{ex.Message}"); } return false; } private void SwitchWindow(ref T windowInstance, Func createFunc) where T : UIForm { // 1. 停止当前窗口的定时器(不释放资源) Timer?.Stop(); // 2. 检查资源是否可用(添加重连机制) if (_tcpClient == null || !_tcpClient.Connected || _modbusMaster == null) { // 尝试重新连接 bool reconnectSuccess = TryReconnect(); if (!reconnectSuccess) { MessageBox.Show("TCP连接已断开,请重新连接!", "提示"); return; } } // 3. 复用窗口实例:不存在则创建,存在则激活 if (windowInstance == null) { windowInstance = createFunc(); // 添加窗口关闭事件处理 windowInstance.Closed += (s, args) => { // 窗口关闭时重新启动定时器并显示当前窗口 //_readTimer?.Start(); //this.Show(); this.Activate(); }; } else { // 激活已存在的窗口(前置显示) windowInstance.Activate(); return; } // 4. 切换窗口:隐藏当前窗口,显示目标窗口(非模态) this.Hide(); windowInstance.Show(); // 使用 Show() 而不是 ShowDialog() } private void LeakageTest_FormClosed(object sender, FormClosedEventArgs e) { _WeepingTest?.Close(); //关闭漏液实验窗口 //_LeakageTest?.Close(); // 若主窗口无需关闭自身,保持注释 _SeparartTest?.Close(); // 关闭分离力实验窗口 _UnsrewtorqueTest?.Close(); // 关闭旋开扭矩实验窗口 _EasyassembleTest?.Close(); // 关闭易装配性实验窗口 _OverloadresTest?.Close();// 关闭抗过载性实验窗口 _StresscrackTest?.Close();// 关闭应力开裂实验窗口 _UncrewseptorqueTest?.Close();// 关闭旋开分离扭力实验窗口 } private void LeakageTest_FormClosing(object sender, FormClosingEventArgs e) { // 停止定时器 Timer?.Stop(); Timer?.Dispose(); // 释放主定时器 _longPressTimer?.Stop(); _longPressTimer?.Dispose(); // 释放长按定时器 // 释放Modbus资源 ModbusResourceManager.Instance?.Dispose(); // 确保应用程序完全退出 Application.Exit(); } //窗口转换 private void uiButton2_Click(object sender, EventArgs e) { _modbusMaster.WriteSingleCoil(1, 30, true); SwitchWindow(ref _WeepingTest, () => new WeepingTest()); } private void uiButton3_Click(object sender, EventArgs e) { //SwitchWindow(ref _LeakageTest, () => new LeakageTest(testScreen)); } private void uiButton6_Click(object sender, EventArgs e) { _modbusMaster.WriteSingleCoil(1, 32, true); SwitchWindow(ref _SeparartTest, () => new SeparatTest()); } private void uiButton7_Click(object sender, EventArgs e) { _modbusMaster.WriteSingleCoil(1, 33, true); SwitchWindow(ref _UnsrewtorqueTest, () => new UnsrewtorqueTest()); } private void uiButton8_Click(object sender, EventArgs e) { _modbusMaster.WriteSingleCoil(1, 34, true); SwitchWindow(ref _EasyassembleTest, () => new EasyassemblyTest()); } private void uiButton9_Click(object sender, EventArgs e) { _modbusMaster.WriteSingleCoil(1, 35, true); SwitchWindow(ref _OverloadresTest, () => new OverloadresTest()); } private void uiButton10_Click(object sender, EventArgs e) { _modbusMaster.WriteSingleCoil(1, 36, true); SwitchWindow(ref _StresscrackTest, () => new StresscrackTest()); } private void uiButton1_Click(object sender, EventArgs e) { _modbusMaster.WriteSingleCoil(1, 37, true); SwitchWindow(ref _UncrewseptorqueTest, () => new UncrewseptorqueTest()); } //复位按钮 private void uiButton15_Click(object sender, EventArgs e) { ma.BtnClickFunctionForNew(Function.ButtonType.切换型, 95); bool result = UIMessageBox.ShowAsk("确保夹具已松开!", true, UIMessageDialogButtons.Ok); if (result) { ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 90); } else { ma.BtnClickFunctionForNew(Function.ButtonType.切换型, 95); } } //停止按钮 private void uiButton19_Click(object sender, EventArgs e) { ma?.BtnClickFunctionForNew(Function.ButtonType.复归型, 113); } //打印按钮 private void uiButton17_Click(object sender, EventArgs e) { ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 15); } //记录按钮 private void uiButton20_Click(object sender, EventArgs e) { SwitchWindow(ref _LeakageReport, () => new LeakageReport(leakageReports)); } //正转按钮 private void uiButton11_Click(object sender, EventArgs e) { ma?.BtnClickFunctionForNew(Function.ButtonType.复归型, 10); } //反转按钮 private void uiButton12_Click(object sender, EventArgs e) { ma?.BtnClickFunctionForNew(Function.ButtonType.复归型, 11); } //前进按钮 private void uiButton13_Click(object sender, EventArgs e) { ma?.BtnClickFunctionForNew(Function.ButtonType.复归型, 12); } //后退按钮 private void uiButton14_Click(object sender, EventArgs e) { ma?.BtnClickFunctionForNew(Function.ButtonType.复归型, 13); } public class LeakageReportRecord { public int? Num { get; set; }//编号 public DateTime? Createtime { get; set; }//日期时间 public float? Force { get; set; } //轴向力 public float? Torque { get; set; }//扭矩力 public int? Keeppressuretime { get; set; }//保压计时 public float? Startpressure { get; set; }//初始压力 public float? Endpressure { get; set; }//结束压力 public float? Leakrate { get; set; }//泄漏率 } //正负压 private void btn_dsqh_Click(object sender, EventArgs e) { ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 62); } //测试 private void uiButton18_Click(object sender, EventArgs e) { ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 110); } //计时 private void uiButton16_Click(object sender, EventArgs e) { ma?.BtnClickFunctionForNew(Function.ButtonType.切换型, 114); } } }