C3031
2026-01-16 28ddc75eadee6c73da2b955e320132fdbecc88de
修改关闭按钮位置
已修改15个文件
1887 ■■■■ 文件已修改
LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.Designer.cs 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.cs 87 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorsEditPage.cs 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_SmartVision/Forms/Pages/MotionControlPage/MotionControlForm.Designer.cs 653 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_SmartVision/Forms/Pages/MotionControlPage/MotionControlForm.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_SmartVision/Forms/Pages/MotionControlPage/MotionControlForm.resx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_SmartVision/VisionForm.Designer.cs 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_SmartVision/VisionForm.cs 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_VisionProcesses/Cameras/HRCameras/HRCamera.cs 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_VisionProcesses/Cameras/LBCameras/LBCamera.cs 149 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_VisionProcesses/Communicators/CommunicatorConfig.cs 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_VisionProcesses/Communicators/CommunicatorForm.Designer.cs 198 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_VisionProcesses/Communicators/CommunicatorForm.cs 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_VisionProcesses/Communicators/CommunicatorForm.resx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_VisionProcesses/Communicators/SiemensS7/SiemensLBS7.cs 358 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.Designer.cs
@@ -44,6 +44,8 @@
            lblType = new Label();
            lblAddress = new Label();
            lblIP = new Label();
            cmbDataType = new ComboBox();
            lblDataType = new Label();
            tableLayoutPanel2 = new TableLayoutPanel();
            btnRuleSend = new Button();
            btnSend = new Button();
@@ -63,9 +65,10 @@
            label3.AutoSize = true;
            label3.Dock = DockStyle.Fill;
            label3.ForeColor = Color.CornflowerBlue;
            label3.Location = new Point(3, 100);
            label3.Location = new Point(4, 125);
            label3.Margin = new Padding(4, 0, 4, 0);
            label3.Name = "label3";
            label3.Size = new Size(655, 20);
            label3.Size = new Size(819, 25);
            label3.TabIndex = 18;
            label3.Text = "发送信息";
            label3.TextAlign = ContentAlignment.BottomLeft;
@@ -81,14 +84,15 @@
            tableLayoutPanel1.Controls.Add(label3, 0, 1);
            tableLayoutPanel1.Dock = DockStyle.Fill;
            tableLayoutPanel1.Location = new Point(0, 0);
            tableLayoutPanel1.Margin = new Padding(4, 4, 4, 4);
            tableLayoutPanel1.Name = "tableLayoutPanel1";
            tableLayoutPanel1.RowCount = 5;
            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 100F));
            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));
            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 40F));
            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 125F));
            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 25F));
            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 38F));
            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F));
            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
            tableLayoutPanel1.Size = new Size(661, 322);
            tableLayoutPanel1.Size = new Size(827, 402);
            tableLayoutPanel1.TabIndex = 26;
            // 
            // grpReceive
@@ -96,9 +100,11 @@
            grpReceive.Controls.Add(txtReceiveMsg);
            grpReceive.Dock = DockStyle.Fill;
            grpReceive.ForeColor = Color.CornflowerBlue;
            grpReceive.Location = new Point(3, 193);
            grpReceive.Location = new Point(4, 242);
            grpReceive.Margin = new Padding(4, 4, 4, 4);
            grpReceive.Name = "grpReceive";
            grpReceive.Size = new Size(655, 126);
            grpReceive.Padding = new Padding(4, 4, 4, 4);
            grpReceive.Size = new Size(819, 156);
            grpReceive.TabIndex = 30;
            grpReceive.TabStop = false;
            grpReceive.Text = "通讯记录";
@@ -106,20 +112,22 @@
            // txtReceiveMsg
            // 
            txtReceiveMsg.Dock = DockStyle.Fill;
            txtReceiveMsg.Location = new Point(3, 17);
            txtReceiveMsg.Location = new Point(4, 21);
            txtReceiveMsg.Margin = new Padding(4, 4, 4, 4);
            txtReceiveMsg.Multiline = true;
            txtReceiveMsg.Name = "txtReceiveMsg";
            txtReceiveMsg.ReadOnly = true;
            txtReceiveMsg.ScrollBars = ScrollBars.Both;
            txtReceiveMsg.Size = new Size(649, 106);
            txtReceiveMsg.Size = new Size(811, 131);
            txtReceiveMsg.TabIndex = 0;
            // 
            // txtSendMsg
            // 
            txtSendMsg.Dock = DockStyle.Fill;
            txtSendMsg.Location = new Point(3, 123);
            txtSendMsg.Location = new Point(4, 154);
            txtSendMsg.Margin = new Padding(4, 4, 4, 4);
            txtSendMsg.Name = "txtSendMsg";
            txtSendMsg.Size = new Size(655, 21);
            txtSendMsg.Size = new Size(819, 24);
            txtSendMsg.TabIndex = 29;
            // 
            // grpSetting
@@ -134,21 +142,26 @@
            grpSetting.Controls.Add(lblType);
            grpSetting.Controls.Add(lblAddress);
            grpSetting.Controls.Add(lblIP);
            grpSetting.Controls.Add(cmbDataType);
            grpSetting.Controls.Add(lblDataType);
            grpSetting.Dock = DockStyle.Fill;
            grpSetting.ForeColor = Color.CornflowerBlue;
            grpSetting.Location = new Point(3, 3);
            grpSetting.MinimumSize = new Size(261, 61);
            grpSetting.Location = new Point(4, 4);
            grpSetting.Margin = new Padding(4, 4, 4, 4);
            grpSetting.MinimumSize = new Size(326, 76);
            grpSetting.Name = "grpSetting";
            grpSetting.Size = new Size(655, 94);
            grpSetting.Padding = new Padding(4, 4, 4, 4);
            grpSetting.Size = new Size(819, 117);
            grpSetting.TabIndex = 28;
            grpSetting.TabStop = false;
            grpSetting.Text = "通讯配置";
            // 
            // txtAddress
            // 
            txtAddress.Location = new Point(251, 60);
            txtAddress.Location = new Point(314, 75);
            txtAddress.Margin = new Padding(4, 4, 4, 4);
            txtAddress.Name = "txtAddress";
            txtAddress.Size = new Size(100, 21);
            txtAddress.Size = new Size(124, 24);
            txtAddress.TabIndex = 9;
            txtAddress.TextChanged += txtAddress_TextChanged;
            // 
@@ -156,92 +169,123 @@
            // 
            cmbType.DropDownStyle = ComboBoxStyle.DropDownList;
            cmbType.FormattingEnabled = true;
            cmbType.Location = new Point(251, 23);
            cmbType.Location = new Point(314, 29);
            cmbType.Margin = new Padding(4, 4, 4, 4);
            cmbType.Name = "cmbType";
            cmbType.Size = new Size(100, 23);
            cmbType.Size = new Size(124, 26);
            cmbType.TabIndex = 8;
            // 
            // txtIP
            // 
            txtIP.Location = new Point(79, 22);
            txtIP.Location = new Point(99, 28);
            txtIP.Margin = new Padding(4, 4, 4, 4);
            txtIP.Name = "txtIP";
            txtIP.Size = new Size(100, 21);
            txtIP.Size = new Size(124, 24);
            txtIP.TabIndex = 7;
            // 
            // txtPort
            // 
            txtPort.Location = new Point(79, 60);
            txtPort.Location = new Point(99, 75);
            txtPort.Margin = new Padding(4, 4, 4, 4);
            txtPort.Name = "txtPort";
            txtPort.Size = new Size(100, 21);
            txtPort.Size = new Size(124, 24);
            txtPort.TabIndex = 6;
            // 
            // lblPort
            // 
            lblPort.AutoSize = true;
            lblPort.Location = new Point(13, 63);
            lblPort.Location = new Point(16, 79);
            lblPort.Margin = new Padding(4, 0, 4, 0);
            lblPort.Name = "lblPort";
            lblPort.Size = new Size(31, 15);
            lblPort.Size = new Size(38, 18);
            lblPort.TabIndex = 4;
            lblPort.Text = "端口";
            // 
            // cmbIP
            // 
            cmbIP.FormattingEnabled = true;
            cmbIP.Location = new Point(79, 21);
            cmbIP.Location = new Point(99, 26);
            cmbIP.Margin = new Padding(4, 4, 4, 4);
            cmbIP.Name = "cmbIP";
            cmbIP.Size = new Size(100, 23);
            cmbIP.Size = new Size(124, 26);
            cmbIP.TabIndex = 1;
            // 
            // lblType
            // 
            lblType.AutoSize = true;
            lblType.Location = new Point(205, 26);
            lblType.Location = new Point(256, 32);
            lblType.Margin = new Padding(4, 0, 4, 0);
            lblType.Name = "lblType";
            lblType.Size = new Size(31, 15);
            lblType.Size = new Size(38, 18);
            lblType.TabIndex = 0;
            lblType.Text = "型号";
            // 
            // lblAddress
            // 
            lblAddress.AutoSize = true;
            lblAddress.Location = new Point(205, 63);
            lblAddress.Location = new Point(256, 79);
            lblAddress.Margin = new Padding(4, 0, 4, 0);
            lblAddress.Name = "lblAddress";
            lblAddress.Size = new Size(31, 15);
            lblAddress.Size = new Size(38, 18);
            lblAddress.TabIndex = 0;
            lblAddress.Text = "地址";
            lblAddress.Text = "变量地址";
            // 
            // lblIP
            // 
            lblIP.AutoSize = true;
            lblIP.Location = new Point(13, 26);
            lblIP.Location = new Point(16, 32);
            lblIP.Margin = new Padding(4, 0, 4, 0);
            lblIP.Name = "lblIP";
            lblIP.Size = new Size(31, 15);
            lblIP.Size = new Size(38, 18);
            lblIP.TabIndex = 0;
            lblIP.Text = "地址";
            //
            // cmbDataType
            //
            cmbDataType.DropDownStyle = ComboBoxStyle.DropDownList;
            cmbDataType.FormattingEnabled = true;
            cmbDataType.Location = new Point(525, 75);
            cmbDataType.Margin = new Padding(4, 4, 4, 4);
            cmbDataType.Name = "cmbDataType";
            cmbDataType.Size = new Size(124, 26);
            cmbDataType.TabIndex = 11;
            cmbDataType.SelectedIndexChanged += cmbDataType_SelectedIndexChanged;
            //
            // lblDataType
            //
            lblDataType.AutoSize = true;
            lblDataType.Location = new Point(462, 79);
            lblDataType.Margin = new Padding(4, 0, 4, 0);
            lblDataType.Name = "lblDataType";
            lblDataType.Size = new Size(38, 18);
            lblDataType.TabIndex = 10;
            lblDataType.Text = "类型";
            // 
            // tableLayoutPanel2
            // 
            tableLayoutPanel2.ColumnCount = 3;
            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 80F));
            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 80F));
            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
            tableLayoutPanel2.Controls.Add(btnRuleSend, 1, 0);
            tableLayoutPanel2.Controls.Add(btnSend, 0, 0);
            tableLayoutPanel2.Dock = DockStyle.Fill;
            tableLayoutPanel2.Location = new Point(3, 153);
            tableLayoutPanel2.Location = new Point(4, 192);
            tableLayoutPanel2.Margin = new Padding(4, 4, 4, 4);
            tableLayoutPanel2.Name = "tableLayoutPanel2";
            tableLayoutPanel2.RowCount = 1;
            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
            tableLayoutPanel2.Size = new Size(655, 34);
            tableLayoutPanel2.Size = new Size(819, 42);
            tableLayoutPanel2.TabIndex = 27;
            // 
            // btnRuleSend
            // 
            btnRuleSend.Dock = DockStyle.Fill;
            btnRuleSend.ForeColor = Color.CornflowerBlue;
            btnRuleSend.Location = new Point(83, 3);
            btnRuleSend.Location = new Point(104, 4);
            btnRuleSend.Margin = new Padding(4, 4, 4, 4);
            btnRuleSend.Name = "btnRuleSend";
            btnRuleSend.Size = new Size(74, 28);
            btnRuleSend.Size = new Size(92, 34);
            btnRuleSend.TabIndex = 14;
            btnRuleSend.Text = "校验发送";
            btnRuleSend.UseVisualStyleBackColor = true;
@@ -251,9 +295,10 @@
            // 
            btnSend.Dock = DockStyle.Fill;
            btnSend.ForeColor = Color.CornflowerBlue;
            btnSend.Location = new Point(3, 3);
            btnSend.Location = new Point(4, 4);
            btnSend.Margin = new Padding(4, 4, 4, 4);
            btnSend.Name = "btnSend";
            btnSend.Size = new Size(74, 28);
            btnSend.Size = new Size(92, 34);
            btnSend.TabIndex = 12;
            btnSend.Text = "发送";
            btnSend.UseVisualStyleBackColor = true;
@@ -268,11 +313,12 @@
            themeForm_Communicator.Font = new Font("Microsoft Sans Serif", 9F);
            themeForm_Communicator.Image = (Image)resources.GetObject("themeForm_Communicator.Image");
            themeForm_Communicator.Location = new Point(0, 0);
            themeForm_Communicator.Margin = new Padding(4, 4, 4, 4);
            themeForm_Communicator.Name = "themeForm_Communicator";
            themeForm_Communicator.Padding = new Padding(10, 70, 10, 9);
            themeForm_Communicator.Padding = new Padding(12, 88, 12, 11);
            themeForm_Communicator.RoundCorners = true;
            themeForm_Communicator.Sizable = true;
            themeForm_Communicator.Size = new Size(681, 401);
            themeForm_Communicator.Size = new Size(851, 501);
            themeForm_Communicator.SmartBounds = true;
            themeForm_Communicator.StartPosition = FormStartPosition.WindowsDefaultLocation;
            themeForm_Communicator.TabIndex = 27;
@@ -288,7 +334,8 @@
            controlBox1.EnableMaximizeButton = true;
            controlBox1.EnableMinimizeButton = true;
            controlBox1.ForeColor = Color.FromArgb(155, 155, 155);
            controlBox1.Location = new Point(581, 18);
            controlBox1.Location = new Point(726, 22);
            controlBox1.Margin = new Padding(4, 4, 4, 4);
            controlBox1.MaximizeHoverColor = Color.FromArgb(74, 74, 74);
            controlBox1.MinimizeHoverColor = Color.FromArgb(63, 63, 65);
            controlBox1.Name = "controlBox1";
@@ -300,19 +347,21 @@
            // 
            panel_CommunicatorForm.Controls.Add(tableLayoutPanel1);
            panel_CommunicatorForm.Dock = DockStyle.Fill;
            panel_CommunicatorForm.Location = new Point(10, 70);
            panel_CommunicatorForm.Location = new Point(12, 88);
            panel_CommunicatorForm.Margin = new Padding(4, 4, 4, 4);
            panel_CommunicatorForm.Name = "panel_CommunicatorForm";
            panel_CommunicatorForm.Size = new Size(661, 322);
            panel_CommunicatorForm.Size = new Size(827, 402);
            panel_CommunicatorForm.TabIndex = 27;
            // 
            // CommunicatorForm
            // 
            AutoScaleDimensions = new SizeF(96F, 96F);
            AutoScaleDimensions = new SizeF(120F, 120F);
            AutoScaleMode = AutoScaleMode.Dpi;
            ClientSize = new Size(681, 401);
            ClientSize = new Size(851, 501);
            Controls.Add(themeForm_Communicator);
            FormBorderStyle = FormBorderStyle.None;
            MinimumSize = new Size(261, 61);
            Margin = new Padding(4, 4, 4, 4);
            MinimumSize = new Size(326, 76);
            Name = "CommunicatorForm";
            Text = "通讯设置";
            TransparencyKey = Color.Fuchsia;
@@ -351,5 +400,7 @@
        private ComboBox cmbType;
        private Label lblAddress;
        private TextBox txtAddress;
        private Label lblDataType;
        private ComboBox cmbDataType;
    }
}
LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.cs
@@ -28,7 +28,6 @@
        {
            InitializeComponent();
            cmbType.Items.Clear();
            if (communicator != null && !string.IsNullOrEmpty(communicator.CommunicatorConnections["型号"]?.ToString()))
            {
                cmbType.Items.Add(communicator.CommunicatorConnections["型号"]?.ToString());
@@ -39,41 +38,44 @@
        {
            InitializeComponent();
            if (communicator == null)
            {
                return;
            }
            cmbIP.Enabled = false;
            txtIP.Enabled = false;
            txtPort.Enabled = false;
            cmbDataType.Enabled = false;
            lblType.Visible = false;
            lblAddress.Visible = false;
            cmbType.Visible = false;
            txtAddress.Visible = false;
            lblDataType.Visible = false;
            cmbDataType.Visible = false;
            this.Text = name;
            if (communicator is UARTPort)
            {
                //统计可用端口
                SerialPortStream temp = new SerialPortStream();
                string[] ArryPort = temp.GetPortNames();
                for (int i = 0; i < ArryPort.Length; i++)
                {
                    cmbIP.Items.Add(ArryPort[i]);
                }
                cmbIP.Text = communicator.CommunicatorConnections["地址"]?.ToString();
                txtPort.Text = communicator.CommunicatorConnections["端口"]?.ToString();
                txtIP.Visible = false;
                cmbIP.Visible = true;
                this.btnRuleSend.Visible = true;
                lblType.Visible = false;
                lblAddress.Visible = false;
                cmbType.Visible = false;
                txtAddress.Visible = false;
                lblDataType.Visible = false;
                cmbDataType.Visible = false;
                lblIP.Text = "COM口";
                lblPort.Text = "波特率";
@@ -81,17 +83,16 @@
            else if (communicator is TCPClient || communicator is TCPServer)
            {
                txtIP.Text = communicator.CommunicatorConnections["地址"]?.ToString();
                txtPort.SelectedText = communicator.CommunicatorConnections["端口"]?.ToString();
                txtPort.Text = communicator.CommunicatorConnections["端口"]?.ToString();
                txtIP.Visible = true;
                cmbIP.Visible = false;
                this.btnRuleSend.Visible = false;
                lblType.Visible = false;
                lblAddress.Visible = false;
                cmbType.Visible = false;
                txtAddress.Visible = false;
                lblDataType.Visible = false;
                cmbDataType.Visible = false;
                lblIP.Text = "地址";
                lblPort.Text = "端口";
@@ -101,7 +102,6 @@
                txtIP.Text = communicator.CommunicatorConnections["地址"]?.ToString();
                txtPort.Text = communicator.CommunicatorConnections["端口"]?.ToString();
                cmbType.Items.Clear();
                if (!string.IsNullOrEmpty(communicator.CommunicatorConnections["型号"]?.ToString()))
                {
                    cmbType.Items.Add(communicator.CommunicatorConnections["型号"]?.ToString());
@@ -111,14 +111,25 @@
                {
                    txtAddress.Text = communicator.CommunicatorConnections["变量地址"]?.ToString();
                }
                // 初始化数据类型
                cmbDataType.Items.Clear();
                cmbDataType.Items.AddRange(new string[] { "String", "Bool", "Byte", "Int", "DInt", "Real", "Double", "Word", "DWord" });
                if (communicator.CommunicatorConnections.Contains("数据类型"))
                    cmbDataType.Text = communicator.CommunicatorConnections["数据类型"].ToString();
                else
                    cmbDataType.Text = "String";
                txtIP.Visible = true;
                cmbIP.Visible = false;
                this.btnRuleSend.Visible = false;
                lblType.Visible = true;
                lblAddress.Visible = true;
                cmbType.Visible = true;
                txtAddress.Visible = true;
                lblDataType.Visible = true;
                cmbDataType.Visible = true;
                cmbDataType.Enabled = true; // 启用数据类型选择
                lblIP.Text = "IP";
                lblPort.Text = "槽";
@@ -127,6 +138,15 @@
            this.communicator = communicator;
            //加载回调函数
            Subscribe();
        }
        private void cmbDataType_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (communicator != null)
            {
                communicator.CommunicatorConnections.Add("数据类型", cmbDataType.Text);
                communicatorChanged(communicator);
            }
        }
        private void CommunicatorForm_FormClosing(object sender, FormClosingEventArgs e) => Unsubscribe();
@@ -228,6 +248,24 @@
            }
        }
        private void ShowLogMsg(string msg)
        {
            // 如果当前不是 UI 线程,则通过 Invoke 将操作调度到 UI 线程
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<string>((message) =>
                {
                    this.txtReceiveMsg.AppendText("[" + DateTime.Now.ToString("HH:mm:ss.fff") + "] " + message + "\r\n");
                    this.txtReceiveMsg.ScrollToCaret();
                }), msg);
            }
            else
            {
                this.txtReceiveMsg.AppendText("[" + DateTime.Now.ToString("HH:mm:ss.fff") + "] " + msg + "\r\n");
                this.txtReceiveMsg.ScrollToCaret();
            }
        }
        private void btnSend_Click(object sender, EventArgs e)
        {
            if (communicator == null)
@@ -235,6 +273,8 @@
            if (communicator.SendMessage(txtSendMsg.Text))
                ShowSendMsg(txtSendMsg.Text);
            else
                ShowLogMsg(communicator.Msg);
        }
        private void btnRuleSend_Click(object sender, EventArgs e)
@@ -253,19 +293,30 @@
            if (communicator.SendMessage(SendMsg))
                ShowSendMsg(SendMsg);
            else
                ShowLogMsg(communicator.Msg);
        }
        private void txtAddress_TextChanged(object sender, EventArgs e)
        {
            if (communicator != null && !communicator.CommunicatorConnections.Contains("变量地址"))
            if (communicator != null)
            {
                communicator.CommunicatorConnections.Add("变量地址", txtAddress.Text);
            }
            else if (communicator != null)
            {
                communicator.CommunicatorConnections["变量地址"] = txtAddress.Text;
                communicatorChanged(communicator);
            }
        }
        private void cmbVarType_SelectedIndexChanged(object sender, EventArgs e)
        {
            //if (communicator != null && !communicator.CommunicatorConnections.Contains("变量类型"))
            //{
            //    communicator.CommunicatorConnections.Add("变量类型", cmbVarType.Text);
            //}
            //else if (communicator != null)
            //{
            //    communicator.CommunicatorConnections["变量类型"] = cmbVarType.Text;
            //    communicatorChanged(communicator);
            //}
        }
    }
}
LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorsEditPage.cs
@@ -34,7 +34,9 @@
                if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(PORT))
                    return;
                string CommunicatorConnectionString = $"({ClassName}){IP}:{PORT}";
                string DataType = item.Value.CommunicatorConnections.Contains("数据类型") ?
                    item.Value.CommunicatorConnections["数据类型"].ToString() : "String";
                string CommunicatorConnectionString = $"({ClassName}){IP}:{PORT} [{DataType}]";
                UserItem flow = new UserItem(new string[] { "测试", "刷新", "移除", "重命名" });
                //flow.SetDPIScale();
@@ -69,7 +71,9 @@
                if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(PORT))
                    return;
                string CommunicatorConnectionString = $"({ClassName}){IP}:{PORT}";
                string DataType = communicator.CommunicatorConnections.Contains("数据类型") ?
                    communicator.CommunicatorConnections["数据类型"].ToString() : "String";
                string CommunicatorConnectionString = $"({ClassName}){IP}:{PORT} [{DataType}]";
                GlobalVar.dicCommunicators.TryAdd(Name, communicator);
                communicator.CommunicatorName = Name;
@@ -135,7 +139,27 @@
        private void CommunicatorFForm_CommunicatorChanged(BaseCommunicator communicator)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<BaseCommunicator>(CommunicatorFForm_CommunicatorChanged), communicator);
                return;
            }
            for (int i = 0; i < uiFlowLayoutPanel1.Controls.Count; i++)
            {
                if (uiFlowLayoutPanel1.Controls[i] is UserItem flow && flow.Name == communicator.CommunicatorName)
                {
                    string ClassName = communicator.GetType().Name;
                    string IP = communicator.CommunicatorConnections["地址"].ToString();
                    string PORT = communicator.CommunicatorConnections["端口"].ToString();
                    string DataType = communicator.CommunicatorConnections.Contains("数据类型") ?
                        communicator.CommunicatorConnections["数据类型"].ToString() : "String";
                    flow.Text = $"({ClassName}){IP}:{PORT} [{DataType}]";
                    flow.Refresh();
                    break;
                }
            }
        }
        // 移除通讯口
LB_SmartVision/Forms/Pages/MotionControlPage/MotionControlForm.Designer.cs
@@ -63,15 +63,44 @@
            groupBoxXPosition = new GroupBox();
            textBoxXPosition = new TextBox();
            tableLayoutPanel1 = new TableLayoutPanel();
            textBox1 = new TextBox();
            textBoxSN = new TextBox();
            uiMarkLabelSN = new Label();
            tableLayoutPanel7 = new TableLayoutPanel();
            textBox2 = new TextBox();
            textBoxName = new TextBox();
            uiMarkLabelName = new Label();
            uiGroupBoxImage = new GroupBox();
            uiSplitContainer1 = new SplitContainer();
            themeForm1 = new ReaLTaiizor.Forms.ThemeForm();
            controlBox1 = new ReaLTaiizor.Controls.ControlBox();
            panel1 = new Panel();
            groupBoxXVarAddress = new GroupBox();
            textBoxXVarAddress = new TextBox();
            groupBoxYVarAddress = new GroupBox();
            textBoxYVarAddress = new TextBox();
            groupBoxZVarAddress = new GroupBox();
            textBoxZVarAddress = new TextBox();
            groupBoxWVarAddress = new GroupBox();
            textBoxWVarAddress = new TextBox();
            groupBoxXDetectLocation = new GroupBox();
            textBoxXDetectLocation = new TextBox();
            groupBoxYDetectLocation = new GroupBox();
            textBoxYDetectLocation = new TextBox();
            groupBoxZDetectLocation = new GroupBox();
            textBoxZDetectLocation = new TextBox();
            groupBoxWDetectLocation = new GroupBox();
            textBoxWDetectLocation = new TextBox();
            groupBoxXOriginalLocation = new GroupBox();
            textBoxXOriginalLocation = new TextBox();
            groupBoxYOriginalLocation = new GroupBox();
            textBoxYOriginalLocation = new TextBox();
            groupBoxZOriginalLocation = new GroupBox();
            textBoxZOriginalLocation = new TextBox();
            groupBoxWOriginalLocation = new GroupBox();
            textBoxWOriginalLocation = new TextBox();
            groupBoxPulseMotionSpeedAddress = new GroupBox();
            textBoxPulseMotionSpeedAddress = new TextBox();
            groupBoxAngularVelocityAddress = new GroupBox();
            textBoxAngularVelocityAddress = new TextBox();
            uiGroupBoxMotionControl.SuspendLayout();
            tableLayoutPanel3.SuspendLayout();
            tableLayoutPanel6.SuspendLayout();
@@ -89,19 +118,35 @@
            uiSplitContainer1.Panel2.SuspendLayout();
            uiSplitContainer1.SuspendLayout();
            themeForm1.SuspendLayout();
            panel1.SuspendLayout();
            groupBoxXVarAddress.SuspendLayout();
            groupBoxYVarAddress.SuspendLayout();
            groupBoxZVarAddress.SuspendLayout();
            groupBoxWVarAddress.SuspendLayout();
            groupBoxXDetectLocation.SuspendLayout();
            groupBoxYDetectLocation.SuspendLayout();
            groupBoxZDetectLocation.SuspendLayout();
            groupBoxWDetectLocation.SuspendLayout();
            groupBoxXOriginalLocation.SuspendLayout();
            groupBoxYOriginalLocation.SuspendLayout();
            groupBoxZOriginalLocation.SuspendLayout();
            groupBoxWOriginalLocation.SuspendLayout();
            groupBoxPulseMotionSpeedAddress.SuspendLayout();
            groupBoxAngularVelocityAddress.SuspendLayout();
            SuspendLayout();
            // 
            // uiGroupBoxMotionControl
            // 
            uiGroupBoxMotionControl.Controls.Add(tableLayoutPanel3);
            uiGroupBoxMotionControl.Controls.Add(panel1);
            uiGroupBoxMotionControl.Dock = DockStyle.Fill;
            uiGroupBoxMotionControl.Font = new Font("宋体", 12F);
            uiGroupBoxMotionControl.ForeColor = SystemColors.Control;
            uiGroupBoxMotionControl.Location = new Point(0, 0);
            uiGroupBoxMotionControl.Margin = new Padding(4, 5, 4, 5);
            uiGroupBoxMotionControl.MinimumSize = new Size(1, 1);
            uiGroupBoxMotionControl.Name = "uiGroupBoxMotionControl";
            uiGroupBoxMotionControl.Padding = new Padding(0, 32, 0, 0);
            uiGroupBoxMotionControl.Size = new Size(374, 624);
            uiGroupBoxMotionControl.Padding = new Padding(0);
            uiGroupBoxMotionControl.Size = new Size(580, 684);
            uiGroupBoxMotionControl.TabIndex = 18;
            uiGroupBoxMotionControl.TabStop = false;
            uiGroupBoxMotionControl.Text = "运动控制参数";
@@ -116,16 +161,17 @@
            tableLayoutPanel3.Controls.Add(tableLayoutPanel2, 0, 4);
            tableLayoutPanel3.Controls.Add(tableLayoutPanel1, 0, 0);
            tableLayoutPanel3.Controls.Add(tableLayoutPanel7, 0, 1);
            tableLayoutPanel3.Location = new Point(0, 55);
            tableLayoutPanel3.Dock = DockStyle.Fill;
            tableLayoutPanel3.Location = new Point(0, 3);
            tableLayoutPanel3.Name = "tableLayoutPanel3";
            tableLayoutPanel3.RowCount = 6;
            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Absolute, 45F));
            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Absolute, 45F));
            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Absolute, 45F));
            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Absolute, 45F));
            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
            tableLayoutPanel3.Size = new Size(374, 560);
            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Absolute, 188F));
            tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
            tableLayoutPanel3.Size = new Size(580, 658);
            tableLayoutPanel3.TabIndex = 0;
            tableLayoutPanel3.Paint += tableLayoutPanel3_Paint;
            // 
@@ -141,14 +187,14 @@
            tableLayoutPanel6.Name = "tableLayoutPanel6";
            tableLayoutPanel6.RowCount = 1;
            tableLayoutPanel6.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
            tableLayoutPanel6.Size = new Size(368, 39);
            tableLayoutPanel6.Size = new Size(574, 39);
            tableLayoutPanel6.TabIndex = 6;
            // 
            // uiButtonCloseSoftGrab
            // 
            uiButtonCloseSoftGrab.Anchor = AnchorStyles.None;
            uiButtonCloseSoftGrab.BackColor = Color.Black;
            uiButtonCloseSoftGrab.Location = new Point(225, 5);
            uiButtonCloseSoftGrab.Location = new Point(379, 5);
            uiButtonCloseSoftGrab.Name = "uiButtonCloseSoftGrab";
            uiButtonCloseSoftGrab.Size = new Size(102, 29);
            uiButtonCloseSoftGrab.TabIndex = 2;
@@ -159,9 +205,9 @@
            // 
            uiButtonHardGrabWithPLC.Anchor = AnchorStyles.None;
            uiButtonHardGrabWithPLC.BackColor = Color.Black;
            uiButtonHardGrabWithPLC.Location = new Point(41, 5);
            uiButtonHardGrabWithPLC.Location = new Point(92, 3);
            uiButtonHardGrabWithPLC.Name = "uiButtonHardGrabWithPLC";
            uiButtonHardGrabWithPLC.Size = new Size(102, 29);
            uiButtonHardGrabWithPLC.Size = new Size(102, 33);
            uiButtonHardGrabWithPLC.TabIndex = 1;
            uiButtonHardGrabWithPLC.Text = "模拟采集";
            uiButtonHardGrabWithPLC.UseVisualStyleBackColor = false;
@@ -177,7 +223,7 @@
            tableLayoutPanel5.Name = "tableLayoutPanel5";
            tableLayoutPanel5.RowCount = 1;
            tableLayoutPanel5.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
            tableLayoutPanel5.Size = new Size(368, 39);
            tableLayoutPanel5.Size = new Size(574, 39);
            tableLayoutPanel5.TabIndex = 5;
            // 
            // uiButtonGrabOnce
@@ -186,7 +232,7 @@
            uiButtonGrabOnce.Dock = DockStyle.Fill;
            uiButtonGrabOnce.Location = new Point(3, 3);
            uiButtonGrabOnce.Name = "uiButtonGrabOnce";
            uiButtonGrabOnce.Size = new Size(362, 33);
            uiButtonGrabOnce.Size = new Size(568, 33);
            uiButtonGrabOnce.TabIndex = 0;
            uiButtonGrabOnce.Text = "单张采集";
            uiButtonGrabOnce.UseVisualStyleBackColor = false;
@@ -194,9 +240,12 @@
            // 
            // tableLayoutPanel4
            // 
            tableLayoutPanel4.ColumnCount = 2;
            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 42.81768F));
            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 57.18232F));
            tableLayoutPanel4.ColumnCount = 4;
            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 160F));
            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 160F));
            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 120F));
            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 120F));
            tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 20F));
            tableLayoutPanel4.Controls.Add(labelPointSpeed, 0, 0);
            tableLayoutPanel4.Controls.Add(textBoxAngleNow, 1, 3);
            tableLayoutPanel4.Controls.Add(labelAngleNow, 0, 3);
@@ -205,15 +254,18 @@
            tableLayoutPanel4.Controls.Add(textBoxAngSpeed, 1, 1);
            tableLayoutPanel4.Controls.Add(labelAngSpeed, 0, 1);
            tableLayoutPanel4.Controls.Add(textBoxPointSpeed, 1, 0);
            tableLayoutPanel4.Controls.Add(groupBoxPulseMotionSpeedAddress, 2, 0);
            tableLayoutPanel4.Controls.Add(groupBoxAngularVelocityAddress, 2, 1);
            tableLayoutPanel4.Dock = DockStyle.Fill;
            tableLayoutPanel4.Location = new Point(3, 373);
            tableLayoutPanel4.Location = new Point(3, 371);
            tableLayoutPanel4.Name = "tableLayoutPanel4";
            tableLayoutPanel4.RowCount = 4;
            tableLayoutPanel4.RowCount = 5;
            tableLayoutPanel4.RowStyles.Add(new RowStyle(SizeType.Absolute, 45F));
            tableLayoutPanel4.RowStyles.Add(new RowStyle(SizeType.Absolute, 45F));
            tableLayoutPanel4.RowStyles.Add(new RowStyle(SizeType.Absolute, 45F));
            tableLayoutPanel4.RowStyles.Add(new RowStyle(SizeType.Absolute, 45F));
            tableLayoutPanel4.Size = new Size(368, 184);
            tableLayoutPanel4.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
            tableLayoutPanel4.Size = new Size(574, 284);
            tableLayoutPanel4.TabIndex = 2;
            // 
            // labelPointSpeed
@@ -223,7 +275,7 @@
            labelPointSpeed.Location = new Point(3, 5);
            labelPointSpeed.Margin = new Padding(3, 5, 3, 5);
            labelPointSpeed.Name = "labelPointSpeed";
            labelPointSpeed.Size = new Size(151, 35);
            labelPointSpeed.Size = new Size(154, 35);
            labelPointSpeed.TabIndex = 18;
            labelPointSpeed.Text = "点动速度(mm/s)";
            labelPointSpeed.TextAlign = ContentAlignment.MiddleLeft;
@@ -232,9 +284,9 @@
            // 
            textBoxAngleNow.Anchor = AnchorStyles.Left | AnchorStyles.Right;
            textBoxAngleNow.Enabled = false;
            textBoxAngleNow.Location = new Point(160, 144);
            textBoxAngleNow.Location = new Point(163, 142);
            textBoxAngleNow.Name = "textBoxAngleNow";
            textBoxAngleNow.Size = new Size(205, 30);
            textBoxAngleNow.Size = new Size(154, 30);
            textBoxAngleNow.TabIndex = 17;
            textBoxAngleNow.Text = "0";
            textBoxAngleNow.TextChanged += textBoxAngleNow_TextChanged;
@@ -246,7 +298,7 @@
            labelAngleNow.Location = new Point(3, 140);
            labelAngleNow.Margin = new Padding(3, 5, 3, 5);
            labelAngleNow.Name = "labelAngleNow";
            labelAngleNow.Size = new Size(151, 39);
            labelAngleNow.Size = new Size(154, 35);
            labelAngleNow.TabIndex = 16;
            labelAngleNow.Text = "当前角度(°)";
            labelAngleNow.TextAlign = ContentAlignment.MiddleLeft;
@@ -255,9 +307,9 @@
            // 
            textBoxPositionNow.Anchor = AnchorStyles.Left | AnchorStyles.Right;
            textBoxPositionNow.Enabled = false;
            textBoxPositionNow.Location = new Point(160, 97);
            textBoxPositionNow.Location = new Point(163, 97);
            textBoxPositionNow.Name = "textBoxPositionNow";
            textBoxPositionNow.Size = new Size(205, 30);
            textBoxPositionNow.Size = new Size(154, 30);
            textBoxPositionNow.TabIndex = 15;
            textBoxPositionNow.Text = "(0,0,0)";
            textBoxPositionNow.TextChanged += textBoxPositionNow_TextChanged;
@@ -269,7 +321,7 @@
            labelPositionNow.Location = new Point(3, 95);
            labelPositionNow.Margin = new Padding(3, 5, 3, 5);
            labelPositionNow.Name = "labelPositionNow";
            labelPositionNow.Size = new Size(151, 35);
            labelPositionNow.Size = new Size(154, 35);
            labelPositionNow.TabIndex = 14;
            labelPositionNow.Text = "当前点位(mm)";
            labelPositionNow.TextAlign = ContentAlignment.MiddleLeft;
@@ -277,9 +329,9 @@
            // textBoxAngSpeed
            // 
            textBoxAngSpeed.Anchor = AnchorStyles.Left | AnchorStyles.Right;
            textBoxAngSpeed.Location = new Point(160, 52);
            textBoxAngSpeed.Location = new Point(163, 52);
            textBoxAngSpeed.Name = "textBoxAngSpeed";
            textBoxAngSpeed.Size = new Size(205, 30);
            textBoxAngSpeed.Size = new Size(154, 30);
            textBoxAngSpeed.TabIndex = 13;
            textBoxAngSpeed.Text = "0";
            textBoxAngSpeed.TextChanged += textBoxAngSpeed_TextChanged;
@@ -293,7 +345,7 @@
            labelAngSpeed.Location = new Point(3, 50);
            labelAngSpeed.Margin = new Padding(3, 5, 3, 5);
            labelAngSpeed.Name = "labelAngSpeed";
            labelAngSpeed.Size = new Size(151, 35);
            labelAngSpeed.Size = new Size(154, 35);
            labelAngSpeed.TabIndex = 12;
            labelAngSpeed.Text = "角速度(rad/s)";
            labelAngSpeed.TextAlign = ContentAlignment.MiddleLeft;
@@ -301,9 +353,9 @@
            // textBoxPointSpeed
            // 
            textBoxPointSpeed.Anchor = AnchorStyles.Left | AnchorStyles.Right;
            textBoxPointSpeed.Location = new Point(160, 7);
            textBoxPointSpeed.Location = new Point(163, 7);
            textBoxPointSpeed.Name = "textBoxPointSpeed";
            textBoxPointSpeed.Size = new Size(205, 30);
            textBoxPointSpeed.Size = new Size(154, 30);
            textBoxPointSpeed.TabIndex = 11;
            textBoxPointSpeed.Text = "0";
            textBoxPointSpeed.TextChanged += textBoxPointSpeed_TextChanged;
@@ -312,10 +364,13 @@
            // 
            // tableLayoutPanel2
            // 
            tableLayoutPanel2.ColumnCount = 3;
            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 60F));
            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
            tableLayoutPanel2.ColumnCount = 6;
            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 45F));
            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 45F));
            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.3333321F));
            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.3333321F));
            tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.3333321F));
            tableLayoutPanel2.Controls.Add(uiButtonIncreasePitchAngle, 2, 3);
            tableLayoutPanel2.Controls.Add(groupBoxPitchAnglePosition, 1, 3);
            tableLayoutPanel2.Controls.Add(uiButtonDecreasePitchAngle, 0, 3);
@@ -328,6 +383,18 @@
            tableLayoutPanel2.Controls.Add(uiButtonIncreaseX, 2, 0);
            tableLayoutPanel2.Controls.Add(uiButtonDecreaseX, 0, 0);
            tableLayoutPanel2.Controls.Add(groupBoxXPosition, 1, 0);
            tableLayoutPanel2.Controls.Add(groupBoxYVarAddress, 3, 1);
            tableLayoutPanel2.Controls.Add(groupBoxXVarAddress, 3, 0);
            tableLayoutPanel2.Controls.Add(groupBoxZVarAddress, 3, 2);
            tableLayoutPanel2.Controls.Add(groupBoxWVarAddress, 3, 3);
            tableLayoutPanel2.Controls.Add(groupBoxYDetectLocation, 4, 1);
            tableLayoutPanel2.Controls.Add(groupBoxZDetectLocation, 4, 2);
            tableLayoutPanel2.Controls.Add(groupBoxWDetectLocation, 4, 3);
            tableLayoutPanel2.Controls.Add(groupBoxXDetectLocation, 4, 0);
            tableLayoutPanel2.Controls.Add(groupBoxXOriginalLocation, 5, 0);
            tableLayoutPanel2.Controls.Add(groupBoxYOriginalLocation, 5, 1);
            tableLayoutPanel2.Controls.Add(groupBoxZOriginalLocation, 5, 2);
            tableLayoutPanel2.Controls.Add(groupBoxWOriginalLocation, 5, 3);
            tableLayoutPanel2.Dock = DockStyle.Fill;
            tableLayoutPanel2.Location = new Point(3, 183);
            tableLayoutPanel2.Name = "tableLayoutPanel2";
@@ -336,17 +403,17 @@
            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 45F));
            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 45F));
            tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 45F));
            tableLayoutPanel2.Size = new Size(368, 184);
            tableLayoutPanel2.Size = new Size(574, 182);
            tableLayoutPanel2.TabIndex = 3;
            // 
            // uiButtonIncreasePitchAngle
            // 
            uiButtonIncreasePitchAngle.BackColor = Color.Black;
            uiButtonIncreasePitchAngle.Dock = DockStyle.Left;
            uiButtonIncreasePitchAngle.Location = new Point(298, 140);
            uiButtonIncreasePitchAngle.Location = new Point(150, 140);
            uiButtonIncreasePitchAngle.Margin = new Padding(5);
            uiButtonIncreasePitchAngle.Name = "uiButtonIncreasePitchAngle";
            uiButtonIncreasePitchAngle.Size = new Size(32, 39);
            uiButtonIncreasePitchAngle.Size = new Size(32, 37);
            uiButtonIncreasePitchAngle.TabIndex = 27;
            uiButtonIncreasePitchAngle.Text = "+";
            uiButtonIncreasePitchAngle.UseVisualStyleBackColor = false;
@@ -355,12 +422,12 @@
            // groupBoxPitchAnglePosition
            // 
            groupBoxPitchAnglePosition.Controls.Add(textBoxPitchAnglePosition);
            groupBoxPitchAnglePosition.Dock = DockStyle.Fill;
            groupBoxPitchAnglePosition.Font = new Font("宋体", 8F);
            groupBoxPitchAnglePosition.ForeColor = Color.White;
            groupBoxPitchAnglePosition.Location = new Point(123, 138);
            groupBoxPitchAnglePosition.Margin = new Padding(50, 3, 3, 3);
            groupBoxPitchAnglePosition.Location = new Point(48, 138);
            groupBoxPitchAnglePosition.Name = "groupBoxPitchAnglePosition";
            groupBoxPitchAnglePosition.Size = new Size(115, 39);
            groupBoxPitchAnglePosition.Size = new Size(94, 41);
            groupBoxPitchAnglePosition.TabIndex = 26;
            groupBoxPitchAnglePosition.TabStop = false;
            groupBoxPitchAnglePosition.Text = "俯仰角(°)";
@@ -369,10 +436,10 @@
            // 
            textBoxPitchAnglePosition.Dock = DockStyle.Bottom;
            textBoxPitchAnglePosition.Font = new Font("宋体", 10F);
            textBoxPitchAnglePosition.Location = new Point(3, 16);
            textBoxPitchAnglePosition.Location = new Point(3, 18);
            textBoxPitchAnglePosition.Multiline = true;
            textBoxPitchAnglePosition.Name = "textBoxPitchAnglePosition";
            textBoxPitchAnglePosition.Size = new Size(109, 20);
            textBoxPitchAnglePosition.Size = new Size(88, 20);
            textBoxPitchAnglePosition.TabIndex = 13;
            textBoxPitchAnglePosition.Text = "1";
            textBoxPitchAnglePosition.KeyDown += textBoxXPosition_KeyDown;
@@ -382,10 +449,10 @@
            // 
            uiButtonDecreasePitchAngle.BackColor = Color.Black;
            uiButtonDecreasePitchAngle.Dock = DockStyle.Right;
            uiButtonDecreasePitchAngle.Location = new Point(37, 140);
            uiButtonDecreasePitchAngle.Location = new Point(9, 140);
            uiButtonDecreasePitchAngle.Margin = new Padding(5);
            uiButtonDecreasePitchAngle.Name = "uiButtonDecreasePitchAngle";
            uiButtonDecreasePitchAngle.Size = new Size(31, 39);
            uiButtonDecreasePitchAngle.Size = new Size(31, 37);
            uiButtonDecreasePitchAngle.TabIndex = 25;
            uiButtonDecreasePitchAngle.Text = "-";
            uiButtonDecreasePitchAngle.UseVisualStyleBackColor = false;
@@ -394,12 +461,12 @@
            // groupBoxZPosition
            // 
            groupBoxZPosition.Controls.Add(textBoxZPosition);
            groupBoxZPosition.Dock = DockStyle.Fill;
            groupBoxZPosition.Font = new Font("宋体", 8F);
            groupBoxZPosition.ForeColor = Color.White;
            groupBoxZPosition.Location = new Point(123, 93);
            groupBoxZPosition.Margin = new Padding(50, 3, 3, 3);
            groupBoxZPosition.Location = new Point(48, 93);
            groupBoxZPosition.Name = "groupBoxZPosition";
            groupBoxZPosition.Size = new Size(115, 39);
            groupBoxZPosition.Size = new Size(94, 39);
            groupBoxZPosition.TabIndex = 24;
            groupBoxZPosition.TabStop = false;
            groupBoxZPosition.Text = "Z(mm)";
@@ -411,7 +478,7 @@
            textBoxZPosition.Location = new Point(3, 16);
            textBoxZPosition.Multiline = true;
            textBoxZPosition.Name = "textBoxZPosition";
            textBoxZPosition.Size = new Size(109, 20);
            textBoxZPosition.Size = new Size(88, 20);
            textBoxZPosition.TabIndex = 13;
            textBoxZPosition.Text = "1";
            textBoxZPosition.KeyDown += textBoxXPosition_KeyDown;
@@ -420,12 +487,12 @@
            // groupBoxYPosition
            // 
            groupBoxYPosition.Controls.Add(textBoxYPosition);
            groupBoxYPosition.Dock = DockStyle.Fill;
            groupBoxYPosition.Font = new Font("宋体", 8F);
            groupBoxYPosition.ForeColor = Color.White;
            groupBoxYPosition.Location = new Point(123, 48);
            groupBoxYPosition.Margin = new Padding(50, 3, 3, 3);
            groupBoxYPosition.Location = new Point(48, 48);
            groupBoxYPosition.Name = "groupBoxYPosition";
            groupBoxYPosition.Size = new Size(115, 39);
            groupBoxYPosition.Size = new Size(94, 39);
            groupBoxYPosition.TabIndex = 23;
            groupBoxYPosition.TabStop = false;
            groupBoxYPosition.Text = "Y(mm)";
@@ -437,7 +504,7 @@
            textBoxYPosition.Location = new Point(3, 16);
            textBoxYPosition.Multiline = true;
            textBoxYPosition.Name = "textBoxYPosition";
            textBoxYPosition.Size = new Size(109, 20);
            textBoxYPosition.Size = new Size(88, 20);
            textBoxYPosition.TabIndex = 13;
            textBoxYPosition.Text = "1";
            textBoxYPosition.KeyDown += textBoxXPosition_KeyDown;
@@ -447,7 +514,7 @@
            // 
            uiButtonIncreaseZ.BackColor = Color.Black;
            uiButtonIncreaseZ.Dock = DockStyle.Left;
            uiButtonIncreaseZ.Location = new Point(298, 95);
            uiButtonIncreaseZ.Location = new Point(150, 95);
            uiButtonIncreaseZ.Margin = new Padding(5);
            uiButtonIncreaseZ.Name = "uiButtonIncreaseZ";
            uiButtonIncreaseZ.Size = new Size(32, 35);
@@ -460,7 +527,7 @@
            // 
            uiButtonDecreaseZ.BackColor = Color.Black;
            uiButtonDecreaseZ.Dock = DockStyle.Right;
            uiButtonDecreaseZ.Location = new Point(37, 95);
            uiButtonDecreaseZ.Location = new Point(9, 95);
            uiButtonDecreaseZ.Margin = new Padding(5);
            uiButtonDecreaseZ.Name = "uiButtonDecreaseZ";
            uiButtonDecreaseZ.Size = new Size(31, 35);
@@ -473,7 +540,7 @@
            // 
            uiButtonIncreaseY.BackColor = Color.Black;
            uiButtonIncreaseY.Dock = DockStyle.Left;
            uiButtonIncreaseY.Location = new Point(298, 50);
            uiButtonIncreaseY.Location = new Point(150, 50);
            uiButtonIncreaseY.Margin = new Padding(5);
            uiButtonIncreaseY.Name = "uiButtonIncreaseY";
            uiButtonIncreaseY.Size = new Size(32, 35);
@@ -486,7 +553,7 @@
            // 
            uiButtonDecreaseY.BackColor = Color.Black;
            uiButtonDecreaseY.Dock = DockStyle.Right;
            uiButtonDecreaseY.Location = new Point(37, 50);
            uiButtonDecreaseY.Location = new Point(9, 50);
            uiButtonDecreaseY.Margin = new Padding(5);
            uiButtonDecreaseY.Name = "uiButtonDecreaseY";
            uiButtonDecreaseY.Size = new Size(31, 35);
@@ -499,7 +566,7 @@
            // 
            uiButtonIncreaseX.BackColor = Color.Black;
            uiButtonIncreaseX.Dock = DockStyle.Left;
            uiButtonIncreaseX.Location = new Point(298, 5);
            uiButtonIncreaseX.Location = new Point(150, 5);
            uiButtonIncreaseX.Margin = new Padding(5);
            uiButtonIncreaseX.Name = "uiButtonIncreaseX";
            uiButtonIncreaseX.Size = new Size(32, 35);
@@ -512,7 +579,7 @@
            // 
            uiButtonDecreaseX.BackColor = Color.Black;
            uiButtonDecreaseX.Dock = DockStyle.Right;
            uiButtonDecreaseX.Location = new Point(37, 5);
            uiButtonDecreaseX.Location = new Point(9, 5);
            uiButtonDecreaseX.Margin = new Padding(5);
            uiButtonDecreaseX.Name = "uiButtonDecreaseX";
            uiButtonDecreaseX.Size = new Size(31, 35);
@@ -524,12 +591,12 @@
            // groupBoxXPosition
            // 
            groupBoxXPosition.Controls.Add(textBoxXPosition);
            groupBoxXPosition.Dock = DockStyle.Fill;
            groupBoxXPosition.Font = new Font("宋体", 8F);
            groupBoxXPosition.ForeColor = Color.White;
            groupBoxXPosition.Location = new Point(123, 3);
            groupBoxXPosition.Margin = new Padding(50, 3, 3, 3);
            groupBoxXPosition.Location = new Point(48, 3);
            groupBoxXPosition.Name = "groupBoxXPosition";
            groupBoxXPosition.Size = new Size(115, 39);
            groupBoxXPosition.Size = new Size(94, 39);
            groupBoxXPosition.TabIndex = 21;
            groupBoxXPosition.TabStop = false;
            groupBoxXPosition.Text = "X(mm)";
@@ -541,7 +608,7 @@
            textBoxXPosition.Location = new Point(3, 16);
            textBoxXPosition.Multiline = true;
            textBoxXPosition.Name = "textBoxXPosition";
            textBoxXPosition.Size = new Size(109, 20);
            textBoxXPosition.Size = new Size(88, 20);
            textBoxXPosition.TabIndex = 12;
            textBoxXPosition.Text = "1";
            textBoxXPosition.KeyDown += textBoxXPosition_KeyDown;
@@ -552,25 +619,25 @@
            tableLayoutPanel1.ColumnCount = 2;
            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 75F));
            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
            tableLayoutPanel1.Controls.Add(textBox1, 1, 0);
            tableLayoutPanel1.Controls.Add(textBoxSN, 1, 0);
            tableLayoutPanel1.Controls.Add(uiMarkLabelSN, 0, 0);
            tableLayoutPanel1.Dock = DockStyle.Fill;
            tableLayoutPanel1.Location = new Point(3, 3);
            tableLayoutPanel1.Name = "tableLayoutPanel1";
            tableLayoutPanel1.RowCount = 1;
            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
            tableLayoutPanel1.Size = new Size(368, 39);
            tableLayoutPanel1.Size = new Size(574, 39);
            tableLayoutPanel1.TabIndex = 4;
            tableLayoutPanel1.Paint += tableLayoutPanel1_Paint;
            // 
            // textBox1
            // textBoxSN
            // 
            textBox1.Anchor = AnchorStyles.Left | AnchorStyles.Right;
            textBox1.Enabled = false;
            textBox1.Location = new Point(78, 4);
            textBox1.Name = "textBox1";
            textBox1.Size = new Size(287, 30);
            textBox1.TabIndex = 20;
            textBoxSN.Anchor = AnchorStyles.Left | AnchorStyles.Right;
            textBoxSN.Enabled = false;
            textBoxSN.Location = new Point(78, 4);
            textBoxSN.Name = "textBoxSN";
            textBoxSN.Size = new Size(493, 30);
            textBoxSN.TabIndex = 20;
            // 
            // uiMarkLabelSN
            // 
@@ -589,24 +656,24 @@
            tableLayoutPanel7.ColumnCount = 2;
            tableLayoutPanel7.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 75F));
            tableLayoutPanel7.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
            tableLayoutPanel7.Controls.Add(textBox2, 1, 0);
            tableLayoutPanel7.Controls.Add(textBoxName, 1, 0);
            tableLayoutPanel7.Controls.Add(uiMarkLabelName, 0, 0);
            tableLayoutPanel7.Dock = DockStyle.Fill;
            tableLayoutPanel7.Location = new Point(3, 48);
            tableLayoutPanel7.Name = "tableLayoutPanel7";
            tableLayoutPanel7.RowCount = 1;
            tableLayoutPanel7.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
            tableLayoutPanel7.Size = new Size(368, 39);
            tableLayoutPanel7.Size = new Size(574, 39);
            tableLayoutPanel7.TabIndex = 7;
            // 
            // textBox2
            // textBoxName
            // 
            textBox2.Anchor = AnchorStyles.Left | AnchorStyles.Right;
            textBox2.Enabled = false;
            textBox2.Location = new Point(78, 4);
            textBox2.Name = "textBox2";
            textBox2.Size = new Size(287, 30);
            textBox2.TabIndex = 21;
            textBoxName.Anchor = AnchorStyles.Left | AnchorStyles.Right;
            textBoxName.Enabled = false;
            textBoxName.Location = new Point(78, 4);
            textBoxName.Name = "textBoxName";
            textBoxName.Size = new Size(493, 30);
            textBoxName.TabIndex = 21;
            // 
            // uiMarkLabelName
            // 
@@ -630,7 +697,7 @@
            uiGroupBoxImage.MinimumSize = new Size(1, 1);
            uiGroupBoxImage.Name = "uiGroupBoxImage";
            uiGroupBoxImage.Padding = new Padding(0, 32, 0, 0);
            uiGroupBoxImage.Size = new Size(495, 684);
            uiGroupBoxImage.Size = new Size(589, 684);
            uiGroupBoxImage.TabIndex = 17;
            uiGroupBoxImage.TabStop = false;
            uiGroupBoxImage.Text = "实时采集";
@@ -651,8 +718,8 @@
            // uiSplitContainer1.Panel2
            // 
            uiSplitContainer1.Panel2.Controls.Add(uiGroupBoxImage);
            uiSplitContainer1.Size = new Size(880, 684);
            uiSplitContainer1.SplitterDistance = 374;
            uiSplitContainer1.Size = new Size(1180, 684);
            uiSplitContainer1.SplitterDistance = 580;
            uiSplitContainer1.SplitterWidth = 11;
            uiSplitContainer1.TabIndex = 20;
            // 
@@ -669,7 +736,7 @@
            themeForm1.Padding = new Padding(10, 70, 10, 9);
            themeForm1.RoundCorners = true;
            themeForm1.Sizable = true;
            themeForm1.Size = new Size(900, 763);
            themeForm1.Size = new Size(1200, 763);
            themeForm1.SmartBounds = true;
            themeForm1.StartPosition = FormStartPosition.WindowsDefaultLocation;
            themeForm1.TabIndex = 21;
@@ -685,7 +752,7 @@
            controlBox1.EnableMaximizeButton = true;
            controlBox1.EnableMinimizeButton = true;
            controlBox1.ForeColor = Color.FromArgb(155, 155, 155);
            controlBox1.Location = new Point(800, 18);
            controlBox1.Location = new Point(1100, 18);
            controlBox1.MaximizeHoverColor = Color.FromArgb(74, 74, 74);
            controlBox1.MinimizeHoverColor = Color.FromArgb(63, 63, 65);
            controlBox1.Name = "controlBox1";
@@ -693,12 +760,358 @@
            controlBox1.TabIndex = 21;
            controlBox1.Text = "controlBox1";
            // 
            // panel1
            //
            panel1.Controls.Add(tableLayoutPanel3);
            panel1.Dock = DockStyle.Fill;
            panel1.Location = new Point(0, 23);
            panel1.Name = "panel1";
            panel1.Padding = new Padding(0, 3, 0, 0);
            panel1.Size = new Size(580, 661);
            panel1.TabIndex = 1;
            //
            // groupBoxXVarAddress
            //
            groupBoxXVarAddress.Controls.Add(textBoxXVarAddress);
            groupBoxXVarAddress.Dock = DockStyle.Fill;
            groupBoxXVarAddress.Font = new Font("宋体", 8F);
            groupBoxXVarAddress.ForeColor = Color.White;
            groupBoxXVarAddress.Location = new Point(193, 3);
            groupBoxXVarAddress.Name = "groupBoxXVarAddress";
            groupBoxXVarAddress.Size = new Size(122, 39);
            groupBoxXVarAddress.TabIndex = 28;
            groupBoxXVarAddress.TabStop = false;
            groupBoxXVarAddress.Text = "X轴变量地址";
            //
            // textBoxXVarAddress
            //
            textBoxXVarAddress.Dock = DockStyle.Bottom;
            textBoxXVarAddress.Font = new Font("宋体", 10F);
            textBoxXVarAddress.Location = new Point(3, 16);
            textBoxXVarAddress.Multiline = true;
            textBoxXVarAddress.Name = "textBoxXVarAddress";
            textBoxXVarAddress.Size = new Size(116, 20);
            textBoxXVarAddress.TabIndex = 12;
            textBoxXVarAddress.Text = "1";
            //
            // groupBoxYVarAddress
            //
            groupBoxYVarAddress.Controls.Add(textBoxYVarAddress);
            groupBoxYVarAddress.Dock = DockStyle.Fill;
            groupBoxYVarAddress.Font = new Font("宋体", 8F);
            groupBoxYVarAddress.ForeColor = Color.White;
            groupBoxYVarAddress.Location = new Point(193, 48);
            groupBoxYVarAddress.Name = "groupBoxYVarAddress";
            groupBoxYVarAddress.Size = new Size(122, 39);
            groupBoxYVarAddress.TabIndex = 29;
            groupBoxYVarAddress.TabStop = false;
            groupBoxYVarAddress.Text = "Y轴变量地址";
            //
            // textBoxYVarAddress
            //
            textBoxYVarAddress.Dock = DockStyle.Bottom;
            textBoxYVarAddress.Font = new Font("宋体", 10F);
            textBoxYVarAddress.Location = new Point(3, 16);
            textBoxYVarAddress.Multiline = true;
            textBoxYVarAddress.Name = "textBoxYVarAddress";
            textBoxYVarAddress.Size = new Size(116, 20);
            textBoxYVarAddress.TabIndex = 12;
            textBoxYVarAddress.Text = "1";
            //
            // groupBoxZVarAddress
            //
            groupBoxZVarAddress.Controls.Add(textBoxZVarAddress);
            groupBoxZVarAddress.Dock = DockStyle.Fill;
            groupBoxZVarAddress.Font = new Font("宋体", 8F);
            groupBoxZVarAddress.ForeColor = Color.White;
            groupBoxZVarAddress.Location = new Point(193, 93);
            groupBoxZVarAddress.Name = "groupBoxZVarAddress";
            groupBoxZVarAddress.Size = new Size(122, 39);
            groupBoxZVarAddress.TabIndex = 29;
            groupBoxZVarAddress.TabStop = false;
            groupBoxZVarAddress.Text = "Z轴变量地址";
            //
            // textBoxZVarAddress
            //
            textBoxZVarAddress.Dock = DockStyle.Bottom;
            textBoxZVarAddress.Font = new Font("宋体", 10F);
            textBoxZVarAddress.Location = new Point(3, 16);
            textBoxZVarAddress.Multiline = true;
            textBoxZVarAddress.Name = "textBoxZVarAddress";
            textBoxZVarAddress.Size = new Size(116, 20);
            textBoxZVarAddress.TabIndex = 12;
            textBoxZVarAddress.Text = "1";
            //
            // groupBoxWVarAddress
            //
            groupBoxWVarAddress.Controls.Add(textBoxWVarAddress);
            groupBoxWVarAddress.Dock = DockStyle.Fill;
            groupBoxWVarAddress.Font = new Font("宋体", 8F);
            groupBoxWVarAddress.ForeColor = Color.White;
            groupBoxWVarAddress.Location = new Point(193, 138);
            groupBoxWVarAddress.Name = "groupBoxWVarAddress";
            groupBoxWVarAddress.Size = new Size(122, 41);
            groupBoxWVarAddress.TabIndex = 29;
            groupBoxWVarAddress.TabStop = false;
            groupBoxWVarAddress.Text = "W轴变量地址";
            //
            // textBoxWVarAddress
            //
            textBoxWVarAddress.Dock = DockStyle.Bottom;
            textBoxWVarAddress.Font = new Font("宋体", 10F);
            textBoxWVarAddress.Location = new Point(3, 18);
            textBoxWVarAddress.Multiline = true;
            textBoxWVarAddress.Name = "textBoxWVarAddress";
            textBoxWVarAddress.Size = new Size(116, 20);
            textBoxWVarAddress.TabIndex = 12;
            textBoxWVarAddress.Text = "1";
            //
            // groupBoxXDetectLocation
            //
            groupBoxXDetectLocation.Controls.Add(textBoxXDetectLocation);
            groupBoxXDetectLocation.Dock = DockStyle.Fill;
            groupBoxXDetectLocation.Font = new Font("宋体", 8F);
            groupBoxXDetectLocation.ForeColor = Color.White;
            groupBoxXDetectLocation.Location = new Point(321, 3);
            groupBoxXDetectLocation.Name = "groupBoxXDetectLocation";
            groupBoxXDetectLocation.Size = new Size(122, 39);
            groupBoxXDetectLocation.TabIndex = 30;
            groupBoxXDetectLocation.TabStop = false;
            groupBoxXDetectLocation.Text = "X轴检测位置";
            //
            // textBoxXDetectLocation
            //
            textBoxXDetectLocation.Dock = DockStyle.Bottom;
            textBoxXDetectLocation.Font = new Font("宋体", 10F);
            textBoxXDetectLocation.Location = new Point(3, 16);
            textBoxXDetectLocation.Multiline = true;
            textBoxXDetectLocation.Name = "textBoxXDetectLocation";
            textBoxXDetectLocation.Size = new Size(116, 20);
            textBoxXDetectLocation.TabIndex = 12;
            textBoxXDetectLocation.Text = "1";
            //
            // groupBoxYDetectLocation
            //
            groupBoxYDetectLocation.Controls.Add(textBoxYDetectLocation);
            groupBoxYDetectLocation.Dock = DockStyle.Fill;
            groupBoxYDetectLocation.Font = new Font("宋体", 8F);
            groupBoxYDetectLocation.ForeColor = Color.White;
            groupBoxYDetectLocation.Location = new Point(321, 48);
            groupBoxYDetectLocation.Name = "groupBoxYDetectLocation";
            groupBoxYDetectLocation.Size = new Size(122, 39);
            groupBoxYDetectLocation.TabIndex = 30;
            groupBoxYDetectLocation.TabStop = false;
            groupBoxYDetectLocation.Text = "Y轴检测位置";
            //
            // textBoxYDetectLocation
            //
            textBoxYDetectLocation.Dock = DockStyle.Bottom;
            textBoxYDetectLocation.Font = new Font("宋体", 10F);
            textBoxYDetectLocation.Location = new Point(3, 16);
            textBoxYDetectLocation.Multiline = true;
            textBoxYDetectLocation.Name = "textBoxYDetectLocation";
            textBoxYDetectLocation.Size = new Size(116, 20);
            textBoxYDetectLocation.TabIndex = 12;
            textBoxYDetectLocation.Text = "1";
            //
            // groupBoxZDetectLocation
            //
            groupBoxZDetectLocation.Controls.Add(textBoxZDetectLocation);
            groupBoxZDetectLocation.Dock = DockStyle.Fill;
            groupBoxZDetectLocation.Font = new Font("宋体", 8F);
            groupBoxZDetectLocation.ForeColor = Color.White;
            groupBoxZDetectLocation.Location = new Point(321, 93);
            groupBoxZDetectLocation.Name = "groupBoxZDetectLocation";
            groupBoxZDetectLocation.Size = new Size(122, 39);
            groupBoxZDetectLocation.TabIndex = 30;
            groupBoxZDetectLocation.TabStop = false;
            groupBoxZDetectLocation.Text = "Z轴检测位置";
            //
            // textBoxZDetectLocation
            //
            textBoxZDetectLocation.Dock = DockStyle.Bottom;
            textBoxZDetectLocation.Font = new Font("宋体", 10F);
            textBoxZDetectLocation.Location = new Point(3, 16);
            textBoxZDetectLocation.Multiline = true;
            textBoxZDetectLocation.Name = "textBoxZDetectLocation";
            textBoxZDetectLocation.Size = new Size(116, 20);
            textBoxZDetectLocation.TabIndex = 12;
            textBoxZDetectLocation.Text = "1";
            //
            // groupBoxWDetectLocation
            //
            groupBoxWDetectLocation.Controls.Add(textBoxWDetectLocation);
            groupBoxWDetectLocation.Dock = DockStyle.Fill;
            groupBoxWDetectLocation.Font = new Font("宋体", 8F);
            groupBoxWDetectLocation.ForeColor = Color.White;
            groupBoxWDetectLocation.Location = new Point(321, 138);
            groupBoxWDetectLocation.Name = "groupBoxWDetectLocation";
            groupBoxWDetectLocation.Size = new Size(122, 41);
            groupBoxWDetectLocation.TabIndex = 30;
            groupBoxWDetectLocation.TabStop = false;
            groupBoxWDetectLocation.Text = "W轴检测位置";
            //
            // textBoxWDetectLocation
            //
            textBoxWDetectLocation.Dock = DockStyle.Bottom;
            textBoxWDetectLocation.Font = new Font("宋体", 10F);
            textBoxWDetectLocation.Location = new Point(3, 18);
            textBoxWDetectLocation.Multiline = true;
            textBoxWDetectLocation.Name = "textBoxWDetectLocation";
            textBoxWDetectLocation.Size = new Size(116, 20);
            textBoxWDetectLocation.TabIndex = 12;
            textBoxWDetectLocation.Text = "1";
            //
            // groupBoxXOriginalLocation
            //
            groupBoxXOriginalLocation.Controls.Add(textBoxXOriginalLocation);
            groupBoxXOriginalLocation.Dock = DockStyle.Fill;
            groupBoxXOriginalLocation.Font = new Font("宋体", 8F);
            groupBoxXOriginalLocation.ForeColor = Color.White;
            groupBoxXOriginalLocation.Location = new Point(449, 3);
            groupBoxXOriginalLocation.Name = "groupBoxXOriginalLocation";
            groupBoxXOriginalLocation.Size = new Size(122, 39);
            groupBoxXOriginalLocation.TabIndex = 30;
            groupBoxXOriginalLocation.TabStop = false;
            groupBoxXOriginalLocation.Text = "X轴原点位置";
            //
            // textBoxXOriginalLocation
            //
            textBoxXOriginalLocation.Dock = DockStyle.Bottom;
            textBoxXOriginalLocation.Font = new Font("宋体", 10F);
            textBoxXOriginalLocation.Location = new Point(3, 16);
            textBoxXOriginalLocation.Multiline = true;
            textBoxXOriginalLocation.Name = "textBoxXOriginalLocation";
            textBoxXOriginalLocation.Size = new Size(116, 20);
            textBoxXOriginalLocation.TabIndex = 12;
            textBoxXOriginalLocation.Text = "1";
            //
            // groupBoxYOriginalLocation
            //
            groupBoxYOriginalLocation.Controls.Add(textBoxYOriginalLocation);
            groupBoxYOriginalLocation.Dock = DockStyle.Fill;
            groupBoxYOriginalLocation.Font = new Font("宋体", 8F);
            groupBoxYOriginalLocation.ForeColor = Color.White;
            groupBoxYOriginalLocation.Location = new Point(449, 48);
            groupBoxYOriginalLocation.Name = "groupBoxYOriginalLocation";
            groupBoxYOriginalLocation.Size = new Size(122, 39);
            groupBoxYOriginalLocation.TabIndex = 30;
            groupBoxYOriginalLocation.TabStop = false;
            groupBoxYOriginalLocation.Text = "Y轴原点位置";
            //
            // textBoxYOriginalLocation
            //
            textBoxYOriginalLocation.Dock = DockStyle.Bottom;
            textBoxYOriginalLocation.Font = new Font("宋体", 10F);
            textBoxYOriginalLocation.Location = new Point(3, 16);
            textBoxYOriginalLocation.Multiline = true;
            textBoxYOriginalLocation.Name = "textBoxYOriginalLocation";
            textBoxYOriginalLocation.Size = new Size(116, 20);
            textBoxYOriginalLocation.TabIndex = 12;
            textBoxYOriginalLocation.Text = "1";
            //
            // groupBoxZOriginalLocation
            //
            groupBoxZOriginalLocation.Controls.Add(textBoxZOriginalLocation);
            groupBoxZOriginalLocation.Dock = DockStyle.Fill;
            groupBoxZOriginalLocation.Font = new Font("宋体", 8F);
            groupBoxZOriginalLocation.ForeColor = Color.White;
            groupBoxZOriginalLocation.Location = new Point(449, 93);
            groupBoxZOriginalLocation.Name = "groupBoxZOriginalLocation";
            groupBoxZOriginalLocation.Size = new Size(122, 39);
            groupBoxZOriginalLocation.TabIndex = 30;
            groupBoxZOriginalLocation.TabStop = false;
            groupBoxZOriginalLocation.Text = "Z轴原点位置";
            //
            // textBoxZOriginalLocation
            //
            textBoxZOriginalLocation.Dock = DockStyle.Bottom;
            textBoxZOriginalLocation.Font = new Font("宋体", 10F);
            textBoxZOriginalLocation.Location = new Point(3, 16);
            textBoxZOriginalLocation.Multiline = true;
            textBoxZOriginalLocation.Name = "textBoxZOriginalLocation";
            textBoxZOriginalLocation.Size = new Size(116, 20);
            textBoxZOriginalLocation.TabIndex = 12;
            textBoxZOriginalLocation.Text = "1";
            //
            // groupBoxWOriginalLocation
            //
            groupBoxWOriginalLocation.Controls.Add(textBoxWOriginalLocation);
            groupBoxWOriginalLocation.Dock = DockStyle.Fill;
            groupBoxWOriginalLocation.Font = new Font("宋体", 8F);
            groupBoxWOriginalLocation.ForeColor = Color.White;
            groupBoxWOriginalLocation.Location = new Point(449, 138);
            groupBoxWOriginalLocation.Name = "groupBoxWOriginalLocation";
            groupBoxWOriginalLocation.Size = new Size(122, 41);
            groupBoxWOriginalLocation.TabIndex = 30;
            groupBoxWOriginalLocation.TabStop = false;
            groupBoxWOriginalLocation.Text = "W轴原点位置";
            //
            // textBoxWOriginalLocation
            //
            textBoxWOriginalLocation.Dock = DockStyle.Bottom;
            textBoxWOriginalLocation.Font = new Font("宋体", 10F);
            textBoxWOriginalLocation.Location = new Point(3, 18);
            textBoxWOriginalLocation.Multiline = true;
            textBoxWOriginalLocation.Name = "textBoxWOriginalLocation";
            textBoxWOriginalLocation.Size = new Size(116, 20);
            textBoxWOriginalLocation.TabIndex = 12;
            textBoxWOriginalLocation.Text = "1";
            //
            // groupBoxPulseMotionSpeedAddress
            //
            groupBoxPulseMotionSpeedAddress.Controls.Add(textBoxPulseMotionSpeedAddress);
            groupBoxPulseMotionSpeedAddress.Dock = DockStyle.Fill;
            groupBoxPulseMotionSpeedAddress.Font = new Font("宋体", 8F);
            groupBoxPulseMotionSpeedAddress.ForeColor = Color.White;
            groupBoxPulseMotionSpeedAddress.Location = new Point(323, 3);
            groupBoxPulseMotionSpeedAddress.Name = "groupBoxPulseMotionSpeedAddress";
            groupBoxPulseMotionSpeedAddress.Size = new Size(114, 39);
            groupBoxPulseMotionSpeedAddress.TabIndex = 30;
            groupBoxPulseMotionSpeedAddress.TabStop = false;
            groupBoxPulseMotionSpeedAddress.Text = "点速度地址";
            //
            // textBoxPulseMotionSpeedAddress
            //
            textBoxPulseMotionSpeedAddress.Dock = DockStyle.Bottom;
            textBoxPulseMotionSpeedAddress.Font = new Font("宋体", 10F);
            textBoxPulseMotionSpeedAddress.Location = new Point(3, 16);
            textBoxPulseMotionSpeedAddress.Multiline = true;
            textBoxPulseMotionSpeedAddress.Name = "textBoxPulseMotionSpeedAddress";
            textBoxPulseMotionSpeedAddress.Size = new Size(108, 20);
            textBoxPulseMotionSpeedAddress.TabIndex = 12;
            textBoxPulseMotionSpeedAddress.Text = "1";
            //
            // groupBoxAngularVelocityAddress
            //
            groupBoxAngularVelocityAddress.Controls.Add(textBoxAngularVelocityAddress);
            groupBoxAngularVelocityAddress.Dock = DockStyle.Fill;
            groupBoxAngularVelocityAddress.Font = new Font("宋体", 8F);
            groupBoxAngularVelocityAddress.ForeColor = Color.White;
            groupBoxAngularVelocityAddress.Location = new Point(323, 48);
            groupBoxAngularVelocityAddress.Name = "groupBoxAngularVelocityAddress";
            groupBoxAngularVelocityAddress.Size = new Size(114, 39);
            groupBoxAngularVelocityAddress.TabIndex = 30;
            groupBoxAngularVelocityAddress.TabStop = false;
            groupBoxAngularVelocityAddress.Text = "角速度地址";
            //
            // textBoxAngularVelocityAddress
            //
            textBoxAngularVelocityAddress.Dock = DockStyle.Bottom;
            textBoxAngularVelocityAddress.Font = new Font("宋体", 10F);
            textBoxAngularVelocityAddress.Location = new Point(3, 16);
            textBoxAngularVelocityAddress.Multiline = true;
            textBoxAngularVelocityAddress.Name = "textBoxAngularVelocityAddress";
            textBoxAngularVelocityAddress.Size = new Size(108, 20);
            textBoxAngularVelocityAddress.TabIndex = 12;
            textBoxAngularVelocityAddress.Text = "1";
            //
            // MotionControlForm
            // 
            AutoScaleDimensions = new SizeF(120F, 120F);
            AutoScaleMode = AutoScaleMode.Dpi;
            AutoSize = true;
            ClientSize = new Size(900, 763);
            ClientSize = new Size(1200, 763);
            Controls.Add(themeForm1);
            FormBorderStyle = FormBorderStyle.None;
            MinimumSize = new Size(261, 61);
@@ -729,6 +1142,35 @@
            ((System.ComponentModel.ISupportInitialize)uiSplitContainer1).EndInit();
            uiSplitContainer1.ResumeLayout(false);
            themeForm1.ResumeLayout(false);
            panel1.ResumeLayout(false);
            groupBoxXVarAddress.ResumeLayout(false);
            groupBoxXVarAddress.PerformLayout();
            groupBoxYVarAddress.ResumeLayout(false);
            groupBoxYVarAddress.PerformLayout();
            groupBoxZVarAddress.ResumeLayout(false);
            groupBoxZVarAddress.PerformLayout();
            groupBoxWVarAddress.ResumeLayout(false);
            groupBoxWVarAddress.PerformLayout();
            groupBoxXDetectLocation.ResumeLayout(false);
            groupBoxXDetectLocation.PerformLayout();
            groupBoxYDetectLocation.ResumeLayout(false);
            groupBoxYDetectLocation.PerformLayout();
            groupBoxZDetectLocation.ResumeLayout(false);
            groupBoxZDetectLocation.PerformLayout();
            groupBoxWDetectLocation.ResumeLayout(false);
            groupBoxWDetectLocation.PerformLayout();
            groupBoxXOriginalLocation.ResumeLayout(false);
            groupBoxXOriginalLocation.PerformLayout();
            groupBoxYOriginalLocation.ResumeLayout(false);
            groupBoxYOriginalLocation.PerformLayout();
            groupBoxZOriginalLocation.ResumeLayout(false);
            groupBoxZOriginalLocation.PerformLayout();
            groupBoxWOriginalLocation.ResumeLayout(false);
            groupBoxWOriginalLocation.PerformLayout();
            groupBoxPulseMotionSpeedAddress.ResumeLayout(false);
            groupBoxPulseMotionSpeedAddress.PerformLayout();
            groupBoxAngularVelocityAddress.ResumeLayout(false);
            groupBoxAngularVelocityAddress.PerformLayout();
            ResumeLayout(false);
        }
@@ -774,10 +1216,39 @@
        private TableLayoutPanel tableLayoutPanel5;
        private Button uiButtonGrabOnce;
        private TableLayoutPanel tableLayoutPanel1;
        private TextBox textBox1;
        private TextBox textBoxSN;
        private Label uiMarkLabelSN;
        private Button uiButtonCloseSoftGrab;
        private Label uiMarkLabelName;
        private TextBox textBox2;
        private TextBox textBoxName;
        private Panel panel1;
        private GroupBox groupBoxYVarAddress;
        private TextBox textBoxYVarAddress;
        private GroupBox groupBoxXVarAddress;
        private TextBox textBoxXVarAddress;
        private GroupBox groupBoxZVarAddress;
        private TextBox textBoxZVarAddress;
        private GroupBox groupBoxWVarAddress;
        private TextBox textBoxWVarAddress;
        private GroupBox groupBoxYDetectLocation;
        private TextBox textBoxYDetectLocation;
        private GroupBox groupBoxZDetectLocation;
        private TextBox textBoxZDetectLocation;
        private GroupBox groupBoxWDetectLocation;
        private TextBox textBoxWDetectLocation;
        private GroupBox groupBoxXDetectLocation;
        private TextBox textBoxXDetectLocation;
        private GroupBox groupBoxXOriginalLocation;
        private TextBox textBoxXOriginalLocation;
        private GroupBox groupBoxYOriginalLocation;
        private TextBox textBoxYOriginalLocation;
        private GroupBox groupBoxZOriginalLocation;
        private TextBox textBoxZOriginalLocation;
        private GroupBox groupBoxWOriginalLocation;
        private TextBox textBoxWOriginalLocation;
        private GroupBox groupBoxPulseMotionSpeedAddress;
        private TextBox textBoxPulseMotionSpeedAddress;
        private GroupBox groupBoxAngularVelocityAddress;
        private TextBox textBoxAngularVelocityAddress;
    }
}
LB_SmartVision/Forms/Pages/MotionControlPage/MotionControlForm.cs
@@ -34,7 +34,7 @@
            this.camera = camera;
            this.Text = camera.SN;
            textBox1.Text = camera.SN;
            textBoxSN.Text = camera.SN;
            onlinePictureBox = new UserPictureBox(uiGroupBoxImage);
            this.uiGroupBoxImage.Controls.Clear();
LB_SmartVision/Forms/Pages/MotionControlPage/MotionControlForm.resx
@@ -121,7 +121,7 @@
  <data name="themeForm1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
    <value>
        iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
        wgAADsIBFShKgAAAA+JJREFUWEftVkuIHGUQbt34iMEoq2S2q3p3yTJsuqpnJ+L6WBRdwaigohfFgEou
        wQAADsEBuJFr7QAAA+JJREFUWEftVkuIHGUQbt34iMEoq2S2q3p3yTJsuqpnJ+L6WBRdwaigohfFgEou
        BkVBUPCBCEG8BXNQ48GLeImCehIJxMsqhsSZruod46K4HtSIGjU+4iOr0c1I9fSsM3/PLNtCPO0H36m/
        evz/X11VnreKVRTAHPOZumkY6lFwqURws3BwZ8ywTQnuiCP/+iTCzY1qaUPzdm/Atf3PaHre6XPsjyQM
        2xLGV4XwIyX4QRj+UMK/lPFvJTyhBMeV8IgQvmRJuH4Ko+l5p9UjGBbCJ5RxTgj+VMZmXxKcSAjekHE/
LB_SmartVision/VisionForm.Designer.cs
@@ -89,7 +89,7 @@
            // 
            sc_VisionForm.Panel2.Controls.Add(grb_Info);
            sc_VisionForm.Size = new Size(1416, 781);
            sc_VisionForm.SplitterDistance = 594;
            sc_VisionForm.SplitterDistance = 593;
            sc_VisionForm.SplitterWidth = 5;
            sc_VisionForm.TabIndex = 1;
            // 
@@ -108,7 +108,7 @@
            tlp_MainView.RowStyles.Add(new RowStyle(SizeType.Absolute, 60F));
            tlp_MainView.RowStyles.Add(new RowStyle(SizeType.Absolute, 39F));
            tlp_MainView.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
            tlp_MainView.Size = new Size(1416, 594);
            tlp_MainView.Size = new Size(1416, 593);
            tlp_MainView.TabIndex = 1;
            tlp_MainView.TagString = null;
            // 
@@ -122,7 +122,7 @@
            materialTabControl.MouseState = MaterialSkin.MouseState.HOVER;
            materialTabControl.Name = "materialTabControl";
            materialTabControl.SelectedIndex = 0;
            materialTabControl.Size = new Size(1412, 491);
            materialTabControl.Size = new Size(1412, 490);
            materialTabControl.TabIndex = 0;
            // 
            // tlp_VisionMainOperator
@@ -249,7 +249,7 @@
            grb_Info.MinimumSize = new Size(1, 1);
            grb_Info.Name = "grb_Info";
            grb_Info.Padding = new Padding(0, 40, 0, 0);
            grb_Info.Size = new Size(1416, 182);
            grb_Info.Size = new Size(1416, 183);
            grb_Info.TabIndex = 1;
            grb_Info.Text = "日志显示区:";
            grb_Info.TextAlignment = ContentAlignment.MiddleLeft;
@@ -265,7 +265,7 @@
            rich_Info.Name = "rich_Info";
            rich_Info.Padding = new Padding(2);
            rich_Info.ShowText = false;
            rich_Info.Size = new Size(1416, 142);
            rich_Info.Size = new Size(1416, 143);
            rich_Info.TabIndex = 0;
            rich_Info.TextAlignment = ContentAlignment.MiddleLeft;
            // 
LB_SmartVision/VisionForm.cs
@@ -843,12 +843,8 @@
                    if (!string.IsNullOrEmpty(CommunicatorAddress) && CommunicatorAddress.Contains("SiemensLBS7"))
                    {
                        // 定义正则表达式以提取协议、IP 地址和端口
                        //1.    \((.*?)\):\(和 \) 是用于匹配括号的转义字符。
                        //      (.*?) 是一个非贪婪的匹配,用来匹配类名(MyProcesses.Communicators.TCPServer 或 MyProcesses.Communicators.UARTPort)。
                        //2.    ([^:] +):匹配冒号之前的部分,即地址(127.0.0.1 或 COM5)。这里使用了[^:] 来匹配除了冒号之外的任意字符。
                        //3.    (\d +) :匹配端口号,确保它匹配一个或多个数字。
                        string pattern = @"^\((?<ClassName>[^)]+)\)\[(?<IP>[^]]+)\]\[(?<Slot>[^]]+)\]\[(?<CpuType>[^]]+)\]\[(?<PlcAddress>[^]]+)\]$";
                        // 更新正则以支持可选的数据类型字段
                        string pattern = @"^\((?<ClassName>[^)]+)\)\[(?<IP>[^]]+)\]\[(?<Slot>[^]]+)\]\[(?<CpuType>[^]]+)\]\[(?<PlcAddress>[^]]+)\](?:\[(?<DataType>[^]]+)\])?$";
                        Match match = Regex.Match(CommunicatorAddress, pattern);
                        if (match.Success)
@@ -858,6 +854,8 @@
                            string Slot = match.Groups["Slot"].Value;        // "1111"
                            string CpuType= match.Groups["CpuType"].Value;
                            string PlcAddress = match.Groups["PlcAddress"].Value;
                            string DataType = match.Groups["DataType"].Success ? match.Groups["DataType"].Value : "String";
                            if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(Slot) || string.IsNullOrEmpty(CpuType) || string.IsNullOrEmpty(PlcAddress))
                                break;
@@ -880,6 +878,7 @@
                            Communicator.CommunicatorConnections.Add("端口", Slot);
                            Communicator.CommunicatorConnections.Add("型号", CpuType);
                            Communicator.CommunicatorConnections.Add("变量地址", PlcAddress);
                            Communicator.CommunicatorConnections.Add("数据类型", DataType);
                            Communicator.CommunicatorName = CommunicatorName;
                            if (!Communicator.Connect())
                            {
@@ -1040,11 +1039,14 @@
                    {
                        string CpuType = item.Value.CommunicatorConnections["型号"].ToString();
                        string PlcAddress = item.Value.CommunicatorConnections["变量地址"].ToString();
                        string DataType = item.Value.CommunicatorConnections.Contains("数据类型") ?
                                          item.Value.CommunicatorConnections["数据类型"].ToString() : "String";
                        if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(PORT) || string.IsNullOrEmpty(CpuType) || string.IsNullOrEmpty(PlcAddress))
                        {
                            break;
                        }
                        string CommunicatorConnectionString = $"({ClassName})[{IP}][{PORT}][{CpuType}][{PlcAddress}]";
                        string CommunicatorConnectionString = $"({ClassName})[{IP}][{PORT}][{CpuType}][{PlcAddress}][{DataType}]";
                        GlobalVar.allCommunicatorsConnectionString.TryAdd(item.Key, CommunicatorConnectionString);
                    }
                    else
LB_VisionProcesses/Cameras/HRCameras/HRCamera.cs
@@ -1,5 +1,6 @@
using HalconDotNet;
using LB_SmartVisionCommon;
using LB_VisionProcesses.Cameras.LBCameras;
using MVSDK_Net;
using System;
using System.Collections.Generic;
@@ -28,6 +29,8 @@
        private Thread _callbackThread; // 回调处理线程
        private List<IMVDefine.IMV_Frame> _frameList; // 图像缓存列表
        private readonly object _frameLock = new object(); // 帧缓存锁
        // 新增:CollectedImages操作锁,保证线程安全
        private readonly object _collectedImagesLock = new object();
        private IMVDefine.IMV_EPixelType type = IMVDefine.IMV_EPixelType.gvspPixelMono8;
        private IMVDefine.IMV_PixelConvertParam stPixelConvertParam = new IMVDefine.IMV_PixelConvertParam();
@@ -217,30 +220,135 @@
            }
            try
            {
                // 1. 将帧转换为Bitmap
                Bitmap bitmap = ConvertFrameToBitmap(frame);
                // 释放帧数据
                // release frame
                // 释放原始帧数据(SDK层面释放)
                _camera.IMV_ReleaseFrame(ref frame);
                Task.Factory.StartNew(() =>
                // 2. 空值校验:转换失败则直接返回
                if (bitmap == null)
                {
                    CallBackImg = (Bitmap)bitmap.Clone();
                    if (CallBackImg == null)
                    AsyncLogHelper.Warn(SN + "帧转换为Bitmap失败,跳过处理");
                    return;
                }
                // 3. 线程安全地将Bitmap添加到CollectedImages字典
                lock (_collectedImagesLock)
                {
                    // 确保当前相机SN对应的列表存在
                    if (!CollectedImages.ContainsKey(SN))
                    {
                        return;
                        CollectedImages[SN] = new List<Bitmap>();
                    }
                    if (GetTriggerMode(out TriggerMode mode, out TriggerSource source))
                    {
                        if (mode == TriggerMode.On && source != TriggerSource.Software)
                            TriggerRunMessageReceived?.Invoke(SN, source.ToString());  // 触发运行事件
                    }
                    bitmap.Dispose();
                });
                    CollectedImages[SN].Add(bitmap);
                    AsyncLogHelper.Info(SN + $"图像已加入缓存,当前缓存数量:{CollectedImages[SN].Count}");
                }
                // 4. 处理CollectedImages中的图像:遍历消费列表第一个元素直到为空
                ProcessCollectedImages();
                //Task.Factory.StartNew(() =>
                //{
                //    CallBackImg = (Bitmap)bitmap.Clone();
                //    if (CallBackImg == null)
                //    {
                //        return;
                //    }
                //    if (GetTriggerMode(out TriggerMode mode, out TriggerSource source))
                //    {
                //        if (mode == TriggerMode.On && source != TriggerSource.Software)
                //            TriggerRunMessageReceived?.Invoke(SN, source.ToString());  // 触发运行事件
                //    }
                //    bitmap.Dispose();
                //});
            }
            catch { }
            AsyncLogHelper.Info(SN + "Get frame blockId = {0}" + frame.frameInfo.blockId);
        }
        /// <summary>
        /// 处理CollectedImages中的缓存图像
        /// 核心逻辑:遍历取第一个图像 -> 赋值给CallBackImg -> 触发事件 -> 释放并移除
        /// </summary>
        private void ProcessCollectedImages()
        {
            Task.Factory.StartNew(() =>
            {
                // 加锁保证线程安全,防止多线程同时操作列表
                lock (_collectedImagesLock)
                {
                    // 校验当前相机的图像列表是否存在且有数据
                    if (!CollectedImages.ContainsKey(SN) || CollectedImages[SN].Count == 0)
                    {
                        AsyncLogHelper.Info(SN + "当前无缓存图像,跳过处理");
                        return;
                    }
                    // 循环处理:直到列表为空
                    while (CollectedImages[SN].Count > 0)
                    {
                        try
                        {
                            // 1 取列表第一个索引的图像赋值给CallBackImg
                            Bitmap firstBitmap = CollectedImages[SN][0];
                            ImageGrabbed?.Invoke(this, new LBCameraEventArgs(SN, firstBitmap, true));
                            CallBackImg = (Bitmap)firstBitmap.Clone(); // 克隆避免原对象被释放后引用失效
                            // 2 获取触发模式并判断是否触发运行事件
                            if (GetTriggerMode(out TriggerMode mode, out TriggerSource source))
                            {
                                // 硬触发模式下触发运行事件
                                if (mode == TriggerMode.On && source != TriggerSource.Software)
                                {
                                    AsyncLogHelper.Info(SN + $"触发硬触发事件,触发源:{source}");
                                    TriggerRunMessageReceived?.Invoke(SN, source.ToString());
                                }
                            }
                            else
                            {
                                AsyncLogHelper.Warn(SN + "获取触发模式失败,跳过事件触发");
                            }
                            // 3 释放第一个图像资源并从列表移除
                            // 先释放Bitmap内存,再移除列表元素
                            firstBitmap.Dispose();
                            CollectedImages[SN].RemoveAt(0);
                            AsyncLogHelper.Info(SN + $"已消费缓存图像,剩余缓存数量:{CollectedImages[SN].Count}");
                        }
                        catch (Exception ex)
                        {
                            AsyncLogHelper.Error(SN + $"处理缓存图像异常:{ex.Message}", ex);
                            // 单个图像处理失败时,移除该图像避免阻塞后续处理
                            if (CollectedImages[SN].Count > 0)
                            {
                                try
                                {
                                    CollectedImages[SN][0]?.Dispose(); // 尝试释放
                                    CollectedImages[SN].RemoveAt(0);
                                }
                                catch (Exception innerEx)
                                {
                                    AsyncLogHelper.Error(SN + $"清理异常图像失败:{innerEx.Message}", innerEx);
                                }
                            }
                            // 单个图像处理失败不终止循环,继续处理下一个
                            // 4. 所有图像处理完成后,清空CallBackImg
                            if (CallBackImg != null)
                            {
                                CallBackImg.Dispose();
                                CallBackImg = null;
                            }
                            continue;
                        }
                        // 4. 所有图像处理完成后,清空CallBackImg
                        if (CallBackImg != null)
                        {
                            CallBackImg.Dispose();
                            CallBackImg = null;
                        }
                    }
                }
            });
        }
        /// <summary>
        /// 图像是否为Mono格式
        /// </summary>
        /// <param name="enType"></param>
LB_VisionProcesses/Cameras/LBCameras/LBCamera.cs
@@ -51,6 +51,8 @@
        // 临时行缓冲,用于接收回调数据
        private byte[] _tempLineBuffer = null;
        private bool _isContinuous = false;
        // 新增:CollectedImages操作锁,保证线程安全
        private readonly object _collectedImagesLock = new object();
        public LBCamera()
        {
@@ -568,37 +570,140 @@
                _frameCount++;
                AsyncLogHelper.Info($"LBCamera[{SN}]: Frame {_frameCount} generated ({width}x{height})");
                // 异步触发事件,避免阻塞SDK回调线程
                Task.Factory.StartNew(() =>
                //空值校验:转换失败则直接返回
                if (bmp == null)
                {
                    try
                    AsyncLogHelper.Warn(SN + "帧转换为Bitmap失败,跳过处理");
                    return;
                }
                // 线程安全地将Bitmap添加到CollectedImages字典
                lock (_collectedImagesLock)
                {
                    // 确保当前相机SN对应的列表存在
                    if (!CollectedImages.ContainsKey(SN))
                    {
                        ImageGrabbed?.Invoke(this, new LBCameraEventArgs(SN, bmp, true));
                        CallBackImg = (Bitmap)bmp.Clone();
                        if (CallBackImg == null)
                        {
                            return;
                        }
                        if (GetTriggerMode(out TriggerMode mode, out TriggerSource source))
                        {
                            if (mode == TriggerMode.On && source != TriggerSource.Software)
                                TriggerRunMessageReceived?.Invoke(SN, source.ToString());  // 触发运行事件
                        }
                        bmp.Dispose();
                        CollectedImages[SN] = new List<Bitmap>();
                    }
                    catch (Exception ex)
                    {
                        AsyncLogHelper.Error($"LBCamera: Event Invoke error - {ex.Message}");
                        bmp.Dispose(); // 异常时释放资源
                    }
                });
                    CollectedImages[SN].Add(bmp);
                    AsyncLogHelper.Info(SN + $"图像已加入缓存,当前缓存数量:{CollectedImages[SN].Count}");
                }
                // 处理CollectedImages中的图像:遍历消费列表第一个元素直到为空
                ProcessCollectedImages();
                //// 异步触发事件,避免阻塞SDK回调线程
                //Task.Factory.StartNew(() =>
                //{
                //    try
                //    {
                //        ImageGrabbed?.Invoke(this, new LBCameraEventArgs(SN, bmp, true));
                //        CallBackImg = (Bitmap)bmp.Clone();
                //        if (CallBackImg == null)
                //        {
                //            return;
                //        }
                //        if (GetTriggerMode(out TriggerMode mode, out TriggerSource source))
                //        {
                //            if (mode == TriggerMode.On && source != TriggerSource.Software)
                //                TriggerRunMessageReceived?.Invoke(SN, source.ToString());  // 触发运行事件
                //        }
                //        bmp.Dispose();
                //    }
                //    catch (Exception ex)
                //    {
                //        AsyncLogHelper.Error($"LBCamera: Event Invoke error - {ex.Message}");
                //        bmp.Dispose(); // 异常时释放资源
                //    }
                //});
            }
            catch (Exception ex)
            {
                AsyncLogHelper.Error($"LBCamera: CreateBitmap error - {ex.Message}");
            }
        }
        /// <summary>
        /// 处理CollectedImages中的缓存图像
        /// 核心逻辑:遍历取第一个图像 -> 赋值给CallBackImg -> 触发事件 -> 释放并移除
        /// </summary>
        private void ProcessCollectedImages()
        {
            Task.Factory.StartNew(() =>
            {
                // 加锁保证线程安全,防止多线程同时操作列表
                lock (_collectedImagesLock)
                {
                    // 校验当前相机的图像列表是否存在且有数据
                    if (!CollectedImages.ContainsKey(SN) || CollectedImages[SN].Count == 0)
                    {
                        AsyncLogHelper.Info(SN + "当前无缓存图像,跳过处理");
                        return;
                    }
                    // 循环处理:直到列表为空
                    while (CollectedImages[SN].Count > 0)
                    {
                        try
                        {
                            // 1 取列表第一个索引的图像赋值给CallBackImg
                            Bitmap firstBitmap = CollectedImages[SN][0];
                            ImageGrabbed?.Invoke(this, new LBCameraEventArgs(SN, firstBitmap, true));
                            CallBackImg = (Bitmap)firstBitmap.Clone(); // 克隆避免原对象被释放后引用失效
                            // 2 获取触发模式并判断是否触发运行事件
                            if (GetTriggerMode(out TriggerMode mode, out TriggerSource source))
                            {
                                // 硬触发模式下触发运行事件
                                if (mode == TriggerMode.On && source != TriggerSource.Software)
                                {
                                    AsyncLogHelper.Info(SN + $"触发硬触发事件,触发源:{source}");
                                    TriggerRunMessageReceived?.Invoke(SN, source.ToString());
                                }
                            }
                            else
                            {
                                AsyncLogHelper.Warn(SN + "获取触发模式失败,跳过事件触发");
                            }
                            // 3 释放第一个图像资源并从列表移除
                            // 先释放Bitmap内存,再移除列表元素
                            firstBitmap.Dispose();
                            CollectedImages[SN].RemoveAt(0);
                            AsyncLogHelper.Info(SN + $"已消费缓存图像,剩余缓存数量:{CollectedImages[SN].Count}");
                        }
                        catch (Exception ex)
                        {
                            AsyncLogHelper.Error(SN + $"处理缓存图像异常:{ex.Message}", ex);
                            // 单个图像处理失败时,移除该图像避免阻塞后续处理
                            if (CollectedImages[SN].Count > 0)
                            {
                                try
                                {
                                    CollectedImages[SN][0]?.Dispose(); // 尝试释放
                                    CollectedImages[SN].RemoveAt(0);
                                }
                                catch (Exception innerEx)
                                {
                                    AsyncLogHelper.Error(SN + $"清理异常图像失败:{innerEx.Message}", innerEx);
                                }
                            }
                            // 单个图像处理失败不终止循环,继续处理下一个
                            // 4. 所有图像处理完成后,清空CallBackImg
                            if (CallBackImg != null)
                            {
                                CallBackImg.Dispose();
                                CallBackImg = null;
                            }
                            continue;
                        }
                        // 4. 所有图像处理完成后,清空CallBackImg
                        if (CallBackImg != null)
                        {
                            CallBackImg.Dispose();
                            CallBackImg = null;
                        }
                    }
                }
            });
        }
        private void SyncConfigFromCamera()
        {
LB_VisionProcesses/Communicators/CommunicatorConfig.cs
@@ -1,4 +1,5 @@
using Newtonsoft.Json;
using LB_SmartVisionCommon;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Collections.Concurrent;
using System.Diagnostics;
@@ -43,12 +44,12 @@
                if (!fullPath.Contains(".json"))
                {
                    Debug.WriteLine("文件路径不完整");
                    AsyncLogHelper.Info("文件路径不完整");
                    return false;
                }
                if (string.IsNullOrEmpty(fullPath) || fullPath.Trim() == "")
                {
                    Debug.WriteLine("文件路径不完整");
                    AsyncLogHelper.Info("文件路径不完整");
                    return false;
                }
@@ -58,7 +59,7 @@
                if (!File.Exists(fullPath))
                {
                    Debug.WriteLine("文件不存在创建空文件");
                    AsyncLogHelper.Info("文件不存在创建空文件");
                    Save(directoryPath);
                    return true;
                }
@@ -90,7 +91,7 @@
            {
                if (string.IsNullOrEmpty(filePath) || filePath.Trim() == "")
                {
                    Debug.WriteLine("文件路径不完整");
                    AsyncLogHelper.Info("文件路径不完整");
                    return false;
                }
LB_VisionProcesses/Communicators/CommunicatorForm.Designer.cs
@@ -37,25 +37,27 @@
            btnConnect = new Button();
            cmbIP = new ComboBox();
            lblIP = new Label();
            lblDataType = new Label();
            cmbDataType = new ComboBox();
            grpReceive = new GroupBox();
            txtReceiveMsg = new TextBox();
            txtSendMsg = new TextBox();
            btnSend = new Button();
            grpTest = new GroupBox();
            lblCom = new Label();
            txtAddress = new TextBox();
            ckbRuleCheck = new CheckBox();
            cmbCom = new ComboBox();
            cmbType = new ComboBox();
            lblType = new Label();
            btnRun = new Button();
            lblAddress = new Label();
            lblMsg = new Label();
            txtMsg = new TextBox();
            btnRuleSend = new Button();
            label6 = new Label();
            themeForm1 = new ReaLTaiizor.Forms.ThemeForm();
            controlBox1 = new ReaLTaiizor.Controls.ControlBox();
            lblAddress = new Label();
            txtAddress = new TextBox();
            grpSetting.SuspendLayout();
            grpReceive.SuspendLayout();
            grpTest.SuspendLayout();
@@ -72,42 +74,48 @@
            grpSetting.Controls.Add(cmbIP);
            grpSetting.Controls.Add(lblIP);
            grpSetting.ForeColor = SystemColors.Control;
            grpSetting.Location = new Point(18, 74);
            grpSetting.Location = new Point(22, 92);
            grpSetting.Margin = new Padding(4);
            grpSetting.Name = "grpSetting";
            grpSetting.Size = new Size(200, 146);
            grpSetting.Padding = new Padding(4);
            grpSetting.Size = new Size(250, 262);
            grpSetting.TabIndex = 0;
            grpSetting.TabStop = false;
            grpSetting.Text = "通讯配置";
            // 
            // txtIP
            // 
            txtIP.Location = new Point(83, 32);
            txtIP.Location = new Point(104, 40);
            txtIP.Margin = new Padding(4);
            txtIP.Name = "txtIP";
            txtIP.Size = new Size(100, 23);
            txtIP.Size = new Size(124, 27);
            txtIP.TabIndex = 7;
            // 
            // txtPort
            // 
            txtPort.Location = new Point(83, 70);
            txtPort.Location = new Point(104, 88);
            txtPort.Margin = new Padding(4);
            txtPort.Name = "txtPort";
            txtPort.Size = new Size(100, 23);
            txtPort.Size = new Size(124, 27);
            txtPort.TabIndex = 6;
            // 
            // lblPort
            // 
            lblPort.AutoSize = true;
            lblPort.Location = new Point(17, 73);
            lblPort.Location = new Point(21, 91);
            lblPort.Margin = new Padding(4, 0, 4, 0);
            lblPort.Name = "lblPort";
            lblPort.Size = new Size(32, 17);
            lblPort.Size = new Size(39, 20);
            lblPort.TabIndex = 4;
            lblPort.Text = "端口";
            // 
            // btnDisconnect
            // 
            btnDisconnect.ForeColor = SystemColors.Control;
            btnDisconnect.Location = new Point(118, 109);
            btnDisconnect.Location = new Point(148, 136);
            btnDisconnect.Margin = new Padding(4);
            btnDisconnect.Name = "btnDisconnect";
            btnDisconnect.Size = new Size(75, 23);
            btnDisconnect.Size = new Size(94, 29);
            btnDisconnect.TabIndex = 3;
            btnDisconnect.Text = "断开";
            btnDisconnect.UseVisualStyleBackColor = true;
@@ -116,9 +124,10 @@
            // btnConnect
            // 
            btnConnect.ForeColor = SystemColors.Control;
            btnConnect.Location = new Point(14, 109);
            btnConnect.Location = new Point(18, 136);
            btnConnect.Margin = new Padding(4);
            btnConnect.Name = "btnConnect";
            btnConnect.Size = new Size(75, 23);
            btnConnect.Size = new Size(94, 29);
            btnConnect.TabIndex = 2;
            btnConnect.Text = "连接";
            btnConnect.UseVisualStyleBackColor = true;
@@ -127,9 +136,10 @@
            // cmbIP
            // 
            cmbIP.FormattingEnabled = true;
            cmbIP.Location = new Point(83, 31);
            cmbIP.Location = new Point(104, 39);
            cmbIP.Margin = new Padding(4);
            cmbIP.Name = "cmbIP";
            cmbIP.Size = new Size(100, 25);
            cmbIP.Size = new Size(124, 28);
            cmbIP.TabIndex = 1;
            cmbIP.Click += cmbIP_Click;
            cmbIP.MouseClick += cmbIP_MouseClick;
@@ -137,19 +147,41 @@
            // lblIP
            // 
            lblIP.AutoSize = true;
            lblIP.Location = new Point(17, 36);
            lblIP.Location = new Point(21, 45);
            lblIP.Margin = new Padding(4, 0, 4, 0);
            lblIP.Name = "lblIP";
            lblIP.Size = new Size(32, 17);
            lblIP.Size = new Size(39, 20);
            lblIP.TabIndex = 0;
            lblIP.Text = "地址";
            //
            // lblDataType
            //
            lblDataType.AutoSize = true;
            lblDataType.Location = new Point(206, 145);
            lblDataType.Margin = new Padding(4, 0, 4, 0);
            lblDataType.Name = "lblDataType";
            lblDataType.Size = new Size(39, 20);
            lblDataType.TabIndex = 8;
            lblDataType.Text = "类型";
            //
            // cmbDataType
            //
            cmbDataType.FormattingEnabled = true;
            cmbDataType.Location = new Point(255, 140);
            cmbDataType.Margin = new Padding(4);
            cmbDataType.Name = "cmbDataType";
            cmbDataType.Size = new Size(94, 28);
            cmbDataType.TabIndex = 9;
            // 
            // grpReceive
            // 
            grpReceive.Controls.Add(txtReceiveMsg);
            grpReceive.ForeColor = SystemColors.Control;
            grpReceive.Location = new Point(18, 311);
            grpReceive.Location = new Point(22, 389);
            grpReceive.Margin = new Padding(4);
            grpReceive.Name = "grpReceive";
            grpReceive.Size = new Size(543, 174);
            grpReceive.Padding = new Padding(4);
            grpReceive.Size = new Size(679, 218);
            grpReceive.TabIndex = 5;
            grpReceive.TabStop = false;
            grpReceive.Text = "通讯记录";
@@ -157,28 +189,31 @@
            // txtReceiveMsg
            // 
            txtReceiveMsg.Dock = DockStyle.Fill;
            txtReceiveMsg.Location = new Point(3, 19);
            txtReceiveMsg.Location = new Point(4, 24);
            txtReceiveMsg.Margin = new Padding(4);
            txtReceiveMsg.Multiline = true;
            txtReceiveMsg.Name = "txtReceiveMsg";
            txtReceiveMsg.ReadOnly = true;
            txtReceiveMsg.ScrollBars = ScrollBars.Both;
            txtReceiveMsg.Size = new Size(537, 152);
            txtReceiveMsg.Size = new Size(671, 190);
            txtReceiveMsg.TabIndex = 0;
            // 
            // txtSendMsg
            // 
            txtSendMsg.ForeColor = SystemColors.WindowText;
            txtSendMsg.Location = new Point(18, 249);
            txtSendMsg.Location = new Point(26, 311);
            txtSendMsg.Margin = new Padding(4);
            txtSendMsg.Name = "txtSendMsg";
            txtSendMsg.Size = new Size(543, 23);
            txtSendMsg.Size = new Size(238, 27);
            txtSendMsg.TabIndex = 10;
            // 
            // btnSend
            // 
            btnSend.ForeColor = SystemColors.WindowText;
            btnSend.Location = new Point(18, 282);
            btnSend.Location = new Point(22, 352);
            btnSend.Margin = new Padding(4);
            btnSend.Name = "btnSend";
            btnSend.Size = new Size(75, 23);
            btnSend.Size = new Size(94, 29);
            btnSend.TabIndex = 11;
            btnSend.Text = "发送";
            btnSend.UseVisualStyleBackColor = true;
@@ -196,10 +231,14 @@
            grpTest.Controls.Add(lblAddress);
            grpTest.Controls.Add(lblMsg);
            grpTest.Controls.Add(txtMsg);
            grpTest.Controls.Add(lblDataType);
            grpTest.Controls.Add(cmbDataType);
            grpTest.ForeColor = SystemColors.Control;
            grpTest.Location = new Point(241, 74);
            grpTest.Location = new Point(301, 92);
            grpTest.Margin = new Padding(4);
            grpTest.Name = "grpTest";
            grpTest.Size = new Size(320, 146);
            grpTest.Padding = new Padding(4);
            grpTest.Size = new Size(400, 262);
            grpTest.TabIndex = 12;
            grpTest.TabStop = false;
            grpTest.Text = "通讯测试";
@@ -207,18 +246,29 @@
            // lblCom
            // 
            lblCom.AutoSize = true;
            lblCom.Location = new Point(165, 40);
            lblCom.Location = new Point(206, 50);
            lblCom.Margin = new Padding(4, 0, 4, 0);
            lblCom.Name = "lblCom";
            lblCom.Size = new Size(32, 17);
            lblCom.Size = new Size(39, 20);
            lblCom.TabIndex = 9;
            lblCom.Text = "通讯";
            //
            // txtAddress
            //
            txtAddress.Location = new Point(74, 140);
            txtAddress.Margin = new Padding(4);
            txtAddress.Name = "txtAddress";
            txtAddress.ReadOnly = true;
            txtAddress.Size = new Size(116, 27);
            txtAddress.TabIndex = 6;
            // 
            // ckbRuleCheck
            // 
            ckbRuleCheck.AutoSize = true;
            ckbRuleCheck.Location = new Point(55, 173);
            ckbRuleCheck.Location = new Point(69, 216);
            ckbRuleCheck.Margin = new Padding(4);
            ckbRuleCheck.Name = "ckbRuleCheck";
            ckbRuleCheck.Size = new Size(99, 21);
            ckbRuleCheck.Size = new Size(121, 24);
            ckbRuleCheck.TabIndex = 6;
            ckbRuleCheck.Text = "是否规则校验";
            ckbRuleCheck.UseVisualStyleBackColor = true;
@@ -226,63 +276,80 @@
            // cmbCom
            // 
            cmbCom.FormattingEnabled = true;
            cmbCom.Location = new Point(204, 35);
            cmbCom.Location = new Point(255, 44);
            cmbCom.Margin = new Padding(4);
            cmbCom.Name = "cmbCom";
            cmbCom.Size = new Size(100, 25);
            cmbCom.Size = new Size(124, 28);
            cmbCom.TabIndex = 8;
            cmbCom.SelectedIndexChanged += cmbCom_SelectedIndexChanged;
            // 
            // cmbType
            // 
            cmbType.FormattingEnabled = true;
            cmbType.Location = new Point(59, 36);
            cmbType.Location = new Point(74, 45);
            cmbType.Margin = new Padding(4);
            cmbType.Name = "cmbType";
            cmbType.Size = new Size(94, 25);
            cmbType.Size = new Size(116, 28);
            cmbType.TabIndex = 5;
            // 
            // lblType
            // 
            lblType.AutoSize = true;
            lblType.Location = new Point(21, 39);
            lblType.Location = new Point(26, 49);
            lblType.Margin = new Padding(4, 0, 4, 0);
            lblType.Name = "lblType";
            lblType.Size = new Size(32, 17);
            lblType.Size = new Size(39, 20);
            lblType.TabIndex = 4;
            lblType.Text = "类型";
            // 
            // btnRun
            // 
            btnRun.ForeColor = SystemColors.WindowText;
            btnRun.Location = new Point(215, 109);
            btnRun.Location = new Point(269, 210);
            btnRun.Margin = new Padding(4);
            btnRun.Name = "btnRun";
            btnRun.Size = new Size(75, 23);
            btnRun.Size = new Size(94, 29);
            btnRun.TabIndex = 3;
            btnRun.Text = "运行测试";
            btnRun.UseVisualStyleBackColor = true;
            btnRun.Click += btnRun_Click;
            // 
            // lblAddress
            //
            lblAddress.AutoSize = true;
            lblAddress.Location = new Point(25, 144);
            lblAddress.Margin = new Padding(4, 0, 4, 0);
            lblAddress.Name = "lblAddress";
            lblAddress.Size = new Size(39, 20);
            lblAddress.TabIndex = 0;
            lblAddress.Text = "地址";
            //
            // lblMsg
            // 
            lblMsg.AutoSize = true;
            lblMsg.Location = new Point(20, 78);
            lblMsg.Location = new Point(25, 98);
            lblMsg.Margin = new Padding(4, 0, 4, 0);
            lblMsg.Name = "lblMsg";
            lblMsg.Size = new Size(32, 17);
            lblMsg.Size = new Size(39, 20);
            lblMsg.TabIndex = 1;
            lblMsg.Text = "消息";
            // 
            // txtMsg
            // 
            txtMsg.Location = new Point(59, 76);
            txtMsg.Location = new Point(74, 95);
            txtMsg.Margin = new Padding(4);
            txtMsg.Name = "txtMsg";
            txtMsg.ReadOnly = true;
            txtMsg.Size = new Size(245, 23);
            txtMsg.Size = new Size(305, 27);
            txtMsg.TabIndex = 0;
            // 
            // btnRuleSend
            // 
            btnRuleSend.ForeColor = SystemColors.WindowText;
            btnRuleSend.Location = new Point(118, 282);
            btnRuleSend.Location = new Point(148, 352);
            btnRuleSend.Margin = new Padding(4);
            btnRuleSend.Name = "btnRuleSend";
            btnRuleSend.Size = new Size(75, 23);
            btnRuleSend.Size = new Size(94, 29);
            btnRuleSend.TabIndex = 13;
            btnRuleSend.Text = "校验发送";
            btnRuleSend.UseVisualStyleBackColor = true;
@@ -292,9 +359,10 @@
            // 
            label6.AutoSize = true;
            label6.ForeColor = SystemColors.Control;
            label6.Location = new Point(18, 223);
            label6.Location = new Point(22, 279);
            label6.Margin = new Padding(4, 0, 4, 0);
            label6.Name = "label6";
            label6.Size = new Size(56, 17);
            label6.Size = new Size(69, 20);
            label6.TabIndex = 9;
            label6.Text = "发送信息";
            // 
@@ -306,11 +374,12 @@
            themeForm1.Font = new Font("Microsoft Sans Serif", 9F);
            themeForm1.Image = (Image)resources.GetObject("themeForm1.Image");
            themeForm1.Location = new Point(0, 0);
            themeForm1.Margin = new Padding(4);
            themeForm1.Name = "themeForm1";
            themeForm1.Padding = new Padding(10, 70, 10, 9);
            themeForm1.Padding = new Padding(12, 88, 12, 11);
            themeForm1.RoundCorners = true;
            themeForm1.Sizable = true;
            themeForm1.Size = new Size(581, 496);
            themeForm1.Size = new Size(726, 620);
            themeForm1.SmartBounds = true;
            themeForm1.StartPosition = FormStartPosition.WindowsDefaultLocation;
            themeForm1.TabIndex = 14;
@@ -326,7 +395,8 @@
            controlBox1.EnableMaximizeButton = false;
            controlBox1.EnableMinimizeButton = false;
            controlBox1.ForeColor = Color.FromArgb(155, 155, 155);
            controlBox1.Location = new Point(481, 18);
            controlBox1.Location = new Point(601, 18);
            controlBox1.Margin = new Padding(4);
            controlBox1.MaximizeHoverColor = Color.FromArgb(74, 74, 74);
            controlBox1.MinimizeHoverColor = Color.FromArgb(63, 63, 65);
            controlBox1.Name = "controlBox1";
@@ -334,28 +404,11 @@
            controlBox1.TabIndex = 0;
            controlBox1.Text = "controlBox1";
            // 
            // lblAddress
            //
            lblAddress.AutoSize = true;
            lblAddress.Location = new Point(20, 115);
            lblAddress.Name = "lblAddress";
            lblAddress.Size = new Size(32, 17);
            lblAddress.TabIndex = 0;
            lblAddress.Text = "地址";
            //
            // txtAddress
            //
            txtAddress.Location = new Point(59, 112);
            txtAddress.Name = "txtAddress";
            txtAddress.ReadOnly = true;
            txtAddress.Size = new Size(94, 23);
            txtAddress.TabIndex = 6;
            //
            // CommunicatorForm
            // 
            AutoScaleDimensions = new SizeF(96F, 96F);
            AutoScaleDimensions = new SizeF(120F, 120F);
            AutoScaleMode = AutoScaleMode.Dpi;
            ClientSize = new Size(581, 496);
            ClientSize = new Size(726, 620);
            Controls.Add(btnRuleSend);
            Controls.Add(grpTest);
            Controls.Add(btnSend);
@@ -365,7 +418,8 @@
            Controls.Add(grpSetting);
            Controls.Add(themeForm1);
            FormBorderStyle = FormBorderStyle.None;
            MinimumSize = new Size(261, 61);
            Margin = new Padding(4);
            MinimumSize = new Size(326, 76);
            Name = "CommunicatorForm";
            Text = "通讯测试";
            TransparencyKey = Color.Fuchsia;
@@ -412,5 +466,7 @@
        private ReaLTaiizor.Controls.ControlBox controlBox1;
        private TextBox txtAddress;
        private Label lblAddress;
        private Label lblDataType;
        private ComboBox cmbDataType;
    }
}
LB_VisionProcesses/Communicators/CommunicatorForm.cs
@@ -56,11 +56,26 @@
        private void CommunicatorForm_Load(object sender, EventArgs e)
        {
            // 初始化数据类型
            cmbDataType.Items.Clear();
            cmbDataType.Items.AddRange(new string[] { "String", "Bool", "Byte", "Int", "DInt", "Real", "Double", "Word", "DWord" });
            // 绑定索引改变事件
            cmbDataType.SelectedIndexChanged += (s, ev) =>
            {
                if (communicator != null)
                {
                    communicator.CommunicatorConnections.Add("数据类型", cmbDataType.Text);
                }
            };
            // 使用 Enum.GetValues 获取 enum 类型的所有值
            foreach (CommunicatorType type in Enum.GetValues(typeof(CommunicatorType)))
            {
                cmbType.Items.Add(type.ToString());
            }
            // ... (保持不变)
            //选择Com会触发ValueChanged事件,没有输入通讯口的情况下选择到-1
            if (comConfig != null)
@@ -118,10 +133,13 @@
                txtIP.Visible = false;
                this.lblAddress.Visible = false;
                this.txtAddress.Visible = false;
                this.lblDataType.Visible = false;
                this.cmbDataType.Visible = false;
                lblIP.Text = "串口号";
                lblIP.Text = "波特率";
                lblIP.Text = "波特率"; // Bug: 这里 lblPort 应该被设置为 "波特率",但原代码复用了 lblIP? 不,lblIP.Text被设了两次。
                lblPort.Text = "波特率"; // 修正原代码的潜在Bug
                cmbIP.Text = communicator.CommunicatorConnections["地址"].ToString();
                txtPort.Text = communicator.CommunicatorConnections["端口"].ToString();
@@ -136,10 +154,12 @@
                txtIP.Visible = true;
                this.lblAddress.Visible = false;
                this.txtAddress.Visible = false;
                this.lblDataType.Visible = false;
                this.cmbDataType.Visible = false;
                lblIP.Text = "监控文件";
                lblIP.Text = "写入文件";
                lblPort.Text = "写入文件"; // 修正原代码可能的错误
                txtIP.Text = communicator.CommunicatorConnections["地址"].ToString();
                txtPort.Text = communicator.CommunicatorConnections["端口"].ToString();
@@ -153,12 +173,21 @@
                txtIP.Visible = true;
                this.lblAddress.Visible = true;
                this.txtAddress.Visible = true;
                this.lblDataType.Visible = true;
                this.cmbDataType.Visible = true;
                lblIP.Text = "IP";
                lblIP.Text = "槽";
                lblPort.Text = "槽"; // 原代码这里是 lblIP.Text="槽" 覆盖了 "IP"
                txtIP.Text = communicator.CommunicatorConnections["地址"].ToString();
                txtPort.Text = communicator.CommunicatorConnections["端口"].ToString();
                this.txtAddress.Text = communicator.CommunicatorConnections["变量地址"]?.ToString();
                if (communicator.CommunicatorConnections.Contains("数据类型"))
                    this.cmbDataType.Text = communicator.CommunicatorConnections["数据类型"].ToString();
                else
                    this.cmbDataType.Text = "String";
                this.grpSetting.ForeColor = SystemColors.Control;
                btnRuleSend.Visible = false;
            }
@@ -168,12 +197,14 @@
                btnRuleSend.Enabled = false;
                this.lblAddress.Visible = false;
                this.txtAddress.Visible = false;
                this.lblDataType.Visible = false;
                this.cmbDataType.Visible = false;
                cmbIP.Visible = false;
                txtIP.Visible = true;
                lblIP.Text = " IP";
                lblIP.Text = "端口";
                lblPort.Text = "端口";
                txtIP.Text = communicator.CommunicatorConnections["地址"].ToString();
                txtPort.Text = communicator.CommunicatorConnections["端口"].ToString();
@@ -198,6 +229,13 @@
            {
                communicator.CommunicatorConnections.Add("地址", cmbIP.SelectedItem.ToString());
                communicator.CommunicatorConnections.Add("端口", txtPort.Text);
            }
            else if (communicator is SiemensLBS7)
            {
                communicator.CommunicatorConnections.Add("地址", txtIP.Text);
                communicator.CommunicatorConnections.Add("端口", txtPort.Text);
                communicator.CommunicatorConnections.Add("变量地址", txtAddress.Text);
                communicator.CommunicatorConnections.Add("数据类型", cmbDataType.Text);
            }
            else
            {
@@ -263,14 +301,37 @@
            MessageBox.Show(result ? "断开成功" : "断开失败,原因是:" + communicator.Msg);
        }
        private void ShowLogMsg(string msg)
        {
            // 如果当前不是 UI 线程,则通过 Invoke 将操作调度到 UI 线程
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<string>((message) =>
                {
                    this.txtReceiveMsg.AppendText("[" + DateTime.Now.ToString("HH:mm:ss.fff") + "] " + message + "\r\n");
                    this.txtReceiveMsg.ScrollToCaret();
                }), msg);
            }
            else
            {
                this.txtReceiveMsg.AppendText("[" + DateTime.Now.ToString("HH:mm:ss.fff") + "] " + msg + "\r\n");
                this.txtReceiveMsg.ScrollToCaret();
            }
        }
        private void btnSend_Click(object sender, EventArgs e)
        {
            if (communicator == null)
                return;
            communicator.SendMessage(txtSendMsg.Text);
            ShowSendMsg(txtSendMsg.Text);
            if (communicator.SendMessage(txtSendMsg.Text))
            {
                ShowSendMsg(txtSendMsg.Text);
            }
            else
            {
                ShowLogMsg(communicator.Msg);
            }
        }
        private void btnRuleSend_Click(object sender, EventArgs e)
@@ -287,7 +348,14 @@
            //HexByte = strToHexByte(strSendMsg + crcString);
            SendMsg = SendMsg + crcString;
            communicator.SendMessage(SendMsg);
            if (communicator.SendMessage(SendMsg))
            {
                ShowSendMsg(SendMsg);
            }
            else
            {
                ShowLogMsg(communicator.Msg);
            }
        }
        private void btnRun_Click(object sender, EventArgs e)
LB_VisionProcesses/Communicators/CommunicatorForm.resx
@@ -121,7 +121,7 @@
  <data name="themeForm1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
    <value>
        iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
        wQAADsEBuJFr7QAAA+JJREFUWEftVkuIHGUQbt34iMEoq2S2q3p3yTJsuqpnJ+L6WBRdwaigohfFgEou
        vgAADr4B6kKxwAAAA+JJREFUWEftVkuIHGUQbt34iMEoq2S2q3p3yTJsuqpnJ+L6WBRdwaigohfFgEou
        BkVBUPCBCEG8BXNQ48GLeImCehIJxMsqhsSZruod46K4HtSIGjU+4iOr0c1I9fSsM3/PLNtCPO0H36m/
        evz/X11VnreKVRTAHPOZumkY6lFwqURws3BwZ8ywTQnuiCP/+iTCzY1qaUPzdm/Atf3PaHre6XPsjyQM
        2xLGV4XwIyX4QRj+UMK/lPFvJTyhBMeV8IgQvmRJuH4Ko+l5p9UjGBbCJ5RxTgj+VMZmXxKcSAjekHE/
LB_VisionProcesses/Communicators/SiemensS7/SiemensLBS7.cs
@@ -1,45 +1,103 @@
using LB_SmartVisionCommon;
using LB_SmartVisionCommon;
using S7.Net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using System.Threading;
namespace LB_VisionProcesses.Communicators.SiemensS7
{
    public class SiemensLBS7 : BaseCommunicator
    {
        private Plc plc;
        public string variable = string.Empty;
        /// <summary>
        ///
        /// </summary>
        /// <param name="name"></param>
        public SiemensLBS7(string name = "西门子S7")
        // 默认变量地址
        public string variable = "DB1.DBD0";
        // 数据类型
        private string dataType = "String";
        // 缓存连接参数
        private string ip = "127.0.0.1";
        private short rack = 0;
        private short slot = 1;
        private CpuType cpuType = CpuType.S71500;
        public SiemensLBS7(string name = "西门子S7") : base(name)
        {
            CommunicatorConnections.Add("地址", "127.0.0.1");
            CommunicatorConnections.Add("端口", "1");
            CommunicatorConnections.Add("型号", S7.Net.CpuType.S71500);
            CommunicatorBrand = CommunicatorBrand.SiemensS7;
            CommunicatorName = name;
            CommunicatorBrand = CommunicatorBrand.SiemensS7;
            // 初始化默认参数
            if (!CommunicatorConnections.Contains("地址")) CommunicatorConnections.Add("地址", "192.168.0.1");
            if (!CommunicatorConnections.Contains("机架号")) CommunicatorConnections.Add("机架号", "0");
            if (!CommunicatorConnections.Contains("插槽号")) CommunicatorConnections.Add("插槽号", "1");
            if (!CommunicatorConnections.Contains("型号")) CommunicatorConnections.Add("型号", CpuType.S71500);
            if (!CommunicatorConnections.Contains("变量地址")) CommunicatorConnections.Add("变量地址", "DB1.DBD0");
            if (!CommunicatorConnections.Contains("数据类型")) CommunicatorConnections.Add("数据类型", "String");
            // 兼容旧配置 "端口"
            if (CommunicatorConnections.Contains("端口"))
            {
                CommunicatorConnections["插槽号"] = CommunicatorConnections["端口"];
            }
            // 设置默认心跳消息
            strHeartbeat = "HEARTBEAT";
        }
        public override bool Connect()
        {
            try
            {
                string IP = CommunicatorConnections["地址"].ToString();
                short slot;
                short.TryParse(CommunicatorConnections["端口"].ToString(), out slot);
                S7.Net.CpuType cpuType = (CpuType)CommunicatorConnections["型号"];
                variable = CommunicatorConnections["变量地址"].ToString();
                plc = new Plc(cpuType, IP, 0, slot);
                plc.Open();
                return true;
                // 更新参数
                if (CommunicatorConnections.Contains("地址")) ip = CommunicatorConnections["地址"].ToString();
                if (CommunicatorConnections.Contains("机架号"))
                    short.TryParse(CommunicatorConnections["机架号"].ToString(), out rack);
                if (CommunicatorConnections.Contains("插槽号"))
                    short.TryParse(CommunicatorConnections["插槽号"].ToString(), out slot);
                else if (CommunicatorConnections.Contains("端口"))
                    short.TryParse(CommunicatorConnections["端口"].ToString(), out slot);
                if (CommunicatorConnections.Contains("型号"))
                {
                    if (CommunicatorConnections["型号"] is CpuType type)
                        cpuType = type;
                    else
                        Enum.TryParse(CommunicatorConnections["型号"].ToString(), out cpuType);
                }
                if (CommunicatorConnections.Contains("变量地址"))
                    variable = CommunicatorConnections["变量地址"].ToString();
                if (CommunicatorConnections.Contains("数据类型"))
                    dataType = CommunicatorConnections["数据类型"].ToString();
                // 关闭旧连接
                plc?.Close();
                plc = new Plc(cpuType, ip, rack, slot);
                plc.Open();
                if (plc.IsConnected)
                {
                    bConnected = true;
                    AsyncLogHelper.Info($"Device:[{CommunicatorName}] 已连接到 {ip} 机架:{rack} 插槽:{slot}");
                    return true;
                }
                else
                {
                    bConnected = false;
                    AsyncLogHelper.Error($"Device:[{CommunicatorName}] 连接失败: IsConnected 为 false");
                    return false;
                }
            }
            catch
            catch (Exception ex)
            {
                bConnected = false;
                AsyncLogHelper.Error($"Device:[{CommunicatorName}] 连接错误: {ex.Message}");
                return false;
            }
        }
@@ -48,7 +106,223 @@
        {
            try
            {
                plc?.Close();
                if (plc != null)
                {
                    plc.Close();
                    bConnected = false;
                    AsyncLogHelper.Info($"Device:[{CommunicatorName}] 已断开连接");
                }
                return true;
            }
            catch (Exception ex)
            {
                AsyncLogHelper.Error($"Device:[{CommunicatorName}] 断开连接错误: {ex.Message}");
                return false;
            }
        }
        public override bool SendMessage(string message)
        {
            if (plc == null || !plc.IsConnected)
            {
                Msg = "连接未开启";
                return false;
            }
            if (message == strHeartbeat) return plc.IsConnected;
            try
            {
                string targetVar = variable;
                string strValue = message;
                // 简单的协议解析:地址:值
                if (message.Contains(":"))
                {
                    var parts = message.Split(new char[] { ':' }, 2);
                    if (parts.Length == 2 && !string.IsNullOrWhiteSpace(parts[0]))
                    {
                        targetVar = parts[0];
                        strValue = parts[1];
                    }
                }
                object valueToWrite = strValue;
                // 获取当前数据类型配置
                string currentDataType = CommunicatorConnections.Contains("数据类型") ? CommunicatorConnections["数据类型"].ToString() : "String";
                // 根据配置的数据类型进行转换
                try
                {
                    switch (currentDataType)
                    {
                        case "Bool":
                            if (strValue == "1") valueToWrite = true;
                            else if (strValue == "0") valueToWrite = false;
                            else valueToWrite = bool.Parse(strValue);
                            break;
                        case "Byte":
                            valueToWrite = byte.Parse(strValue);
                            break;
                        case "Int": // 16-bit
                            valueToWrite = short.Parse(strValue);
                            break;
                        case "DInt": // 32-bit
                            valueToWrite = int.Parse(strValue);
                            break;
                        case "Word": // 16-bit unsigned
                            valueToWrite = ushort.Parse(strValue);
                            break;
                        case "DWord": // 32-bit unsigned
                            valueToWrite = uint.Parse(strValue);
                            break;
                        case "Real": // Float
                            valueToWrite = float.Parse(strValue);
                            break;
                        case "Double": // LReal
                            valueToWrite = double.Parse(strValue);
                            break;
                        case "String":
                        default:
                            valueToWrite = strValue;
                            break;
                    }
                }
                catch (FormatException)
                {
                    Msg = $"无效的{currentDataType}值,请输入正确格式。";
                    if (currentDataType == "Bool") Msg += " (true/false 或 1/0)";
                    AsyncLogHelper.Error($"Device:[{CommunicatorName}] {Msg}");
                    return false;
                }
                catch (Exception castEx)
                {
                    Msg = $"数据转换错误({currentDataType}): {castEx.Message}";
                    AsyncLogHelper.Error($"Device:[{CommunicatorName}] {Msg}");
                    return false;
                }
                // 尝试写入
                plc.Write(targetVar, valueToWrite);
                AsyncLogHelper.Info($"Device:[{CommunicatorName}] 写入({currentDataType}) {targetVar} = {valueToWrite}");
                return true;
            }
            catch (Exception ex)
            {
                Msg = $"发送消息错误: {ex.Message}";
                AsyncLogHelper.Error($"Device:[{CommunicatorName}] {Msg}");
                return false;
            }
        }
        public override string ReceiveMsg()
        {
            if (plc == null || !plc.IsConnected) return string.Empty;
            try
            {
                // 获取当前数据类型配置
                string currentDataType = CommunicatorConnections.Contains("数据类型") ? CommunicatorConnections["数据类型"].ToString() : "String";
                if (currentDataType == "String")
                {
                    var match = Regex.Match(variable, @"DB(\d+)\.DB[B|W|D|X]?(\d+)", RegexOptions.IgnoreCase);
                    if (match.Success)
                    {
                        try
                        {
                            int db = int.Parse(match.Groups[1].Value);
                            int startByte = int.Parse(match.Groups[2].Value);
                            // 读取头部 (MaxLen, ActLen)
                            byte[] header = plc.ReadBytes(DataType.DataBlock, db, startByte, 2);
                            if (header != null && header.Length >= 2)
                            {
                                int actLen = header[1];
                                if (actLen > 0)
                                {
                                    // 读取实际字符数据
                                    byte[] strBytes = plc.ReadBytes(DataType.DataBlock, db, startByte + 2, actLen);
                                    strReceiveMsg = Encoding.ASCII.GetString(strBytes);
                                    return strReceiveMsg;
                                }
                                else
                                {
                                    strReceiveMsg = string.Empty;
                                    return strReceiveMsg;
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            AsyncLogHelper.Error($"Device:[{CommunicatorName}] 读取S7String失败: {ex.Message}");
                        }
                    }
                    // 如果正则不匹配或读取失败,回退到默认读取
                }
                var result = plc.Read(variable);
                if (result != null)
                {
                    // 尝试根据 dataType 格式化输出 (S7.Net 读出来的类型可能与预期不符,特别是 DWord/Real)
                    // 例如 DBD0 默认读出来是 UInt32,如果 dataType 是 Real,需要转换
                    if (currentDataType == "Real" && (result is uint || result is int))
                    {
                        byte[] bytes = BitConverter.GetBytes(Convert.ToUInt32(result));
                        float f = BitConverter.ToSingle(bytes, 0);
                        strReceiveMsg = f.ToString();
                    }
                    else
                    {
                        strReceiveMsg = result.ToString();
                    }
                    return strReceiveMsg;
                }
            }
            catch (Exception ex)
            {
                AsyncLogHelper.Error($"Device:[{CommunicatorName}] 接收消息错误: {ex.Message}");
            }
            return string.Empty;
        }
        /// <summary>
        /// 带填充的 S7 字符串写入,防止残留数据
        /// </summary>
        private bool WriteS7StringWithPadding(string address, string value)
        {
            try
            {
                // 解析地址,例如 DB1.DBB0, DB1.DBD0
                var match = Regex.Match(address, @"DB(\d+)\.DB[B|W|D|X]?(\d+)", RegexOptions.IgnoreCase);
                if (!match.Success) return false;
                int db = int.Parse(match.Groups[1].Value);
                int startByte = int.Parse(match.Groups[2].Value);
                byte maxLen = 254; // 默认最大值
                try
                {
                    var header = plc.ReadBytes(DataType.DataBlock, db, startByte, 1);
                    if (header != null && header.Length > 0 && header[0] > 0)
                    {
                        maxLen = header[0];
                    }
                }
                catch { }
                byte[] buffer = new byte[maxLen + 2];
                buffer[0] = maxLen;
                int currentLen = Math.Min(value.Length, maxLen);
                buffer[1] = (byte)currentLen;
                if (currentLen > 0)
                {
                    byte[] strBytes = Encoding.ASCII.GetBytes(value);
                    Array.Copy(strBytes, 0, buffer, 2, Math.Min(strBytes.Length, currentLen));
                }
                plc.WriteBytes(DataType.DataBlock, db, startByte, buffer);
                return true;
            }
            catch
@@ -56,45 +330,31 @@
                return false;
            }
        }
        public override bool SendMessage(string message)
        public object Read(string address)
        {
            try
            {
                if (plc!=null)
                {
                    if (string.IsNullOrEmpty(variable))
                    {
                        variable = CommunicatorConnections["变量地址"].ToString();
                    }
                    plc.Write(variable, message);
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch
            {
                return false;
            }
             if (plc == null || !plc.IsConnected) return null;
             return plc.Read(address);
        }
        public void Write(string address, object value)
        {
             if (plc != null && plc.IsConnected)
                plc.Write(address, value);
        }
        public override void Dispose()
        {
            try
            {
                AsyncLogHelper.Info($"Device:[{CommunicatorName}],Dispose()");
                AsyncLogHelper.Info($"Device:[{CommunicatorName}],释放资源(Dispose)");
                plc?.Close();
                plc = null;
                // Suppress finalization.
                GC.SuppressFinalize(this);
            }
            catch (Exception ex)
            {
                AsyncLogHelper.Error($"Device:[{CommunicatorName}],Dispose(),Error" + ex);
                AsyncLogHelper.Error($"Device:[{CommunicatorName}],释放资源(Dispose)错误: " + ex.Message);
            }
        }
    }