From 4091d5009b63ba1d6f24788ca79877c37001e0f6 Mon Sep 17 00:00:00 2001
From: C3032 <1057644574@qq.com>
Date: 星期五, 20 三月 2026 11:08:39 +0800
Subject: [PATCH] 华睿读码器集成完成,使用抽象接口-基类-各品牌子类的架构,实现可插拔设计,遵循开闭原则,方便后续集成其他品牌读码器

---
 LB_SmartVision/Forms/Pages/BarcodeReaderPage/BarcodeReaderForm.Designer.cs       |  258 ++++++++++
 LB_SmartVision/Forms/Pages/BarcodeReaderPage/BarcodeReadersEditPage.cs           |  226 +++++++++
 LB_SmartVision/VisionForm.cs                                                     |  143 +++++
 LB_VisionProcesses/BarcodeReaders/BarcodeReaderBase.cs                           |    8 
 LB_SmartVision/Forms/Pages/BarcodeReaderPage/CreateBarcodeReaderForm.cs          |  117 ++++
 LB_VisionProcesses/BarcodeReaders/BarcodeReaderForm.cs                           |   50 +
 LB_VisionProcesses/BarcodeReaders/Huayray/HRBarcodeReader.cs                     |   79 ++
 LB_VisionProcesses/BarcodeReaders/IBarcodeReader.cs                              |   27 
 LB_SmartVision/Forms/Pages/BarcodeReaderPage/BarcodeReadersEditPage.Designer.cs  |  152 ++++++
 LB_SmartVision/Forms/Pages/BarcodeReaderPage/CreateBarcodeReaderForm.Designer.cs |  178 +++++++
 LB_SmartVision/Forms/Pages/BarcodeReaderPage/BarcodeReaderForm.cs                |  207 ++++++++
 LB_SmartVision/GlobalVar.cs                                                      |    7 
 12 files changed, 1,426 insertions(+), 26 deletions(-)

diff --git a/LB_SmartVision/Forms/Pages/BarcodeReaderPage/BarcodeReaderForm.Designer.cs b/LB_SmartVision/Forms/Pages/BarcodeReaderPage/BarcodeReaderForm.Designer.cs
new file mode 100644
index 0000000..217611f
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/BarcodeReaderPage/BarcodeReaderForm.Designer.cs
@@ -0,0 +1,258 @@
+using LB_VisionControl;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace LB_SmartVision.Forms.Pages.BarcodeReaderPage
+{
+    partial class BarcodeReaderForm
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            uiGroupBoxImage = new GroupBox();
+            uiGroupBoxControl = new GroupBox();
+            uiGroupBoxResult = new GroupBox();
+            uiComboBoxBrand = new ComboBox();
+            uiLabel1 = new Label();
+            uiRadioButtonSoftTrigger = new RadioButton();
+            uiRadioButtonHardTrigger = new RadioButton();
+            uiButtonStartGrabbing = new Button();
+            uiButtonStopGrabbing = new Button();
+            uiButtonSoftTrigger = new Button();
+            uiListBoxBarcodes = new ListBox();
+            uiTextBoxResult = new TextBox();
+            uiLabel2 = new Label();
+            uiButtonClear = new Button();
+            uiGroupBoxImage.SuspendLayout();
+            uiGroupBoxControl.SuspendLayout();
+            uiGroupBoxResult.SuspendLayout();
+            SuspendLayout();
+            //
+            // uiGroupBoxImage
+            //
+            uiGroupBoxImage.BackColor = Color.FromArgb(32, 41, 50);
+            uiGroupBoxImage.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            uiGroupBoxImage.ForeColor = Color.White;
+            uiGroupBoxImage.Location = new Point(12, 12);
+            uiGroupBoxImage.Margin = new Padding(4, 5, 4, 5);
+            uiGroupBoxImage.Name = "uiGroupBoxImage";
+            uiGroupBoxImage.Padding = new Padding(4, 5, 4, 5);
+            uiGroupBoxImage.Size = new Size(400, 400);
+            uiGroupBoxImage.TabIndex = 0;
+            uiGroupBoxImage.TabStop = false;
+            uiGroupBoxImage.Text = "鍥惧儚棰勮";
+            //
+            // uiGroupBoxControl
+            //
+            uiGroupBoxControl.BackColor = Color.FromArgb(32, 41, 50);
+            uiGroupBoxControl.Controls.Add(uiButtonSoftTrigger);
+            uiGroupBoxControl.Controls.Add(uiButtonStopGrabbing);
+            uiGroupBoxControl.Controls.Add(uiButtonStartGrabbing);
+            uiGroupBoxControl.Controls.Add(uiRadioButtonHardTrigger);
+            uiGroupBoxControl.Controls.Add(uiRadioButtonSoftTrigger);
+            uiGroupBoxControl.Controls.Add(uiComboBoxBrand);
+            uiGroupBoxControl.Controls.Add(uiLabel1);
+            uiGroupBoxControl.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            uiGroupBoxControl.ForeColor = Color.White;
+            uiGroupBoxControl.Location = new Point(430, 12);
+            uiGroupBoxControl.Margin = new Padding(4, 5, 4, 5);
+            uiGroupBoxControl.Name = "uiGroupBoxControl";
+            uiGroupBoxControl.Padding = new Padding(4, 5, 4, 5);
+            uiGroupBoxControl.Size = new Size(350, 200);
+            uiGroupBoxControl.TabIndex = 1;
+            uiGroupBoxControl.TabStop = false;
+            uiGroupBoxControl.Text = "鎺у埗闈㈡澘";
+            //
+            // uiGroupBoxResult
+            //
+            uiGroupBoxResult.BackColor = Color.FromArgb(32, 41, 50);
+            uiGroupBoxResult.Controls.Add(uiButtonClear);
+            uiGroupBoxResult.Controls.Add(uiLabel2);
+            uiGroupBoxResult.Controls.Add(uiTextBoxResult);
+            uiGroupBoxResult.Controls.Add(uiListBoxBarcodes);
+            uiGroupBoxResult.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            uiGroupBoxResult.ForeColor = Color.White;
+            uiGroupBoxResult.Location = new Point(430, 230);
+            uiGroupBoxResult.Margin = new Padding(4, 5, 4, 5);
+            uiGroupBoxResult.Name = "uiGroupBoxResult";
+            uiGroupBoxResult.Padding = new Padding(4, 5, 4, 5);
+            uiGroupBoxResult.Size = new Size(350, 280);
+            uiGroupBoxResult.TabIndex = 2;
+            uiGroupBoxResult.TabStop = false;
+            uiGroupBoxResult.Text = "璇荤爜缁撴灉";
+            //
+            // uiComboBoxBrand
+            //
+            uiComboBoxBrand.DropDownStyle = ComboBoxStyle.DropDownList;
+            uiComboBoxBrand.FormattingEnabled = true;
+            uiComboBoxBrand.Location = new Point(90, 50);
+            uiComboBoxBrand.Name = "uiComboBoxBrand";
+            uiComboBoxBrand.Size = new Size(150, 28);
+            uiComboBoxBrand.TabIndex = 0;
+            //
+            // uiLabel1
+            //
+            uiLabel1.Location = new Point(15, 50);
+            uiLabel1.Name = "uiLabel1";
+            uiLabel1.Size = new Size(70, 29);
+            uiLabel1.TabIndex = 1;
+            uiLabel1.Text = "鍝佺墝:";
+            uiLabel1.TextAlign = ContentAlignment.MiddleRight;
+            //
+            // uiRadioButtonSoftTrigger
+            //
+            uiRadioButtonSoftTrigger.Checked = true;
+            uiRadioButtonSoftTrigger.Location = new Point(20, 90);
+            uiRadioButtonSoftTrigger.Name = "uiRadioButtonSoftTrigger";
+            uiRadioButtonSoftTrigger.Size = new Size(100, 29);
+            uiRadioButtonSoftTrigger.TabIndex = 2;
+            uiRadioButtonSoftTrigger.TabStop = true;
+            uiRadioButtonSoftTrigger.Text = "杞Е鍙�";
+            uiRadioButtonSoftTrigger.UseVisualStyleBackColor = true;
+            uiRadioButtonSoftTrigger.CheckedChanged += uiRadioButtonSoftTrigger_CheckedChanged;
+            //
+            // uiRadioButtonHardTrigger
+            //
+            uiRadioButtonHardTrigger.Location = new Point(140, 90);
+            uiRadioButtonHardTrigger.Name = "uiRadioButtonHardTrigger";
+            uiRadioButtonHardTrigger.Size = new Size(100, 29);
+            uiRadioButtonHardTrigger.TabIndex = 3;
+            uiRadioButtonHardTrigger.Text = "纭Е鍙�";
+            uiRadioButtonHardTrigger.UseVisualStyleBackColor = true;
+            //
+            // uiButtonStartGrabbing
+            //
+            uiButtonStartGrabbing.BackColor = Color.FromArgb(0, 150, 136);
+            uiButtonStartGrabbing.ForeColor = Color.White;
+            uiButtonStartGrabbing.Location = new Point(20, 140);
+            uiButtonStartGrabbing.Name = "uiButtonStartGrabbing";
+            uiButtonStartGrabbing.Size = new Size(100, 35);
+            uiButtonStartGrabbing.TabIndex = 4;
+            uiButtonStartGrabbing.Text = "寮�濮嬮噰闆�";
+            uiButtonStartGrabbing.UseVisualStyleBackColor = false;
+            uiButtonStartGrabbing.Click += uiButtonStartGrabbing_Click;
+            //
+            // uiButtonStopGrabbing
+            //
+            uiButtonStopGrabbing.BackColor = Color.FromArgb(255, 87, 34);
+            uiButtonStopGrabbing.Enabled = false;
+            uiButtonStopGrabbing.ForeColor = Color.White;
+            uiButtonStopGrabbing.Location = new Point(140, 140);
+            uiButtonStopGrabbing.Name = "uiButtonStopGrabbing";
+            uiButtonStopGrabbing.Size = new Size(100, 35);
+            uiButtonStopGrabbing.TabIndex = 5;
+            uiButtonStopGrabbing.Text = "鍋滄閲囬泦";
+            uiButtonStopGrabbing.UseVisualStyleBackColor = false;
+            uiButtonStopGrabbing.Click += uiButtonStopGrabbing_Click;
+            //
+            // uiButtonSoftTrigger
+            //
+            uiButtonSoftTrigger.BackColor = Color.FromArgb(64, 158, 255);
+            uiButtonSoftTrigger.ForeColor = Color.White;
+            uiButtonSoftTrigger.Location = new Point(260, 140);
+            uiButtonSoftTrigger.Name = "uiButtonSoftTrigger";
+            uiButtonSoftTrigger.Size = new Size(75, 35);
+            uiButtonSoftTrigger.TabIndex = 6;
+            uiButtonSoftTrigger.Text = "瑙﹀彂";
+            uiButtonSoftTrigger.UseVisualStyleBackColor = false;
+            uiButtonSoftTrigger.Click += uiButtonSoftTrigger_Click;
+            //
+            // uiListBoxBarcodes
+            //
+            uiListBoxBarcodes.FormattingEnabled = true;
+            uiListBoxBarcodes.ItemHeight = 20;
+            uiListBoxBarcodes.Location = new Point(15, 35);
+            uiListBoxBarcodes.Name = "uiListBoxBarcodes";
+            uiListBoxBarcodes.Size = new Size(320, 164);
+            uiListBoxBarcodes.TabIndex = 0;
+            //
+            // uiTextBoxResult
+            //
+            uiTextBoxResult.Location = new Point(90, 210);
+            uiTextBoxResult.Name = "uiTextBoxResult";
+            uiTextBoxResult.ReadOnly = true;
+            uiTextBoxResult.Size = new Size(160, 26);
+            uiTextBoxResult.TabIndex = 1;
+            //
+            // uiLabel2
+            //
+            uiLabel2.Location = new Point(15, 210);
+            uiLabel2.Name = "uiLabel2";
+            uiLabel2.Size = new Size(70, 29);
+            uiLabel2.TabIndex = 2;
+            uiLabel2.Text = "鐘舵��:";
+            uiLabel2.TextAlign = ContentAlignment.MiddleRight;
+            //
+            // uiButtonClear
+            //
+            uiButtonClear.BackColor = Color.FromArgb(64, 158, 255);
+            uiButtonClear.ForeColor = Color.White;
+            uiButtonClear.Location = new Point(260, 208);
+            uiButtonClear.Name = "uiButtonClear";
+            uiButtonClear.Size = new Size(75, 30);
+            uiButtonClear.TabIndex = 3;
+            uiButtonClear.Text = "娓呯┖";
+            uiButtonClear.UseVisualStyleBackColor = false;
+            uiButtonClear.Click += uiButtonClear_Click;
+            //
+            // BarcodeReaderForm
+            //
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            BackColor = Color.FromArgb(32, 41, 50);
+            ClientSize = new Size(800, 530);
+            Controls.Add(uiGroupBoxResult);
+            Controls.Add(uiGroupBoxControl);
+            Controls.Add(uiGroupBoxImage);
+            Name = "BarcodeReaderForm";
+            StartPosition = FormStartPosition.CenterScreen;
+            Text = "璇荤爜鍣ㄦ祴璇�";
+            FormClosing += BarcodeReaderForm_FormClosing;
+            uiGroupBoxImage.ResumeLayout(false);
+            uiGroupBoxControl.ResumeLayout(false);
+            uiGroupBoxResult.ResumeLayout(false);
+            uiGroupBoxResult.PerformLayout();
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private GroupBox uiGroupBoxImage;
+        private GroupBox uiGroupBoxControl;
+        private GroupBox uiGroupBoxResult;
+        private ComboBox uiComboBoxBrand;
+        private Label uiLabel1;
+        private RadioButton uiRadioButtonSoftTrigger;
+        private RadioButton uiRadioButtonHardTrigger;
+        private Button uiButtonStartGrabbing;
+        private Button uiButtonStopGrabbing;
+        private Button uiButtonSoftTrigger;
+        private ListBox uiListBoxBarcodes;
+        private TextBox uiTextBoxResult;
+        private Label uiLabel2;
+        private Button uiButtonClear;
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/BarcodeReaderPage/BarcodeReaderForm.cs b/LB_SmartVision/Forms/Pages/BarcodeReaderPage/BarcodeReaderForm.cs
new file mode 100644
index 0000000..66da515
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/BarcodeReaderPage/BarcodeReaderForm.cs
@@ -0,0 +1,207 @@
+using LB_VisionProcesses.BarcodeReaders;
+using System;
+using System.Diagnostics;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace LB_SmartVision.Forms.Pages.BarcodeReaderPage
+{
+    public partial class BarcodeReaderForm : Form
+    {
+        BarcodeReaderBase barcodeReader { get; set; }
+        PictureBox pictureBox1 { get; set; }
+
+        public BarcodeReaderForm()
+        {
+            InitializeComponent();
+        }
+
+        public BarcodeReaderForm(BarcodeReaderBase reader)
+        {
+            InitializeComponent();
+
+            // 鍒涘缓鍥惧儚鏄剧ず鎺т欢
+            pictureBox1 = new PictureBox();
+            pictureBox1.Dock = DockStyle.Fill;
+            pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
+            uiGroupBoxImage.Controls.Add(pictureBox1);
+
+            if (reader == null)
+                return;
+
+            this.barcodeReader = reader;
+            this.Text = reader.SN;
+
+            // 娣诲姞鍝佺墝閫夐」
+            foreach (BarcodeReaderBrand brand in Enum.GetValues(typeof(BarcodeReaderBrand)))
+            {
+                if (brand != BarcodeReaderBrand.Unsupported)
+                    uiComboBoxBrand.Items.Add(brand.ToString());
+            }
+
+            // 璁剧疆鍝佺墝
+            uiComboBoxBrand.Text = reader.Brand.ToString();
+
+            // 鍔犺浇鍥炶皟鍑芥暟
+            Subscribe();
+        }
+
+        private void BarcodeReaderForm_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            if (barcodeReader == null)
+                return;
+
+            barcodeReader.StopGrabbing();
+            Unsubscribe();
+        }
+
+        public void Unsubscribe()
+        {
+            try
+            {
+                if (barcodeReader == null)
+                    return;
+                // 鍙栨秷鍥炶皟鍑芥暟
+                barcodeReader.BarcodeRead -= OnBarcodeRead;
+            }
+            catch (Exception ex)
+            {
+                // 璁板綍閿欒淇℃伅
+                Debug.WriteLine($"閿欒: {ex.Message}");
+            }
+        }
+
+        public void Subscribe()
+        {
+            try
+            {
+                if (barcodeReader == null)
+                    return;
+
+                // 鍙栨秷鍥炶皟鍑芥暟
+                barcodeReader.BarcodeRead -= OnBarcodeRead;
+                // 鍔犺浇鍥炶皟鍑芥暟
+                barcodeReader.BarcodeRead += OnBarcodeRead;
+            }
+            catch (Exception ex)
+            {
+                // 璁板綍閿欒淇℃伅
+                Debug.WriteLine($"閿欒: {ex.Message}");
+            }
+        }
+
+        private void OnBarcodeRead(object sender, BarcodeEventArgs e)
+        {
+            if (e.Barcodes == null || e.Barcodes.Count == 0)
+                return;
+
+            if (this.InvokeRequired)
+            {
+                this.Invoke(new Action(() =>
+                {
+                    DisplayBarcodeResult(e);
+                }));
+            }
+            else
+            {
+                DisplayBarcodeResult(e);
+            }
+        }
+
+        private void DisplayBarcodeResult(BarcodeEventArgs e)
+        {
+            uiListBoxBarcodes.Items.Clear();
+            if (e.BarcodeInfos != null && e.BarcodeInfos.Count > 0)
+            {
+                foreach (var info in e.BarcodeInfos)
+                {
+                    uiListBoxBarcodes.Items.Add(info.Text);
+                }
+            }
+
+            if (e.Image != null)
+            {
+                // 鍒涘缓鍥惧儚鍓湰杩涜缁樺埗
+                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 = pictureBox1.Image;
+                pictureBox1.Image = drawImg;
+                oldImg?.Dispose();
+            }
+
+            uiTextBoxResult.Text = $"璇诲彇鍒皗e.BarcodeInfos.Count}涓潯鐮�";
+        }
+
+        private void uiRadioButtonSoftTrigger_CheckedChanged(object sender, EventArgs e)
+        {
+            uiButtonSoftTrigger.Enabled = uiRadioButtonSoftTrigger.Checked;
+
+            if (barcodeReader == null)
+                return;
+
+            barcodeReader.SetTriggerMode(uiRadioButtonSoftTrigger.Checked);
+        }
+
+        private void uiButtonStartGrabbing_Click(object sender, EventArgs e)
+        {
+            if (barcodeReader == null)
+                return;
+
+            if (barcodeReader.StartGrabbing())
+            {
+                uiButtonStartGrabbing.Enabled = false;
+                uiButtonStopGrabbing.Enabled = true;
+            }
+        }
+
+        private void uiButtonStopGrabbing_Click(object sender, EventArgs e)
+        {
+            if (barcodeReader == null)
+                return;
+
+            if (barcodeReader.StopGrabbing())
+            {
+                uiButtonStartGrabbing.Enabled = true;
+                uiButtonStopGrabbing.Enabled = false;
+            }
+        }
+
+        private void uiButtonSoftTrigger_Click(object sender, EventArgs e)
+        {
+            if (barcodeReader == null)
+                return;
+
+            barcodeReader.SoftTrigger();
+        }
+
+        private void uiButtonClear_Click(object sender, EventArgs e)
+        {
+            uiListBoxBarcodes.Items.Clear();
+            uiTextBoxResult.Text = "";
+            if (pictureBox1 != null)
+                pictureBox1.Image = null;
+        }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/BarcodeReaderPage/BarcodeReadersEditPage.Designer.cs b/LB_SmartVision/Forms/Pages/BarcodeReaderPage/BarcodeReadersEditPage.Designer.cs
new file mode 100644
index 0000000..4f738aa
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/BarcodeReaderPage/BarcodeReadersEditPage.Designer.cs
@@ -0,0 +1,152 @@
+using ReaLTaiizor.Controls;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace LB_SmartVision.Forms.Pages.BarcodeReaderPage
+{
+    partial class BarcodeReadersEditPage
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            uiButton1 = new HopeButton();
+            uiButton2 = new LostButton();
+            uiFlowLayoutPanel1 = new FlowLayoutPanel();
+            tableLayoutPanel1 = new TableLayoutPanel();
+            tableLayoutPanel2 = new TableLayoutPanel();
+            tableLayoutPanel1.SuspendLayout();
+            tableLayoutPanel2.SuspendLayout();
+            SuspendLayout();
+            //
+            // uiButton1
+            //
+            uiButton1.BorderColor = Color.FromArgb(220, 223, 230);
+            uiButton1.ButtonType = ReaLTaiizor.Util.HopeButtonType.Primary;
+            uiButton1.Cursor = Cursors.Hand;
+            uiButton1.DangerColor = Color.FromArgb(245, 108, 108);
+            uiButton1.DefaultColor = Color.FromArgb(255, 255, 255);
+            uiButton1.Dock = DockStyle.Fill;
+            uiButton1.Font = new Font("瀹嬩綋", 12F);
+            uiButton1.HoverTextColor = Color.FromArgb(48, 49, 51);
+            uiButton1.InfoColor = Color.FromArgb(144, 147, 153);
+            uiButton1.Location = new Point(503, 3);
+            uiButton1.MinimumSize = new Size(1, 1);
+            uiButton1.Name = "uiButton1";
+            uiButton1.PrimaryColor = Color.FromArgb(64, 158, 255);
+            uiButton1.Size = new Size(95, 38);
+            uiButton1.SuccessColor = Color.FromArgb(103, 194, 58);
+            uiButton1.TabIndex = 11;
+            uiButton1.Text = "鏂板";
+            uiButton1.TextColor = Color.White;
+            uiButton1.WarningColor = Color.FromArgb(230, 162, 60);
+            uiButton1.Click += uiButton1_Click;
+            //
+            // uiButton2
+            //
+            uiButton2.BackColor = Color.FromArgb(39, 41, 60);
+            uiButton2.Cursor = Cursors.Hand;
+            uiButton2.Dock = DockStyle.Fill;
+            uiButton2.Font = new Font("瀹嬩綋", 12F);
+            uiButton2.ForeColor = Color.White;
+            uiButton2.HoverColor = Color.DodgerBlue;
+            uiButton2.Image = null;
+            uiButton2.Location = new Point(403, 3);
+            uiButton2.MinimumSize = new Size(1, 1);
+            uiButton2.Name = "uiButton2";
+            uiButton2.Size = new Size(94, 38);
+            uiButton2.TabIndex = 12;
+            uiButton2.Text = "鍏ㄩ儴娓呴櫎";
+            uiButton2.Click += uiButton2_Click;
+            //
+            // uiFlowLayoutPanel1
+            //
+            uiFlowLayoutPanel1.BackColor = Color.FromArgb(32, 41, 50);
+            uiFlowLayoutPanel1.Dock = DockStyle.Fill;
+            uiFlowLayoutPanel1.Font = new Font("瀹嬩綋", 12F);
+            uiFlowLayoutPanel1.ForeColor = SystemColors.Control;
+            uiFlowLayoutPanel1.Location = new Point(4, 5);
+            uiFlowLayoutPanel1.Margin = new Padding(4, 5, 4, 5);
+            uiFlowLayoutPanel1.MinimumSize = new Size(1, 1);
+            uiFlowLayoutPanel1.Name = "uiFlowLayoutPanel1";
+            uiFlowLayoutPanel1.Padding = new Padding(2);
+            uiFlowLayoutPanel1.Size = new Size(599, 293);
+            uiFlowLayoutPanel1.TabIndex = 10;
+            //
+            // tableLayoutPanel1
+            //
+            tableLayoutPanel1.ColumnCount = 1;
+            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.Controls.Add(uiFlowLayoutPanel1, 0, 0);
+            tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 0, 1);
+            tableLayoutPanel1.Dock = DockStyle.Fill;
+            tableLayoutPanel1.Location = new Point(0, 0);
+            tableLayoutPanel1.Name = "tableLayoutPanel1";
+            tableLayoutPanel1.RowCount = 2;
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F));
+            tableLayoutPanel1.Size = new Size(607, 353);
+            tableLayoutPanel1.TabIndex = 13;
+            //
+            // tableLayoutPanel2
+            //
+            tableLayoutPanel2.ColumnCount = 6;
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 16.666666F));
+            tableLayoutPanel2.Controls.Add(uiButton1, 5, 0);
+            tableLayoutPanel2.Controls.Add(uiButton2, 4, 0);
+            tableLayoutPanel2.Dock = DockStyle.Fill;
+            tableLayoutPanel2.Location = new Point(3, 306);
+            tableLayoutPanel2.Name = "tableLayoutPanel2";
+            tableLayoutPanel2.RowCount = 1;
+            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
+            tableLayoutPanel2.Size = new Size(601, 44);
+            tableLayoutPanel2.TabIndex = 11;
+            //
+            // BarcodeReadersEditPage
+            //
+            BackColor = Color.FromArgb(32, 41, 50);
+            Controls.Add(tableLayoutPanel1);
+            Name = "BarcodeReadersEditPage";
+            Size = new Size(607, 353);
+            Paint += BarcodeReadersEditPage_Paint;
+            tableLayoutPanel1.ResumeLayout(false);
+            tableLayoutPanel2.ResumeLayout(false);
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private HopeButton uiButton1;
+        private LostButton uiButton2;
+        private FlowLayoutPanel uiFlowLayoutPanel1;
+        private TableLayoutPanel tableLayoutPanel1;
+        private TableLayoutPanel tableLayoutPanel2;
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/BarcodeReaderPage/BarcodeReadersEditPage.cs b/LB_SmartVision/Forms/Pages/BarcodeReaderPage/BarcodeReadersEditPage.cs
new file mode 100644
index 0000000..6bee541
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/BarcodeReaderPage/BarcodeReadersEditPage.cs
@@ -0,0 +1,226 @@
+using LB_VisionControl;
+using LB_VisionProcesses.BarcodeReaders;
+using LB_VisionProcesses.BarcodeReaders.Huayray;
+using System;
+using System.Collections.Concurrent;
+using System.Windows.Forms;
+
+namespace LB_SmartVision.Forms.Pages.BarcodeReaderPage
+{
+    public partial class BarcodeReadersEditPage : UserControl
+    {
+        public Action<string, LogInfoType> LogInfo;
+
+
+        public BarcodeReadersEditPage()
+        {
+            InitializeComponent();
+
+            Name = "BarcodeReadersEditPage";
+            Text = "璇荤爜鍣ㄨ缃�";
+        }
+
+        private void BarcodeReadersEditPage_Paint(object sender, PaintEventArgs e)
+        {
+            uiFlowLayoutPanel1.Controls.Clear();
+
+            if (GlobalVar.dicBarcodeReaders.Count <= 0)
+                return;
+
+            foreach (var item in GlobalVar.dicBarcodeReaders)
+            {
+                string ReaderSN = item.Key;
+                string ReaderBrand = item.Value.Brand.ToString();
+
+                if (string.IsNullOrEmpty(ReaderSN) || string.IsNullOrEmpty(ReaderBrand))
+                    continue;
+
+                UserItem flow = new UserItem(new string[] { "娴嬭瘯", "鍒锋柊", "绉婚櫎" });
+                flow.Name = ReaderSN;
+                flow.Text = $"[{ReaderBrand}] {ReaderSN}";
+                if (item.Value.IsConnected)
+                    flow.state = State.Pass;
+                else
+                    flow.state = State.Error;
+                LoadFlowEvent(flow);
+
+                uiFlowLayoutPanel1.Controls.Add(flow);
+            }
+        }
+
+
+        private void uiButton1_Click(object sender, System.EventArgs e)
+        {
+            CreateBarcodeReaderForm createForm = new CreateBarcodeReaderForm();
+            createForm.ShowDialog();
+
+            if (createForm.bCreate)
+            {
+                BarcodeReaderBase reader = createForm.barcodeReader;
+                if (GlobalVar.dicBarcodeReaders.ContainsKey(reader.SN))
+                {
+                    MessageBox.Show($"璇荤爜鍣╗{reader.SN}]宸插瓨鍦�!", "寮傚父");
+                    return;
+                }
+
+                string ReaderSN = reader.SN;
+                string ReaderBrand = reader.Brand.ToString();
+
+                if (string.IsNullOrEmpty(ReaderSN) || string.IsNullOrEmpty(ReaderBrand))
+                    return;
+
+                GlobalVar.dicBarcodeReaders.TryAdd(ReaderSN, reader);
+                LogInfo?.Invoke(string.Format("娣诲姞璇荤爜鍣╗{0}][{1}]鎴愬姛", ReaderBrand, ReaderSN), LogInfoType.PASS);
+            }
+            this.Invalidate();
+        }
+
+        private void uiButton2_Click(object sender, System.EventArgs e)
+        {
+            //娓呴櫎鐢–lear鏂规硶
+            uiFlowLayoutPanel1.Controls.Clear();
+            foreach (var reader in GlobalVar.dicBarcodeReaders.Values)
+            {
+                reader.Dispose();
+            }
+            GlobalVar.dicBarcodeReaders.Clear();
+        }
+
+        private void LoadFlowEvent(UserItem flow)
+        {
+            //鎸夐敭1涓烘祴璇�
+            flow.MenuItem1ClickedEvent += TestEvent;
+            //鎸夐敭2涓哄埛鏂�
+            flow.MenuItem2ClickedEvent += ReconnectEvent;
+            //鎸夐敭3涓虹Щ闄�
+            flow.MenuItem3ClickedEvent += DeleteEvent;
+        }
+
+        private void RemoveFlowEvent(UserItem flow)
+        {
+            //鎸夐敭1涓烘祴璇�
+            flow.MenuItem1ClickedEvent -= TestEvent;
+            //鎸夐敭2涓哄埛鏂�
+            flow.MenuItem2ClickedEvent -= ReconnectEvent;
+            //鎸夐敭3涓虹Щ闄�
+            flow.MenuItem3ClickedEvent -= DeleteEvent;
+        }
+
+        // 娴嬭瘯璇荤爜鍣�
+        private void TestEvent(string Name, string Text)
+        {
+            for (int i = 0; i < uiFlowLayoutPanel1.Controls.Count; i++)
+            {
+                UserItem flow = (UserItem)uiFlowLayoutPanel1.Controls[i];
+                string name = flow.Name;
+                if (name != Name)
+                    continue;
+
+                if (GlobalVar.dicBarcodeReaders.ContainsKey(name))
+                {
+                    BarcodeReaderForm readerForm = new BarcodeReaderForm(GlobalVar.dicBarcodeReaders[name]);
+                    readerForm.Show();
+                }
+            }
+        }
+
+        // 绉婚櫎璇荤爜鍣�
+        private void DeleteEvent(string Name, string Text)
+        {
+            for (int i = 0; i < uiFlowLayoutPanel1.Controls.Count; i++)
+            {
+                UserItem flow = (UserItem)uiFlowLayoutPanel1.Controls[i];
+                string name = flow.Name;
+                if (name != Name)
+                    continue;
+
+                RemoveFlowEvent(flow);
+                uiFlowLayoutPanel1.Controls.Remove(uiFlowLayoutPanel1.Controls[i]);
+                if (GlobalVar.dicBarcodeReaders.TryRemove(name, out BarcodeReaderBase barcodeReader))
+                {
+                    barcodeReader.Dispose();
+                    LogInfo?.Invoke(string.Format("绉婚櫎璇荤爜鍣╗{0}]", name), LogInfoType.INFO);
+                }
+                else
+                    LogInfo?.Invoke(string.Format("绉婚櫎璇荤爜鍣╗{0}]澶辫触", name), LogInfoType.ERROR);
+
+            }
+        }
+
+        // 閲嶈繛璇荤爜鍣�
+        private void ReconnectEvent(string Name, string Text)
+        {
+            for (int i = 0; i < uiFlowLayoutPanel1.Controls.Count; i++)
+            {
+                UserItem flow = (UserItem)uiFlowLayoutPanel1.Controls[i];
+                string name = flow.Name;
+                if (name != Name)
+                    continue;
+
+                if (!GlobalVar.dicBarcodeReaders.ContainsKey(name))
+                {
+                    LogInfo?.Invoke(string.Format("璇荤爜鍣╗{0}]涓嶅瓨鍦�", name), LogInfoType.ERROR);
+                    flow.state = State.Error;
+                    flow.Refresh();
+                    return;
+                }
+
+                var reader = GlobalVar.dicBarcodeReaders[name];
+                if (reader == null)
+                {
+                    LogInfo?.Invoke(string.Format("璇荤爜鍣╗{0}]瀹炰緥涓虹┖", name), LogInfoType.ERROR);
+                    flow.state = State.Error;
+                    flow.Refresh();
+                    return;
+                }
+
+                try
+                {
+                    // 鍏堥噴鏀炬棫瀹炰緥鐨勮祫婧�
+                    reader.Dispose();
+
+                    // 娣诲姞鐭殏寤惰繜锛岀‘淇漇DK搴曞眰璧勬簮瀹屽叏閲婃斁
+                    System.Threading.Thread.Sleep(500);
+
+                    // 寮哄埗鍨冨溇鍥炴敹锛岀‘淇濈浉鏈哄璞¤瀹屽叏閲婃斁
+                    GC.Collect();
+                    GC.WaitForPendingFinalizers();
+                    GC.Collect();
+
+                    // 浠庡瓧鍏镐腑绉婚櫎鏃у疄渚�
+                    GlobalVar.dicBarcodeReaders.TryRemove(name, out _);
+
+                    // 鍒涘缓鏂板疄渚�
+                    BarcodeReaderBase newReader = null;
+                    switch (reader.Brand)
+                    {
+                        case BarcodeReaderBrand.Huayray:
+                            newReader = new HRBarcodeReader();
+                            break;
+                        default:
+                            throw new Exception($"涓嶆敮鎸佺殑璇荤爜鍣ㄥ搧鐗�: {reader.Brand}");
+                    }
+
+                    if (newReader.Open(name))
+                    {
+                        // 娣诲姞鍒板瓧鍏�
+                        GlobalVar.dicBarcodeReaders.TryAdd(name, newReader);
+                        flow.state = State.Pass;
+                        LogInfo?.Invoke(string.Format("閲嶈繛璇荤爜鍣╗{0}]鎴愬姛", name), LogInfoType.PASS);
+                    }
+                    else
+                    {
+                        flow.state = State.Error;
+                        LogInfo?.Invoke(string.Format("璇荤爜鍣╗{0}]閲嶆柊鍒涘缓鍚庝粛杩炴帴澶辫触", name), LogInfoType.ERROR);
+                    }
+                }
+                catch (Exception ex)
+                {
+                    flow.state = State.Error;
+                    LogInfo?.Invoke(string.Format("閲嶈繛璇荤爜鍣╗{0}]寮傚父: {1}", name, ex.Message), LogInfoType.ERROR);
+                }
+                flow.Refresh();
+            }
+        }
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/BarcodeReaderPage/CreateBarcodeReaderForm.Designer.cs b/LB_SmartVision/Forms/Pages/BarcodeReaderPage/CreateBarcodeReaderForm.Designer.cs
new file mode 100644
index 0000000..c359fe6
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/BarcodeReaderPage/CreateBarcodeReaderForm.Designer.cs
@@ -0,0 +1,178 @@
+using ReaLTaiizor.Controls;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace LB_SmartVision.Forms.Pages.BarcodeReaderPage
+{
+    partial class CreateBarcodeReaderForm
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            uiComboBoxBrand = new ComboBox();
+            uiComboBoxSN = new ComboBox();
+            uiLabel1 = new Label();
+            uiLabel2 = new Label();
+            uiButtonTest = new HopeButton();
+            uiButtonCreate = new HopeButton();
+            uiButtonCancel = new LostButton();
+            SuspendLayout();
+            //
+            // uiComboBoxBrand
+            //
+            uiComboBoxBrand.DropDownStyle = ComboBoxStyle.DropDownList;
+            uiComboBoxBrand.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            uiComboBoxBrand.FormattingEnabled = true;
+            uiComboBoxBrand.Location = new Point(127, 30);
+            uiComboBoxBrand.Name = "uiComboBoxBrand";
+            uiComboBoxBrand.Size = new Size(200, 28);
+            uiComboBoxBrand.TabIndex = 0;
+            uiComboBoxBrand.MouseClick += uiComboBoxBrand_MouseClick;
+            uiComboBoxBrand.SelectedIndexChanged += uiComboBoxBrand_SelectedIndexChanged;
+            //
+            // uiComboBoxSN
+            //
+            uiComboBoxSN.DropDownStyle = ComboBoxStyle.DropDownList;
+            uiComboBoxSN.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            uiComboBoxSN.FormattingEnabled = true;
+            uiComboBoxSN.Location = new Point(127, 80);
+            uiComboBoxSN.Name = "uiComboBoxSN";
+            uiComboBoxSN.Size = new Size(200, 28);
+            uiComboBoxSN.TabIndex = 1;
+            uiComboBoxSN.MouseClick += uiComboBoxSN_MouseClick;
+            //
+            // uiLabel1
+            //
+            uiLabel1.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            uiLabel1.ForeColor = Color.White;
+            uiLabel1.Location = new Point(25, 30);
+            uiLabel1.Name = "uiLabel1";
+            uiLabel1.Size = new Size(100, 29);
+            uiLabel1.TabIndex = 2;
+            uiLabel1.Text = "鍝佺墝:";
+            uiLabel1.TextAlign = ContentAlignment.MiddleRight;
+            //
+            // uiLabel2
+            //
+            uiLabel2.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            uiLabel2.ForeColor = Color.White;
+            uiLabel2.Location = new Point(25, 80);
+            uiLabel2.Name = "uiLabel2";
+            uiLabel2.Size = new Size(100, 29);
+            uiLabel2.TabIndex = 3;
+            uiLabel2.Text = "搴忓垪鍙�:";
+            uiLabel2.TextAlign = ContentAlignment.MiddleRight;
+            //
+            // uiButtonTest
+            //
+            uiButtonTest.BorderColor = Color.FromArgb(220, 223, 230);
+            uiButtonTest.ButtonType = ReaLTaiizor.Util.HopeButtonType.Primary;
+            uiButtonTest.Cursor = Cursors.Hand;
+            uiButtonTest.DangerColor = Color.FromArgb(245, 108, 108);
+            uiButtonTest.DefaultColor = Color.FromArgb(255, 255, 255);
+            uiButtonTest.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            uiButtonTest.HoverTextColor = Color.FromArgb(48, 49, 51);
+            uiButtonTest.InfoColor = Color.FromArgb(144, 147, 153);
+            uiButtonTest.Location = new Point(350, 52);
+            uiButtonTest.MinimumSize = new Size(1, 1);
+            uiButtonTest.Name = "uiButtonTest";
+            uiButtonTest.PrimaryColor = Color.FromArgb(64, 158, 255);
+            uiButtonTest.Size = new Size(100, 35);
+            uiButtonTest.SuccessColor = Color.FromArgb(103, 194, 58);
+            uiButtonTest.TabIndex = 4;
+            uiButtonTest.Text = "娴嬭瘯杩炴帴";
+            uiButtonTest.TextColor = Color.White;
+            uiButtonTest.WarningColor = Color.FromArgb(230, 162, 60);
+            uiButtonTest.Click += uiButtonTest_Click;
+            //
+            // uiButtonCreate
+            //
+            uiButtonCreate.BorderColor = Color.FromArgb(220, 223, 230);
+            uiButtonCreate.ButtonType = ReaLTaiizor.Util.HopeButtonType.Primary;
+            uiButtonCreate.Cursor = Cursors.Hand;
+            uiButtonCreate.DangerColor = Color.FromArgb(245, 108, 108);
+            uiButtonCreate.DefaultColor = Color.FromArgb(255, 255, 255);
+            uiButtonCreate.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            uiButtonCreate.HoverTextColor = Color.FromArgb(48, 49, 51);
+            uiButtonCreate.InfoColor = Color.FromArgb(144, 147, 153);
+            uiButtonCreate.Location = new Point(127, 140);
+            uiButtonCreate.MinimumSize = new Size(1, 1);
+            uiButtonCreate.Name = "uiButtonCreate";
+            uiButtonCreate.PrimaryColor = Color.FromArgb(0, 150, 136);
+            uiButtonCreate.Size = new Size(100, 35);
+            uiButtonCreate.SuccessColor = Color.FromArgb(103, 194, 58);
+            uiButtonCreate.TabIndex = 5;
+            uiButtonCreate.Text = "鍒涘缓";
+            uiButtonCreate.TextColor = Color.White;
+            uiButtonCreate.WarningColor = Color.FromArgb(230, 162, 60);
+            uiButtonCreate.Click += uiButtonCreate_Click;
+            //
+            // uiButtonCancel
+            //
+            uiButtonCancel.BackColor = Color.FromArgb(39, 41, 60);
+            uiButtonCancel.Cursor = Cursors.Hand;
+            uiButtonCancel.Font = new Font("瀹嬩綋", 12F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            uiButtonCancel.ForeColor = Color.White;
+            uiButtonCancel.HoverColor = Color.DodgerBlue;
+            uiButtonCancel.Image = null;
+            uiButtonCancel.Location = new Point(245, 140);
+            uiButtonCancel.MinimumSize = new Size(1, 1);
+            uiButtonCancel.Name = "uiButtonCancel";
+            uiButtonCancel.Size = new Size(100, 35);
+            uiButtonCancel.TabIndex = 6;
+            uiButtonCancel.Text = "鍙栨秷";
+            uiButtonCancel.Click += uiButtonCancel_Click;
+            //
+            // CreateBarcodeReaderForm
+            //
+            AutoScaleDimensions = new SizeF(7F, 17F);
+            AutoScaleMode = AutoScaleMode.Font;
+            BackColor = Color.FromArgb(32, 41, 50);
+            ClientSize = new Size(484, 211);
+            Controls.Add(uiButtonCancel);
+            Controls.Add(uiButtonCreate);
+            Controls.Add(uiButtonTest);
+            Controls.Add(uiLabel2);
+            Controls.Add(uiLabel1);
+            Controls.Add(uiComboBoxSN);
+            Controls.Add(uiComboBoxBrand);
+            Name = "CreateBarcodeReaderForm";
+            StartPosition = FormStartPosition.CenterParent;
+            Text = "娣诲姞璇荤爜鍣�";
+            ResumeLayout(false);
+        }
+
+        #endregion
+
+        private ComboBox uiComboBoxBrand;
+        private ComboBox uiComboBoxSN;
+        private Label uiLabel1;
+        private Label uiLabel2;
+        private HopeButton uiButtonTest;
+        private HopeButton uiButtonCreate;
+        private LostButton uiButtonCancel;
+    }
+}
diff --git a/LB_SmartVision/Forms/Pages/BarcodeReaderPage/CreateBarcodeReaderForm.cs b/LB_SmartVision/Forms/Pages/BarcodeReaderPage/CreateBarcodeReaderForm.cs
new file mode 100644
index 0000000..363e9df
--- /dev/null
+++ b/LB_SmartVision/Forms/Pages/BarcodeReaderPage/CreateBarcodeReaderForm.cs
@@ -0,0 +1,117 @@
+using LB_VisionProcesses.BarcodeReaders;
+using LB_VisionProcesses.BarcodeReaders.Huayray;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace LB_SmartVision.Forms.Pages.BarcodeReaderPage
+{
+    public partial class CreateBarcodeReaderForm : Form
+    {
+        public BarcodeReaderBase barcodeReader { get; set; }
+        public bool bCreate = false;
+
+        public CreateBarcodeReaderForm(BarcodeReaderBase reader = null)
+        {
+            InitializeComponent();
+            // 绂佹淇敼绐楀彛澶у皬
+            this.FormBorderStyle = FormBorderStyle.FixedDialog;
+            if (reader == null)
+                this.barcodeReader = new HRBarcodeReader();
+            else
+                this.barcodeReader = reader;
+
+            uiButtonCreate.Enabled = false;
+        }
+
+        private void uiButtonTest_Click(object sender, EventArgs e)
+        {
+            uiButtonCreate.Enabled = false;
+
+            if (string.IsNullOrEmpty(uiComboBoxSN.Text))
+                MessageBox.Show($"鍒濆鍖栬鐮佸櫒[{uiComboBoxSN.Text}]涓虹┖!", "寮傚父");
+
+            if (barcodeReader == null)
+            {
+                MessageBox.Show("璇峰厛閫夋嫨璇荤爜鍣ㄥ搧鐗�!", "寮傚父");
+                return;
+            }
+
+            barcodeReader.Close();
+            if (barcodeReader.Open(uiComboBoxSN.Text))
+            {
+                uiButtonCreate.Enabled = true;
+                barcodeReader.Close();
+            }
+            else
+                MessageBox.Show($"鍒濆鍖栬鐮佸櫒[{uiComboBoxSN.Text}]澶辫触!", "寮傚父");
+        }
+
+        private void uiButtonCreate_Click(object sender, EventArgs e)
+        {
+            if (barcodeReader.Open(uiComboBoxSN.Text))
+            {
+                barcodeReader.SN = uiComboBoxSN.Text;
+                bCreate = true;
+                this.Close();
+            }
+            else
+                MessageBox.Show($"鍒濆鍖栬鐮佸櫒[{uiComboBoxSN.Text}]澶辫触!", "寮傚父");
+        }
+
+        private void uiButtonCancel_Click(object sender, EventArgs e)
+        {
+            if (barcodeReader != null)
+                barcodeReader.Close();
+            bCreate = false;
+            this.Close();
+        }
+
+        private void uiComboBoxBrand_MouseClick(object sender, MouseEventArgs e)
+        {
+            uiComboBoxBrand.Items.Clear();
+            foreach (BarcodeReaderBrand brand in Enum.GetValues(typeof(BarcodeReaderBrand)))
+            {
+                if (brand != BarcodeReaderBrand.Unsupported)
+                    uiComboBoxBrand.Items.Add(brand.ToString());
+            }
+        }
+
+        private void uiComboBoxBrand_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            uiButtonCreate.Enabled = false;
+            uiComboBoxSN.Text = string.Empty;
+
+            if (barcodeReader != null)
+                barcodeReader.Close();
+
+            Enum.TryParse<BarcodeReaderBrand>(uiComboBoxBrand.Text, out BarcodeReaderBrand brand);
+            switch (brand)
+            {
+                case BarcodeReaderBrand.Huayray:
+                    barcodeReader = new HRBarcodeReader();
+                    break;
+                default:
+                    return;
+            }
+        }
+
+        private void uiComboBoxSN_MouseClick(object sender, MouseEventArgs e)
+        {
+            uiButtonCreate.Enabled = false;
+            uiComboBoxSN.Text = string.Empty;
+
+            uiComboBoxSN.Items.Clear();
+            var list = barcodeReader.GetDeviceList();
+
+            foreach (string sn in list)
+                uiComboBoxSN.Items.Add(sn);
+        }
+    }
+}
diff --git a/LB_SmartVision/GlobalVar.cs b/LB_SmartVision/GlobalVar.cs
index eff8e9e..90c2f9c 100644
--- a/LB_SmartVision/GlobalVar.cs
+++ b/LB_SmartVision/GlobalVar.cs
@@ -88,6 +88,13 @@
 
         #endregion
 
+        #region 璇荤爜鍣�
+        public static ConcurrentDictionary<string, string> allBarcodeReadersConnectionString = new ConcurrentDictionary<string, string>();
+        public static string allBarcodeReadersConnectionStringPath
+            => GlobalVar.strApplicationPath + "\\鎵�鏈変骇鍝乗\" + GlobalVar.strProductName + "\\A_BarcodeReaderConnections.json";
+
+        #endregion
+
         #region 娴佺▼
         public static Dictionary<string, object> ControlStates { get; set; } = new Dictionary<string, object>();
 
diff --git a/LB_SmartVision/VisionForm.cs b/LB_SmartVision/VisionForm.cs
index 8a041a1..216c564 100644
--- a/LB_SmartVision/VisionForm.cs
+++ b/LB_SmartVision/VisionForm.cs
@@ -1,6 +1,7 @@
 锘縰sing HalconDotNet;
 using LB_SmartVision.Forms;
 using LB_SmartVision.Forms.Pages;
+using LB_SmartVision.Forms.Pages.BarcodeReaderPage;
 using LB_SmartVision.Forms.Pages.CameraPage;
 using LB_SmartVision.Forms.Pages.CommunicatorPage;
 using LB_SmartVision.Forms.Pages.HistoricalData;
@@ -18,6 +19,8 @@
 using LB_VisionProcesses.Cameras;
 using LB_VisionProcesses.Cameras.HRCameras;
 using LB_VisionProcesses.Cameras.LBCameras;
+using LB_VisionProcesses.BarcodeReaders;
+using LB_VisionProcesses.BarcodeReaders.Huayray;
 using LB_VisionProcesses.Communicators;
 using LB_VisionProcesses.Communicators.SiemensS7;
 using LB_VisionProcesses.Communicators.TCom;
@@ -46,6 +49,7 @@
     {
         AllProcessesPage AllProcessesPages = new AllProcessesPage();
         CamerasEditPage CamerasEditPage = new CamerasEditPage();
+        BarcodeReadersEditPage BarcodeReadersEditPage = new BarcodeReadersEditPage();
         HistoricalDataEditPage HistoricalDataEditPage = new HistoricalDataEditPage();
         CommunicatorsEditPage CommunicatorsEditPage = new CommunicatorsEditPage();
         SettingEditPage SettingEditPage = new SettingEditPage();
@@ -68,6 +72,7 @@
 
             GlobalVar.dicCommunicators.DictionaryChanged += CommunicatorsChanged;
             GlobalVar.dicCameras.DictionaryChanged += CamerasChanged;
+            GlobalVar.dicBarcodeReaders.DictionaryChanged += BarcodeReadersChanged;
             GlobalVar.dicProcesses.DictionaryChanged += ProcessRunBllChanged;
 
             //鏈�寮�濮嬪氨娓呯┖鎵�鏈塗ab椤�
@@ -80,6 +85,9 @@
 
             CamerasEditPage.LogInfo += LogInfo;
             materialTabControl.Controls.Add(new MyPage(CamerasEditPage));
+
+            BarcodeReadersEditPage.LogInfo += LogInfo;
+            materialTabControl.Controls.Add(new MyPage(BarcodeReadersEditPage));
 
             CommunicatorsEditPage.LogInfo += LogInfo;
             materialTabControl.Controls.Add(new MyPage(CommunicatorsEditPage));
@@ -573,6 +581,26 @@
             catch { }
         }
 
+        private void BarcodeReadersChanged(object sender, DictionaryChangedEventArgs<string, BarcodeReaderBase> e)
+        {
+            try
+            {
+                switch (e.ChangeType)
+                {
+                    case DictionaryChangeType.Added:
+                        LogInfo($"璇荤爜鍣╗{e.NewValue.SN}]鍔犺浇鎴愬姛", LogInfoType.INFO);
+                        e.NewValue.SN = e.NewKey;
+                        break;
+                    case DictionaryChangeType.Removed:
+                        if (e.OldValue != null)
+                            e.OldValue.Dispose();
+                        LogInfo($"璇荤爜鍣╗{e.OldValue.SN}]宸茬Щ闄�", LogInfoType.INFO);
+                        break;
+                }
+            }
+            catch { }
+        }
+
         private void VisionForm_Load(object sender, EventArgs e)
         {
             XmlConfigurator.Configure(new System.IO.FileInfo("log4net.config"));
@@ -623,6 +651,21 @@
             else
             {
                 LogInfo("鐩告満鍔犺浇澶辫触", LogInfoType.ERROR);
+            }
+
+            //鍔犺浇璇荤爜鍣�
+            foreach (var reader in GlobalVar.dicBarcodeReaders.Values)
+            {
+                reader.Dispose();
+            }
+            GlobalVar.dicBarcodeReaders.Clear();
+            if (LoadAllBarcodeReaders(GlobalVar.allBarcodeReadersConnectionStringPath))
+            {
+                LogInfo("璇荤爜鍣ㄥ姞杞芥垚鍔�", LogInfoType.PASS);
+            }
+            else
+            {
+                LogInfo("璇荤爜鍣ㄥ姞杞藉け璐�", LogInfoType.ERROR);
             }
             //鍔犺浇鍏ㄥ眬鍙橀噺
             IProcess.dicGlobalVars.Clear();
@@ -705,6 +748,7 @@
             SaveAllProcessVars();
             SaveAllCommunicators();
             SaveAllCameras();
+            SaveAllBarcodeReaders();
             SaveAllProcessSetting();
             SaveAllLayout();
             SaveAllCsv();
@@ -862,6 +906,105 @@
             catch { return false; }
         }
 
+        public bool LoadAllBarcodeReaders(string allBarcodeReadersConnectionStringPath)
+        {
+            if (!File.Exists(allBarcodeReadersConnectionStringPath))
+            {
+                Debug.WriteLine("璇荤爜鍣ㄩ厤缃枃浠朵笉瀛樺湪锛屽垱寤虹┖鏂囦欢");
+                SaveAllBarcodeReaders();
+                return true;
+            }
+            string strJson = string.Empty;
+            using (StreamReader streamReader = new StreamReader(allBarcodeReadersConnectionStringPath, Encoding.UTF8))
+            {
+                strJson = streamReader.ReadToEnd();
+                streamReader.Close();
+            }
+            GlobalVar.allBarcodeReadersConnectionString = JsonConvert.DeserializeObject<ConcurrentDictionary<string, string>>(strJson);
+            if (GlobalVar.allBarcodeReadersConnectionString == null)
+            {
+                MessageBox.Show("璇荤爜鍣ㄥ姞杞藉け璐�!", "寮傚父");
+                return false;
+            }
+            BarcodeReaderBase reader = null;
+            foreach (var ReaderConnectionString in GlobalVar.allBarcodeReadersConnectionString)
+            {
+                Enum.TryParse<BarcodeReaderBrand>(ReaderConnectionString.Value, out BarcodeReaderBrand brand);
+                switch (brand)
+                {
+                    case BarcodeReaderBrand.Huayray:
+                        {
+                            reader = new HRBarcodeReader();
+                            break;
+                        }
+                    default:
+                        {
+                            MessageBox.Show($"[{ReaderConnectionString.Key}]璇荤爜鍣ㄥ搧鐗屼笉鏀寔!", "寮傚父");
+                            continue;
+                        }
+                }
+                reader.SN = ReaderConnectionString.Key;
+                if (!reader.Open(ReaderConnectionString.Key))
+                {
+                    LogInfo($"鍒濆鍖栬鐮佸櫒[{ReaderConnectionString.Key}]澶辫触", LogInfoType.ERROR);
+                    reader.IsConnected = false;
+                    reader.IsGrabbing = false;
+                }
+                else
+                {
+                    LogInfo($"鍒濆鍖栬鐮佸櫒[{ReaderConnectionString.Key}]鎴愬姛", LogInfoType.PASS);
+                }
+
+                GlobalVar.dicBarcodeReaders.TryAdd(ReaderConnectionString.Key, reader);
+            }
+
+            return true;
+        }
+
+        public bool SaveAllBarcodeReaders()
+        {
+            try
+            {
+                string strJson = string.Empty;
+                GlobalVar.allBarcodeReadersConnectionString = new ConcurrentDictionary<string, string>();
+
+                foreach (var item in GlobalVar.dicBarcodeReaders)
+                {
+                    string ReaderSN = item.Value.SN;
+                    string ReaderBrand = item.Value.Brand.ToString();
+
+                    if (string.IsNullOrEmpty(ReaderSN) || string.IsNullOrEmpty(ReaderBrand))
+                    {
+                        break;
+                    }
+                    GlobalVar.allBarcodeReadersConnectionString.TryAdd(ReaderSN, ReaderBrand);
+                }
+                var settings = new JsonSerializerSettings
+                {
+                    Formatting = Formatting.Indented,
+                    ContractResolver = new DefaultContractResolver
+                    {
+                        NamingStrategy = new CamelCaseNamingStrategy()
+                    }
+                };
+
+                strJson = JsonConvert.SerializeObject(GlobalVar.allBarcodeReadersConnectionString, settings);
+                string directoryPath = Path.GetDirectoryName(GlobalVar.allBarcodeReadersConnectionStringPath);
+                if (!Directory.Exists(directoryPath))
+                {
+                    try
+                    {
+                        Directory.CreateDirectory(directoryPath);
+                    }
+                    catch (Exception)
+                    { }
+                }
+                File.WriteAllText(GlobalVar.allBarcodeReadersConnectionStringPath, strJson, Encoding.UTF8);
+                return true;
+            }
+            catch { return false; }
+        }
+
 
         public bool LoadAllCommunicators(string allCommunicatorsConnectionStringPath)
         {
diff --git a/LB_VisionProcesses/BarcodeReaders/BarcodeReaderBase.cs b/LB_VisionProcesses/BarcodeReaders/BarcodeReaderBase.cs
index b5814a7..83fd230 100644
--- a/LB_VisionProcesses/BarcodeReaders/BarcodeReaderBase.cs
+++ b/LB_VisionProcesses/BarcodeReaders/BarcodeReaderBase.cs
@@ -10,11 +10,11 @@
     {
         public virtual event EventHandler<BarcodeEventArgs> BarcodeRead;
 
-        public virtual string SN { get; protected set; } = string.Empty;
+        public virtual string SN { get; set; } = string.Empty;
 
-        public virtual bool IsConnected { get; protected set; } = false;
+        public virtual bool IsConnected { get; set; } = false;
 
-        public virtual bool IsGrabbing { get; protected set; } = false;
+        public virtual bool IsGrabbing { get; set; } = false;
 
         public abstract BarcodeReaderBrand Brand { get; }
 
@@ -50,6 +50,8 @@
                 {
                     Close();
                 }
+                IsConnected = false;
+                IsGrabbing = false;
             }
             catch { }
         }
diff --git a/LB_VisionProcesses/BarcodeReaders/BarcodeReaderForm.cs b/LB_VisionProcesses/BarcodeReaders/BarcodeReaderForm.cs
index 34a5867..911612c 100644
--- a/LB_VisionProcesses/BarcodeReaders/BarcodeReaderForm.cs
+++ b/LB_VisionProcesses/BarcodeReaders/BarcodeReaderForm.cs
@@ -22,6 +22,18 @@
             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();
@@ -192,11 +204,11 @@
             {
                 // 鏇存柊缁撴灉鍒楄〃
                 lstBarcodes.Items.Clear();
-                if (e.Barcodes != null && e.Barcodes.Count > 0)
+                if (e.BarcodeInfos != null && e.BarcodeInfos.Count > 0)
                 {
-                    foreach (var code in e.Barcodes)
+                    foreach (var info in e.BarcodeInfos)
                     {
-                        lstBarcodes.Items.Add($"{DateTime.Now:HH:mm:ss} - {code}");
+                        lstBarcodes.Items.Add($"{DateTime.Now:HH:mm:ss} - {info.Text}");
                     }
                 }
                 else
@@ -204,12 +216,40 @@
                     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 = new Bitmap(e.Image); // 鎷疯礉涓�浠介槻姝㈣ SDK 鍐呴儴閲婃斁
+                    picPreview.Image = drawImg;
                     oldImg?.Dispose();
                 }
             }
diff --git a/LB_VisionProcesses/BarcodeReaders/Huayray/HRBarcodeReader.cs b/LB_VisionProcesses/BarcodeReaders/Huayray/HRBarcodeReader.cs
index 872c066..aa9be07 100644
--- a/LB_VisionProcesses/BarcodeReaders/Huayray/HRBarcodeReader.cs
+++ b/LB_VisionProcesses/BarcodeReaders/Huayray/HRBarcodeReader.cs
@@ -59,15 +59,39 @@
 
             try
             {
+                // 鍏堣繘琛屼竴娆℃灇涓撅紝纭繚 SDK 鑳藉鍙戠幇璁惧锛堥儴鍒� SDK 瑕佹眰鍦ㄦ墦寮�鍓嶅繀椤绘墽琛屾灇涓撅級
+                GetDeviceList();
+
+                // 濡傛灉涔嬪墠澶辫触杩囷紝閲嶆柊鍒涘缓鐩告満瀵硅薄纭繚骞插噣鐘舵��
+                if (_camera == null)
+                {
+                    _camera = new EidCamera();
+                }
+
+                // 纭繚涔嬪墠鐨勫彞鏌勫凡閲婃斁
+                try { _camera.eidReleaseHandle_Net(); } catch { }
+
                 // 鍒涘缓鍙ユ焺
                 int nRet = _camera.eidCreateDevice_Net(sn, EidCamera.EidDeviceDataType.eidDeviceDataTypeSN);
-                if (nRet != EidCamera.eidErrorOK) return false;
+                if (nRet != EidCamera.eidErrorOK)
+                {
+                    _camera = null;
+                    return false;
+                }
+
+                // 鍒嗛厤鍥哄畾鍙ユ焺缁欏鎵橈紝闃叉琚� GC 鍥炴敹
+                if (!_callbackHandle.IsAllocated)
+                {
+                    _callbackHandle = GCHandle.Alloc(_frameCallback);
+                }
 
                 // 鎵撳紑璁惧
                 nRet = _camera.eidOpenDevice_Net();
                 if (nRet != EidCamera.eidErrorOK)
                 {
                     _camera.eidReleaseHandle_Net();
+                    if (_callbackHandle.IsAllocated) _callbackHandle.Free();
+                    _camera = null;
                     return false;
                 }
 
@@ -77,6 +101,8 @@
                 {
                     _camera.eidCloseDevice_Net();
                     _camera.eidReleaseHandle_Net();
+                    if (_callbackHandle.IsAllocated) _callbackHandle.Free();
+                    _camera = null;
                     return false;
                 }
 
@@ -86,21 +112,39 @@
             }
             catch
             {
+                // 鍙戠敓寮傚父鏃剁‘淇濋噴鏀捐祫婧�
+                try { _camera?.eidCloseDevice_Net(); } catch { }
+                try { _camera?.eidReleaseHandle_Net(); } catch { }
+                if (_callbackHandle.IsAllocated) _callbackHandle.Free();
+                // 鍙戠敓寮傚父鏃堕噴鏀剧浉鏈哄璞★紝纭繚涓嬫鍒涘缓鏂板疄渚�
+                _camera = null;
                 return false;
             }
         }
 
         public override bool Close()
         {
-            if (!IsConnected) return true;
-
             try
             {
-                StopGrabbing();
-                _camera.eidCloseDevice_Net();
-                _camera.eidReleaseHandle_Net();
+                if (IsConnected)
+                {
+                    StopGrabbing();
+                    _camera?.eidCloseDevice_Net();
+                }
+                // 鏃犺鏄惁杩炴帴锛岄兘灏濊瘯閲婃斁鍙ユ焺
+                _camera?.eidReleaseHandle_Net();
+
+                // 閲婃斁鍥炶皟鍙ユ焺
+                if (_callbackHandle.IsAllocated)
+                {
+                    _callbackHandle.Free();
+                }
+
+                // 閲婃斁鐩告満瀵硅薄寮曠敤锛岀‘淇漇DK璧勬簮瀹屽叏閲婃斁
+                _camera = null;
+
                 this.IsConnected = false;
-                this.SN = string.Empty;
+                this.IsGrabbing = false;
                 return true;
             }
             catch
@@ -166,7 +210,7 @@
         {
             try
             {
-                List<string> barcodes = new List<string>();
+                List<BarcodeInfo> barcodeInfos = new List<BarcodeInfo>();
                 // 瑙f瀽鏉$爜
                 for (int i = 0; i < frameInfo.codeNum; i++)
                 {
@@ -177,16 +221,25 @@
                     string data = Marshal.PtrToStringAnsi(codeInfo.data);
                     if (!string.IsNullOrEmpty(data))
                     {
-                        barcodes.Add(data);
+                        BarcodeInfo info = new BarcodeInfo
+                        {
+                            Text = data,
+                            Points = new Point[]
+                            {
+                                new Point((int)codeInfo.position[0].x, (int)codeInfo.position[0].y),
+                                new Point((int)codeInfo.position[1].x, (int)codeInfo.position[1].y),
+                                new Point((int)codeInfo.position[2].x, (int)codeInfo.position[2].y),
+                                new Point((int)codeInfo.position[3].x, (int)codeInfo.position[3].y)
+                            }
+                        };
+                        barcodeInfos.Add(info);
                     }
                 }
 
-                // 杞崲鍥惧儚 (濡傛灉闇�瑕�)
+                // 杞崲鍥惧儚
                 Bitmap bitmap = null;
                 if (frameInfo.imageDataLen > 0 && frameInfo.imageData != IntPtr.Zero)
                 {
-                    // 杩欓噷绠�鍖栧鐞嗭紝濡傛灉鏄疛peg鍒欑洿鎺ヤ粠鍐呭瓨鍔犺浇锛屽鏋滄槸Raw鍒欓渶杞崲
-                    // 瀹為檯椤圭洰涓彲鏍规嵁 frameInfo.format 杩涜澶勭悊
                     if (frameInfo.isJpeg)
                     {
                         byte[] managedArray = new byte[frameInfo.imageDataLen];
@@ -199,7 +252,7 @@
                 }
 
                 // 瑙﹀彂浜嬩欢
-                OnBarcodeRead(new BarcodeEventArgs(this.SN, barcodes, bitmap));
+                OnBarcodeRead(new BarcodeEventArgs(this.SN, barcodeInfos, bitmap));
             }
             catch (Exception ex)
             {
diff --git a/LB_VisionProcesses/BarcodeReaders/IBarcodeReader.cs b/LB_VisionProcesses/BarcodeReaders/IBarcodeReader.cs
index e9875c6..53157ae 100644
--- a/LB_VisionProcesses/BarcodeReaders/IBarcodeReader.cs
+++ b/LB_VisionProcesses/BarcodeReaders/IBarcodeReader.cs
@@ -14,6 +14,18 @@
     }
 
     /// <summary>
+    /// 鏉$爜璇︾粏淇℃伅
+    /// </summary>
+    public class BarcodeInfo
+    {
+        public string Text { get; set; }
+        /// <summary>
+        /// 鏉$爜鐨勫洓涓《鐐瑰潗鏍�
+        /// </summary>
+        public Point[] Points { get; set; }
+    }
+
+    /// <summary>
     /// 璇荤爜缁撴灉鍙傛暟绫�
     /// </summary>
     public class BarcodeEventArgs : EventArgs
@@ -24,9 +36,14 @@
         public string SN { get; set; }
 
         /// <summary>
-        /// 璇荤爜缁撴灉鍐呭
+        /// 鏉$爜璇︾粏淇℃伅鍒楄〃
         /// </summary>
-        public List<string> Barcodes { get; set; } = new List<string>();
+        public List<BarcodeInfo> BarcodeInfos { get; set; } = new List<BarcodeInfo>();
+
+        /// <summary>
+        /// 浠呰幏鍙栨潯鐮佹枃鏈垪琛� (淇濇寔鍏煎鎬�)
+        /// </summary>
+        public List<string> Barcodes => BarcodeInfos.Select(x => x.Text).ToList();
 
         /// <summary>
         /// 鍏宠仈鍥惧儚 (鍙��)
@@ -36,12 +53,12 @@
         /// <summary>
         /// 鏄惁璇诲彇鎴愬姛
         /// </summary>
-        public bool IsSuccess => Barcodes.Count > 0;
+        public bool IsSuccess => BarcodeInfos.Count > 0;
 
-        public BarcodeEventArgs(string sn, List<string> barcodes, Bitmap image = null)
+        public BarcodeEventArgs(string sn, List<BarcodeInfo> barcodeInfos, Bitmap image = null)
         {
             SN = sn;
-            Barcodes = barcodes;
+            BarcodeInfos = barcodeInfos;
             Image = image;
         }
     }

--
Gitblit v1.9.3