华睿读码器集成完成,使用抽象接口-基类-各品牌子类的架构,实现可插拔设计,遵循开闭原则,方便后续集成其他品牌读码器
已添加6个文件
已修改6个文件
1450 ■■■■■ 文件已修改
LB_SmartVision/Forms/Pages/BarcodeReaderPage/BarcodeReaderForm.Designer.cs 258 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_SmartVision/Forms/Pages/BarcodeReaderPage/BarcodeReaderForm.cs 207 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_SmartVision/Forms/Pages/BarcodeReaderPage/BarcodeReadersEditPage.Designer.cs 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_SmartVision/Forms/Pages/BarcodeReaderPage/BarcodeReadersEditPage.cs 226 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_SmartVision/Forms/Pages/BarcodeReaderPage/CreateBarcodeReaderForm.Designer.cs 178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_SmartVision/Forms/Pages/BarcodeReaderPage/CreateBarcodeReaderForm.cs 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_SmartVision/GlobalVar.cs 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_SmartVision/VisionForm.cs 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_VisionProcesses/BarcodeReaders/BarcodeReaderBase.cs 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_VisionProcesses/BarcodeReaders/BarcodeReaderForm.cs 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_VisionProcesses/BarcodeReaders/Huayray/HRBarcodeReader.cs 77 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_VisionProcesses/BarcodeReaders/IBarcodeReader.cs 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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;
    }
}
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;
        }
    }
}
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;
    }
}
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)
        {
            //清除用Clear方法
            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();
                    // æ·»åŠ çŸ­æš‚å»¶è¿Ÿï¼Œç¡®ä¿SDK底层资源完全释放
                    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();
            }
        }
    }
}
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;
    }
}
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);
        }
    }
}
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>();
LB_SmartVision/VisionForm.cs
@@ -1,6 +1,7 @@
using 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;
            //最开始就清空所有Tab页
@@ -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)
        {
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 { }
        }
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();
                }
            }
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
            {
                if (IsConnected)
                {
                StopGrabbing();
                _camera.eidCloseDevice_Net();
                _camera.eidReleaseHandle_Net();
                    _camera?.eidCloseDevice_Net();
                }
                // æ— è®ºæ˜¯å¦è¿žæŽ¥ï¼Œéƒ½å°è¯•释放句柄
                _camera?.eidReleaseHandle_Net();
                // é‡Šæ”¾å›žè°ƒå¥æŸ„
                if (_callbackHandle.IsAllocated)
                {
                    _callbackHandle.Free();
                }
                // é‡Šæ”¾ç›¸æœºå¯¹è±¡å¼•用,确保SDK资源完全释放
                _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>();
                // è§£æžæ¡ç 
                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)
                {
                    // è¿™é‡Œç®€åŒ–处理,如果是Jpeg则直接从内存加载,如果是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)
            {
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;
        }
    }