using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows.Forms; using LB_VisionProcesses.BarcodeReaders; namespace LB_VisionProcesses.BarcodeReaders { /// /// 读码器配置与测试窗体 /// public partial class BarcodeReaderForm : Form { private IBarcodeReader _reader; private string _currentSN; private LB_VisionProcesses.Processes.BarcodeReaderProcess _process; private string _processPath; public BarcodeReaderForm() { InitializeComponent(); } public BarcodeReaderForm(IBarcodeReader reader) { InitializeComponent(); _reader = reader; _reader.BarcodeRead += Reader_BarcodeRead; _currentSN = _reader.IsConnected ? "设备已在线" : ""; // 同步 UI 状态 cmbBrand.Text = _reader.Brand.ToString(); cmbSN.Text = _reader.IsConnected ? "在线设备" : ""; } public BarcodeReaderForm(LB_VisionProcesses.Processes.BarcodeReaderProcess process, string processPath) { InitializeComponent(); _process = process; _processPath = processPath; // 加载流程参数到 UI if (_process.Params.Inputs.ContainsKey("设备品牌")) cmbBrand.Text = _process.Params.Inputs["设备品牌"].ToString(); if (_process.Params.Inputs.ContainsKey("设备SN")) cmbSN.Text = _process.Params.Inputs["设备SN"].ToString(); if (_process.Params.Inputs.ContainsKey("触发模式")) radSoftTrigger.Checked = _process.Params.Inputs["触发模式"].ToString() == "软触发"; if (_process.Params.Inputs.ContainsKey("超时时间")) txtTimeout.Text = _process.Params.Inputs["超时时间"].ToString(); } private void BarcodeReaderForm_Load(object sender, EventArgs e) { // 初始化品牌列表 cmbBrand.Items.Clear(); foreach (var brand in Enum.GetValues(typeof(BarcodeReaderBrand))) { if ((BarcodeReaderBrand)brand != BarcodeReaderBrand.Unsupported) { cmbBrand.Items.Add(brand); } } if (cmbBrand.Items.Count > 0) cmbBrand.SelectedIndex = 0; UpdateUIStatus(); } private void btnRefresh_Click(object sender, EventArgs e) { try { if (cmbBrand.SelectedItem == null) return; var brand = (BarcodeReaderBrand)cmbBrand.SelectedItem; using (var tempReader = BarcodeReaderFactory.CreateReader(brand)) { var devices = tempReader.GetDeviceList(); cmbSN.Items.Clear(); if (devices != null && devices.Count > 0) { cmbSN.Items.AddRange(devices.ToArray()); cmbSN.SelectedIndex = 0; } } lblStatus.Text = $"设备列表已刷新,找到 {cmbSN.Items.Count} 个设备"; } catch (Exception ex) { MessageBox.Show($"刷新设备列表失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void btnOpen_Click(object sender, EventArgs e) { try { if (cmbSN.SelectedItem == null && string.IsNullOrEmpty(cmbSN.Text)) { MessageBox.Show("请选择或输入设备序列号"); return; } _currentSN = cmbSN.Text; var brand = (BarcodeReaderBrand)cmbBrand.SelectedItem; if (_reader != null) { _reader.BarcodeRead -= Reader_BarcodeRead; _reader.Dispose(); } _reader = BarcodeReaderFactory.CreateReader(brand); _reader.BarcodeRead += Reader_BarcodeRead; if (_reader.Open(_currentSN)) { lblStatus.Text = $"设备 {_currentSN} 已打开"; UpdateUIStatus(); } else { MessageBox.Show("设备打开失败,请检查连接或占用状态"); } } catch (Exception ex) { MessageBox.Show($"打开设备异常: {ex.Message}"); } } private void btnClose_Click(object sender, EventArgs e) { if (_reader != null) { _reader.Close(); lblStatus.Text = "设备已关闭"; UpdateUIStatus(); } } private void btnStart_Click(object sender, EventArgs e) { if (_reader != null && _reader.IsConnected) { // 设置触发模式(根据 UI 选择) _reader.SetTriggerMode(radSoftTrigger.Checked); if (_reader.StartGrabbing()) { lblStatus.Text = "采集已开始"; UpdateUIStatus(); } } } private void btnStop_Click(object sender, EventArgs e) { if (_reader != null && _reader.IsGrabbing) { if (_reader.StopGrabbing()) { lblStatus.Text = "采集已停止"; UpdateUIStatus(); } } } private void btnSoftTrigger_Click(object sender, EventArgs e) { if (_reader != null && _reader.IsGrabbing) { _reader.SoftTrigger(); lblStatus.Text = "已执行软触发"; } else { lblStatus.Text = "请先开始采集再执行触发"; } } private void radTrigger_CheckedChanged(object sender, EventArgs e) { if (_reader != null && _reader.IsConnected) { _reader.SetTriggerMode(radSoftTrigger.Checked); lblStatus.Text = radSoftTrigger.Checked ? "已切换至软触发模式" : "已切换至硬触发/自动模式"; } } private void Reader_BarcodeRead(object sender, BarcodeEventArgs e) { // 异步更新 UI if (this.InvokeRequired) { this.BeginInvoke(new Action(Reader_BarcodeRead), sender, e); return; } try { // 更新结果列表 lstBarcodes.Items.Clear(); if (e.BarcodeInfos != null && e.BarcodeInfos.Count > 0) { foreach (var info in e.BarcodeInfos) { lstBarcodes.Items.Add($"{DateTime.Now:HH:mm:ss} - {info.Text}"); } } else { lstBarcodes.Items.Add($"{DateTime.Now:HH:mm:ss} - 未读到条码"); } // 更新预览图像并绘制标注 if (e.Image != null) { // 创建新位图用于绘图,不直接修改 SDK 传入的原图 Bitmap drawImg = new Bitmap(e.Image); using (Graphics g = Graphics.FromImage(drawImg)) { // 设置绘图质量 g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; using (Pen pen = new Pen(Color.LimeGreen, 3)) using (SolidBrush brush = new SolidBrush(Color.LimeGreen)) using (Font font = new Font("Arial", 16, FontStyle.Bold)) { foreach (var info in e.BarcodeInfos) { if (info.Points != null && info.Points.Length >= 4) { // 绘制四边形框 g.DrawPolygon(pen, info.Points); // 在第一个点上方绘制条码内容 // 计算绘制文本的位置(稍微偏移一点防止覆盖边框) Point textPos = info.Points[0]; textPos.Y -= 25; g.DrawString(info.Text, font, brush, textPos); } } } } // 释放旧图像,防止内存泄漏 var oldImg = picPreview.Image; picPreview.Image = drawImg; oldImg?.Dispose(); } } catch (Exception ex) { // 静默处理 UI 更新异常 Console.WriteLine($"UI更新异常: {ex.Message}"); } } private void UpdateUIStatus() { bool isConnected = _reader?.IsConnected ?? false; bool isGrabbing = _reader?.IsGrabbing ?? false; btnOpen.Enabled = !isConnected; btnClose.Enabled = isConnected; cmbBrand.Enabled = !isConnected; cmbSN.Enabled = !isConnected; btnRefresh.Enabled = !isConnected; btnStart.Enabled = isConnected && !isGrabbing; btnStop.Enabled = isGrabbing; btnSoftTrigger.Enabled = isGrabbing && radSoftTrigger.Checked; grpParams.Enabled = isConnected; } private void BarcodeReaderForm_FormClosing(object sender, FormClosingEventArgs e) { // 关闭前保存参数到流程 if (_process != null) { _process.Params.Inputs["设备品牌"] = cmbBrand.Text; _process.Params.Inputs["设备SN"] = cmbSN.Text; _process.Params.Inputs["触发模式"] = radSoftTrigger.Checked ? "软触发" : "硬触发"; if (int.TryParse(txtTimeout.Text, out int timeout)) _process.Params.Inputs["超时时间"] = timeout; _process.Save(_processPath); } if (_reader != null) { if (_reader.IsGrabbing) _reader.StopGrabbing(); _reader.Close(); _reader.BarcodeRead -= Reader_BarcodeRead; _reader.Dispose(); _reader = null; } } } }