C3032
2026-01-08 37aff9db0932e3e274b3c26650060f7d2d336888
LB_VisionProcesses/Cameras/2DCameraForm.cs
@@ -80,9 +80,23 @@
        private System.Windows.Forms.Timer updateTimer;
        Total total = new Total { iImageCount = 0, iScanCount = 0 };
        DateTime startGrabtime = DateTime.Now;
        // 动态添加的增益下拉框
        private ComboBox cmbGain;
        private void CameraForm_Load(object sender, EventArgs e)
        {
            // 初始化增益下拉框
            cmbGain = new ComboBox();
            cmbGain.Visible = false; // 默认隐藏
            cmbGain.DropDownStyle = ComboBoxStyle.DropDownList;
            cmbGain.Size = txtGain.Size;
            cmbGain.Location = txtGain.Location;
            cmbGain.Font = txtGain.Font;
            cmbGain.SelectedIndexChanged += CmbGain_SelectedIndexChanged;
            this.txtGain.Parent.Controls.Add(cmbGain);
            cmbGain.BringToFront();
            // 设置一个定时器,每 100 毫秒触发一次
            updateTimer = new System.Windows.Forms.Timer();
            updateTimer.Interval = 1000;  // 设置定时器间隔为 1000 毫秒
@@ -124,6 +138,16 @@
                if (camConfig.OutputImage != null && camConfig.OutputImage is Bitmap bitmap)
                    onlinePictureBox.Image = bitmap;
                lblCapTime.Text = $"{camConfig.RunTime}ms";
            }
        }
        private void CmbGain_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (camera != null && camera is LBCamera && cmbGain.Visible)
            {
                // LBCamera SetGain expects double which is cast to int for enum value
                // ComboBox index corresponds directly to EnumAnalogGain value (0-4)
                camera.SetGain((double)cmbGain.SelectedIndex);
            }
        }
@@ -232,42 +256,71 @@
            // 尝试将输入字符串转换为枚举值
            if (Enum.TryParse(cmbBrand.Text, true, out CameraBrand brand))
            {
                if (camera != null)
                string selectedSN = cmbSN.Text.ToString();
                bool isReusingExisting = false;
                // 1. 尝试从现有字典中查找已初始化的相机
                if (dicCameras != null && dicCameras.ContainsKey(selectedSN))
                {
                    var existingCamera = dicCameras[selectedSN];
                    // 确保品牌匹配
                    if (existingCamera.Brand == brand)
                    {
                        camera = existingCamera;
                        isReusingExisting = true;
                    }
                }
                // 2. 如果没有复用现有相机,且当前camera对象不是我们要复用的对象,则清理旧对象
                if (!isReusingExisting && camera != null)
                {
                    camera.ImageGrabbed -= GetImageBllComplete;
                    camera.Dispose();
                    camera = null;
                }
                // 使用 switch 语句来判断枚举值
                switch (brand)
                // 3. 如果没有复用,则创建新实例
                if (!isReusingExisting)
                {
                    case CameraBrand.LBCamera:
                        camera = new LBCamera();
                        break;
                    case CameraBrand.HRCamera:
                        camera = new HRCamera();
                        break;
                    default:
                        Debug.WriteLine($"【{DateTime.Now:HH:mm:ss.fff}】未知品牌");
                        return;
                    // 使用 switch 语句来判断枚举值
                    switch (brand)
                    {
                        case CameraBrand.LBCamera:
                            camera = new LBCamera();
                            break;
                        case CameraBrand.HRCamera:
                            camera = new HRCamera();
                            break;
                        default:
                            Debug.WriteLine($"【{DateTime.Now:HH:mm:ss.fff}】未知品牌");
                            return;
                    }
                }
                IntPtr displayHandle = onlinePictureBox.Handle;
                if (brand == CameraBrand.LBCamera)
                onlinePictureBox.Visible = true;
                bool initSuccess = false;
                if (isReusingExisting)
                {
                    onlinePictureBox.Visible = false;
                    displayHandle = this.panel_Picture.Handle;
                    // 复用时不需要再次InitDevice,但可能需要更新显示句柄(视具体SDK实现而定,LBCamera通常不需要)
                    initSuccess = true;
                    MessageBox.Show(camera.SN + "已连接 (复用)");
                }
                else
                {
                    onlinePictureBox.Visible = true;
                    if (cmbSN.Items.Count > 0 && camera.InitDevice(selectedSN, displayHandle))
                    {
                        initSuccess = true;
                        MessageBox.Show(camera.SN + "打开成功");
                    }
                }
                if (cmbSN.Items.Count > 0 && camera.InitDevice(cmbSN.Text.ToString(), displayHandle))
                if (initSuccess)
                {
                    // 重新绑定显示回调
                    camera.ImageGrabbed -= GetImageBllComplete;
                    camera.ImageGrabbed += GetImageBllComplete;
                    MessageBox.Show(camera.SN + "打开成功");
                    this.btnEdit.Enabled = true;
                }
            }
@@ -275,18 +328,51 @@
            {
                Debug.WriteLine($"【{DateTime.Now:HH:mm:ss.fff}】无效的枚举值!");
            }
            // ... (rest of the UI update logic)
            if (camera != null)
            {
                this.BeginInvoke(new Action(() =>
                {
                    double exp = 0;
                    double gain = 0;
                    camera.GetExpouseTime(out exp);
                    txtExp.Text = exp.ToString();
                    if (camera is LBCamera lbCam)
                    {
                        // 切换到下拉框显示
                        txtGain.Visible = false;
                        cmbGain.Visible = true;
                        // 填充选项 (对应 EnumAnalogGain: Gain_1_0, Gain_1_3, Gain_1_9, Gain_2_8, Gain_5_5)
                        cmbGain.Items.Clear();
                        cmbGain.Items.AddRange(new object[] { "1.0x", "1.3x", "1.9x", "2.8x", "5.5x" });
                    camera.GetGain(out gain);
                    txtGain.Text = gain.ToString();
                        var config = lbCam.GetSensorConfig();
                        txtExp.Text = config.ExposureTime.ToString();
                        // 设置当前选中的增益
                        int gainIndex = (int)config.AnalogGain;
                        if (gainIndex >= 0 && gainIndex < cmbGain.Items.Count)
                        {
                            cmbGain.SelectedIndex = gainIndex;
                        }
                        else
                        {
                            cmbGain.SelectedIndex = 0;
                        }
                    }
                    else
                    {
                        // 恢复文本框显示
                        txtGain.Visible = true;
                        cmbGain.Visible = false;
                        double exp = 0;
                        double gain = 0;
                        camera.GetExpouseTime(out exp);
                        txtExp.Text = exp.ToString();
                        camera.GetGain(out gain);
                        txtGain.Text = gain.ToString();
                    }
                    camera.GetTriggerMode(out TriggerMode mode, out TriggerSource source);
@@ -402,18 +488,7 @@
        /// <param name="image"></param>
        private void GetImageBllComplete(object sender, CameraEventArgs e)
        {
            // 对于LBCamera(SDK自动显示模式),Bitmap为null,我们只需要统计
            if (camera.Brand == CameraBrand.LBCamera)
            {
                if (e is LBCameraEventArgs args && args.IsComplete)
                {
                    total.iImageCount++;
                    // 不需要更新onlinePictureBox.Image,SDK会自动显示
                }
                return;
            }
            // 对于2D相机(手动处理模式)
            // 对于2D相机(手动处理模式)和现在的LBCamera(手动处理模式)
            if (e.Bitmap == null)
                return;
@@ -466,89 +541,47 @@
                if (success)
                {
                    // 对于LBCamera(SDK自动显示模式),等待采集完成即可
                    // 对于2D相机,等待Bitmap事件
                    if (camera.Brand == CameraBrand.LBCamera)
                    // 等待图像数据
                    using (AutoResetEvent waitHandle = new AutoResetEvent(false))
                    {
                        // SDK自动显示模式下,等待采集完成
                        using (AutoResetEvent waitHandle = new AutoResetEvent(false))
                        Bitmap captured = null;
                        EventHandler<CameraEventArgs> handler = (s, evt) =>
                        {
                            bool captured = false;
                            EventHandler<CameraEventArgs> handler = (s, evt) =>
                            if (evt.Bitmap != null)
                            {
                                if (evt is LBCameraEventArgs args && args.IsComplete)
                                {
                                    captured = true;
                                    waitHandle.Set();
                                }
                            };
                            camera.ImageGrabbed += handler;
                            try
                            {
                                // 等待5秒超时
                                if (waitHandle.WaitOne(5000))
                                {
                                    // SDK自动显示模式,不返回Bitmap
                                    // 但采集已完成
                                }
                                this.BeginInvoke(new Action(() =>
                                {
                                    this.lblCapTime.Text = $"{(DateTime.Now - StartTime).TotalMilliseconds}ms";
                                }));
                                captured = evt.Bitmap.Clone() as Bitmap;
                                waitHandle.Set();
                            }
                            finally
                        };
                        camera.ImageGrabbed += handler;
                        try
                        {
                            // 等待5秒超时
                            if (waitHandle.WaitOne(5000))
                            {
                                camera.ImageGrabbed -= handler;
                                camera.StopGrabbing();
                                bitmap = captured;
                            }
                        }
                    }
                    else
                    {
                        // 对于2D相机,等待图像数据
                        using (AutoResetEvent waitHandle = new AutoResetEvent(false))
                        finally
                        {
                            Bitmap captured = null;
                            EventHandler<CameraEventArgs> handler = (s, evt) =>
                            {
                                // 对于2D相机,直接接收图像
                                if (!(evt is LBCameraEventArgs) && evt.Bitmap != null)
                                {
                                    captured = evt.Bitmap.Clone() as Bitmap;
                                    waitHandle.Set();
                                }
                            };
                            camera.ImageGrabbed += handler;
                            try
                            {
                                // 等待5秒超时
                                if (waitHandle.WaitOne(5000))
                                {
                                    bitmap = captured;
                                }
                            }
                            finally
                            {
                                camera.ImageGrabbed -= handler;
                                camera.StopGrabbing();
                            }
                            camera.ImageGrabbed -= handler;
                            camera.StopGrabbing();
                        }
                        this.BeginInvoke(new Action(() =>
                        {
                            if (bitmap != null)
                            {
                                this.lblCapTime.Text = $"{(DateTime.Now - StartTime).TotalMilliseconds}ms";
                                onlinePictureBox.Image = bitmap;
                            }
                            else
                            {
                                this.lblCapTime.Text = "-1ms";
                            }
                        }));
                    }
                    this.BeginInvoke(new Action(() =>
                    {
                        if (bitmap != null)
                        {
                            this.lblCapTime.Text = $"{(DateTime.Now - StartTime).TotalMilliseconds}ms";
                            onlinePictureBox.Image = bitmap;
                        }
                        else
                        {
                            this.lblCapTime.Text = "-1ms";
                        }
                    }));
                }
                else
                {
@@ -683,7 +716,8 @@
        private void txtGain_TextChanged(object sender, EventArgs e)
        {
            if (camera == null)
            // 如果正在使用下拉框模式(LBCamera),忽略文本框的变化
            if (camera == null || (cmbGain != null && cmbGain.Visible))
                return;
            double gain = 10;
@@ -785,19 +819,25 @@
            if (camera != null)
            {
                camera.ImageGrabbed -= GetImageBllComplete;
                camera.StopGrabbing();
                // 检查该相机是否由主系统管理
                bool isManagedBySystem = dicCameras != null && dicCameras.ContainsKey(camera.SN);
                camera.GetTriggerMode(out _, out TriggerSource actualSource);
                if (radioButtonSoft.Checked)
                    camera.SetTriggerMode(TriggerMode.On, TriggerSource.Software);
                else
                    camera.SetTriggerMode(TriggerMode.On, actualSource);
                // LBCamera在StartGrabbing时会直接开启激光和采集,因此关闭窗口时不应自动重启采集
                // 其他相机(如2D相机)通常需要保持Grabbing状态以接收触发
                if (camera.Brand != CameraBrand.LBCamera)
                if (!isManagedBySystem)
                {
                    camera.StartGrabbing();
                    // 只有非托管的(临时打开的)相机才停止采集和释放
                    camera.StopGrabbing();
                    camera.GetTriggerMode(out _, out TriggerSource actualSource);
                    if (radioButtonSoft.Checked)
                        camera.SetTriggerMode(TriggerMode.On, TriggerSource.Software);
                    else
                        camera.SetTriggerMode(TriggerMode.On, actualSource);
                    if (camera.Brand != CameraBrand.LBCamera)
                    {
                        camera.StartGrabbing();
                    }
                }
            }