using Cognex.VisionPro; using Cognex.VisionPro.ImageFile; using Cognex.VisionPro3D; using log4net.Core; using MahApps.Metro.Controls; using Prism.Events; using Prism.Ioc; using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Forms.Integration; using System.Windows.Interop; using TeamAAS_VP; using TeamAAS_VP.Core; using TeamAAS_VP.Enums; using TeamAAS_VP.Events; using TeamAAS_VP.Interfaces; using TeamAAS_VP.Models; using TeamAAS_VP.Resources.Languages; using TeamAAS_VP.ViewModels; using TeamAAS_VP.ViewModels.Home; //using static MaterialDesignThemes.Wtf.ToolBar; namespace TeamAAS_VP.Views.Home { /// /// Interaction logic for ShowVisionRender /// public partial class ShowVisionRender : UserControl { private const string Render2DKeySuffix = ":2D"; private const string Render3DKeySuffix = ":3D"; private static string Get2DKey(Guid id) => id.ToString() + Render2DKeySuffix; private static string Get3DKey(Guid id) => id.ToString() + Render3DKeySuffix; ShowVisionRenderViewModel viewModel; Dictionary vmRenders; Dictionary Titles; IEventAggregator _eventAggregator; private readonly IProductService _productService; private readonly Prism.Services.Dialogs.IDialogService _dialogService; public ShowVisionRender() { InitializeComponent(); vmRenders = new Dictionary(); Titles = new Dictionary(); viewModel = DataContext as ShowVisionRenderViewModel; _eventAggregator = viewModel._eventAggregator; _productService = ((Prism.PrismApplicationBase)App.Current).Container.Resolve(); // 新增:DialogService _dialogService = ((Prism.PrismApplicationBase)App.Current).Container.Resolve(); viewModel.UpdateLayout += ViewModel_UpdateLayout; _eventAggregator.GetEvent().Subscribe(UpdateRenderModuleSource); _eventAggregator.GetEvent().Subscribe(ProductChanged); } private bool GetView3DUse() { try { var configService = ((Prism.PrismApplicationBase)App.Current).Container.Resolve(); if(configService.GetSystemConfiguration().PickPointNum==0) { return false; } else { return true; } //return true; } catch { return false; } } private void UpdateRenderModuleSource(ShowRender render) { //foreach (var item in vmRenders) //{ // if (item.Key== render.Id) // { // App.Current.Dispatcher.Invoke(new Action(() => // { // item.Value.ModuleSource = render.ModuleSource; // })); // break; // } //} this.gridRender.Dispatcher.BeginInvoke(new Action(() => { if (render == null) return; if (render.Is3DModel == true && GetView3DUse()==true) { //if (!GetView3DUse()) // return; if (!vmRenders.TryGetValue(Get3DKey(render.Id), out var host)) return; var display = host.Child as Cognex.VisionPro3D.Cog3DDisplayV2WF; if (display == null) return; try { display.Clear(); if (render.RangeImage == null || render.GreyImage == null) return; var rImgG = new Cog3DRangeImageGraphic(render.RangeImage, render.GreyImage); display.Add(rImgG, "__default"); display.FitView(); } catch (System.Windows.Forms.AxHost.InvalidActiveXStateException) { } //return; } if (!vmRenders.TryGetValue(Get2DKey(render.Id), out var host2D)) return; var recordDisplay = host2D.Child as Cognex.VisionPro.CogRecordDisplay; if (recordDisplay == null) return; try { recordDisplay.Record = null; recordDisplay.Image = render.Image; recordDisplay.StaticGraphics.Clear(); if (render.Graphic != null) recordDisplay.StaticGraphics.AddList(render.Graphic, ""); if (render.Record != null) recordDisplay.Record = render.Record; if (render.IsSaveImage) { Bitmap bitmap = null; try { bitmap = (Bitmap)recordDisplay.CreateContentBitmap(Cognex.VisionPro.Display.CogDisplayContentBitmapConstants.Custom); SaveImage( render.SaveImageModel, render.SaveImagePathModel, render.SavePath, render.Image, bitmap, render.Result, render.IsCompress, render.ImageFileName, render.Is3DModel ); } catch { try { bitmap?.Dispose(); } catch { } throw; } } } catch (System.Windows.Forms.AxHost.InvalidActiveXStateException) { } })); } private void AddRenderPair(Guid id, string displayName) { // 2D var display2D = new Cognex.VisionPro.CogRecordDisplay() { Tag = displayName }; display2D.HandleCreated += (s, e) => { try { display2D.HorizontalScrollBar = false; display2D.VerticalScrollBar = false; display2D.AutoFit = true; display2D.BackColor = System.Drawing.SystemColors.ActiveCaption; } catch (System.Windows.Forms.AxHost.InvalidActiveXStateException) { } }; // 绑定双击:弹出预览窗口 display2D.DoubleClick += (s, e) => OnDisplayDoubleClick(display2D); vmRenders.Add(Get2DKey(id), new WindowsFormsHost() { Tag = displayName, Child = display2D }); // 3D:按配置创建 if (!GetView3DUse()) return; // 3D var display3D = new Cognex.VisionPro3D.Cog3DDisplayV2WF() { Tag = displayName }; display3D.HandleCreated += (s, e) => { try { display3D.BackColor = System.Drawing.SystemColors.ActiveCaption; } catch (System.Windows.Forms.AxHost.InvalidActiveXStateException) { } }; vmRenders.Add(Get3DKey(id), new WindowsFormsHost() { Tag = displayName, Child = display3D }); } private Grid CreateCellGrid(Guid id, string displayName, System.Windows.Media.FontFamily font) { var is3DEnabled = GetView3DUse(); var cell = new Grid(); cell.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) }); cell.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); var title = new TextBlock() { Text = displayName, HorizontalAlignment = System.Windows.HorizontalAlignment.Center, FontWeight = FontWeights.Bold, FontFamily = font, FontSize = 12, Foreground = System.Windows.Media.Brushes.Black }; Titles[id] = title; var content = new Grid(); if(is3DEnabled) { content.ColumnDefinitions.Add(new ColumnDefinition()); // 2D content.ColumnDefinitions.Add(new ColumnDefinition()); // 3D content.Children.Add(vmRenders[Get2DKey(id)]); content.Children.Add(vmRenders[Get3DKey(id)]); Grid.SetColumn(vmRenders[Get2DKey(id)], 0); Grid.SetColumn(vmRenders[Get3DKey(id)], 1); } else { content.ColumnDefinitions.Add(new ColumnDefinition()); // 仅 2D content.Children.Add(vmRenders[Get2DKey(id)]); Grid.SetColumn(vmRenders[Get2DKey(id)], 0); } cell.Children.Add(title); cell.Children.Add(content); Grid.SetRow(title, 0); Grid.SetRow(content, 1); return cell; } Grid grid1 = new Grid(); Grid grid2 = new Grid(); Grid grid3 = new Grid(); Grid grid4 = new Grid(); Grid grid5 = new Grid(); Grid grid6 = new Grid(); Grid grid7 = new Grid(); Grid grid8 = new Grid(); Grid grid9 = new Grid(); Grid grid10 = new Grid(); Grid grid11 = new Grid(); Grid grid12 = new Grid(); Grid grid13 = new Grid(); Grid grid14 = new Grid(); Grid grid15 = new Grid(); Grid grid16 = new Grid(); Grid grid17 = new Grid(); Grid grid18 = new Grid(); Grid grid19 = new Grid(); Grid grid20 = new Grid(); private void ViewModel_UpdateLayout(System.Collections.ObjectModel.ObservableCollection obj) { System.Windows.Media.FontFamily font = Application.Current.Resources["DefaultFont"] as System.Windows.Media.FontFamily; if (vmRenders.Count > 0) { foreach (var render in vmRenders) { render.Value.Dispose(); } } vmRenders.Clear(); gridRender.Children.Clear(); gridRender.RowDefinitions.Clear(); gridRender.ColumnDefinitions.Clear(); Titles.Clear(); if (obj == null || obj.Count == 0) return; // 先创建所有相机的 2D/3D 对 for (int i = 0; i < obj.Count; i++) AddRenderPair(obj[i].Id, obj[i].DisplayName); switch (obj.Count) { case 1: { gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.ColumnDefinitions.Add(new ColumnDefinition()); var cell = CreateCellGrid(obj[0].Id, obj[0].DisplayName, font); gridRender.Children.Add(cell); Grid.SetRow(cell, 0); Grid.SetColumn(cell, 0); gridRender.ShowGridLines = false; break; } case 2: { gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ShowGridLines = true; var cell0 = CreateCellGrid(obj[0].Id, obj[0].DisplayName, font); var cell1 = CreateCellGrid(obj[1].Id, obj[1].DisplayName, font); gridRender.Children.Add(cell0); gridRender.Children.Add(cell1); Grid.SetRow(cell0, 0); Grid.SetColumn(cell0, 0); Grid.SetRow(cell1, 0); Grid.SetColumn(cell1, 1); break; } case 3: { gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ShowGridLines = true; var cell0 = CreateCellGrid(obj[0].Id, obj[0].DisplayName, font); var cell1 = CreateCellGrid(obj[1].Id, obj[1].DisplayName, font); var cell2 = CreateCellGrid(obj[2].Id, obj[2].DisplayName, font); gridRender.Children.Add(cell0); gridRender.Children.Add(cell1); gridRender.Children.Add(cell2); Grid.SetRow(cell0, 0); Grid.SetColumn(cell0, 0); Grid.SetRow(cell1, 0); Grid.SetColumn(cell1, 1); Grid.SetRow(cell2, 1); Grid.SetColumn(cell2, 0); Grid.SetColumnSpan(cell2, 2); break; } case 4: { gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ShowGridLines = true; for (int i = 0; i < 4; i++) { var cell = CreateCellGrid(obj[i].Id, obj[i].DisplayName, font); gridRender.Children.Add(cell); Grid.SetRow(cell, i / 2); Grid.SetColumn(cell, i % 2); } break; } case 5: { // 你的原布局:上面2个,下面3个(通过嵌套grid6) gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ShowGridLines = true; var top0 = CreateCellGrid(obj[0].Id, obj[0].DisplayName, font); var top1 = CreateCellGrid(obj[1].Id, obj[1].DisplayName, font); var bottom = new Grid(); bottom.ColumnDefinitions.Add(new ColumnDefinition()); bottom.ColumnDefinitions.Add(new ColumnDefinition()); bottom.ColumnDefinitions.Add(new ColumnDefinition()); var b0 = CreateCellGrid(obj[2].Id, obj[2].DisplayName, font); var b1 = CreateCellGrid(obj[3].Id, obj[3].DisplayName, font); var b2 = CreateCellGrid(obj[4].Id, obj[4].DisplayName, font); bottom.Children.Add(b0); bottom.Children.Add(b1); bottom.Children.Add(b2); Grid.SetColumn(b0, 0); Grid.SetColumn(b1, 1); Grid.SetColumn(b2, 2); gridRender.Children.Add(top0); gridRender.Children.Add(top1); gridRender.Children.Add(bottom); Grid.SetRow(top0, 0); Grid.SetColumn(top0, 0); Grid.SetRow(top1, 0); Grid.SetColumn(top1, 1); Grid.SetRow(bottom, 1); Grid.SetColumn(bottom, 0); Grid.SetColumnSpan(bottom, 2); break; } case 6: { // 你的原布局:2行3列 gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ShowGridLines = true; for (int i = 0; i < 6; i++) { var cell = CreateCellGrid(obj[i].Id, obj[i].DisplayName, font); gridRender.Children.Add(cell); Grid.SetRow(cell, i / 3); Grid.SetColumn(cell, i % 3); } break; } case 7: { // 你的原布局:第一行4个,第二行3个(但原来只放到 col 0/1/2) // 这里保持原样:第一行4列,第二行3列(第4列留空) gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ShowGridLines = true; for (int i = 0; i < 7; i++) { var cell = CreateCellGrid(obj[i].Id, obj[i].DisplayName, font); gridRender.Children.Add(cell); if (i < 4) { Grid.SetRow(cell, 0); Grid.SetColumn(cell, i); } else { Grid.SetRow(cell, 1); Grid.SetColumn(cell, i - 4); } } break; } case 8: { // 2行4列 gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); for (int i = 0; i < 4; i++) gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ShowGridLines = true; for (int i = 0; i < 8; i++) { var cell = CreateCellGrid(obj[i].Id, obj[i].DisplayName, font); gridRender.Children.Add(cell); Grid.SetRow(cell, i / 4); Grid.SetColumn(cell, i % 4); } break; } case 9: { // 3行3列 gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ShowGridLines = true; for (int i = 0; i < 9; i++) { var cell = CreateCellGrid(obj[i].Id, obj[i].DisplayName, font); gridRender.Children.Add(cell); Grid.SetRow(cell, i / 3); Grid.SetColumn(cell, i % 3); } break; } case 12: { // 3行4列 gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); for (int i = 0; i < 4; i++) gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ShowGridLines = true; for (int i = 0; i < 12; i++) { var cell = CreateCellGrid(obj[i].Id, obj[i].DisplayName, font); gridRender.Children.Add(cell); Grid.SetRow(cell, i / 4); Grid.SetColumn(cell, i % 4); } break; } case 16: { // 4行4列 gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); for (int i = 0; i < 4; i++) gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ShowGridLines = true; for (int i = 0; i < 16; i++) { var cell = CreateCellGrid(obj[i].Id, obj[i].DisplayName, font); gridRender.Children.Add(cell); Grid.SetRow(cell, i / 4); Grid.SetColumn(cell, i % 4); } break; } case 20: { // 5行4列 for (int r = 0; r < 5; r++) gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); for (int c = 0; c < 4; c++) gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ShowGridLines = true; for (int i = 0; i < 20; i++) { var cell = CreateCellGrid(obj[i].Id, obj[i].DisplayName, font); gridRender.Children.Add(cell); Grid.SetRow(cell, i / 4); Grid.SetColumn(cell, i % 4); } break; } default: { // 未覆盖的数量:先用简单的 1列多行兜底(避免空白) gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); gridRender.ColumnDefinitions.Add(new ColumnDefinition()); gridRender.ShowGridLines = false; var cell = CreateCellGrid(obj[0].Id, obj[0].DisplayName, font); gridRender.Children.Add(cell); Grid.SetRow(cell, 0); Grid.SetColumn(cell, 0); break; } } } /// /// 保存图像(保持你原有逻辑不变,补充 Dispose 兜底,防止压缩分支不释放导致闪退) /// private void SaveImage(ProcedureSaveImageModel saveImageModel, ProcedureSaveImagePathModel saveImagePathModel, string path, ICogImage image, Bitmap reimage, bool result, bool isCompress, string imageFileName,bool is3Dmodel) { if (string.IsNullOrEmpty(path) || string.IsNullOrWhiteSpace(path) || !Path.IsPathRooted(path)) { _eventAggregator.GetEvent() .Publish(new Models.MessageStruct() { Message = "保存图像路径为无效的路径!", level = MessageLevel.Alarm }); return; } Task.Run(() => { try { DateTime now = DateTime.Now; //图片名 string imgName = now.ToString("yyyy-MM-dd HH_mm_ss"); if (!string.IsNullOrEmpty(imageFileName)) { imgName = imageFileName; } if (saveImageModel == ProcedureSaveImageModel.Original) { string Originalpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp"; if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_OkNG_Time) { Originalpath = result ? $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp" : $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp"; } else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ok_Time) { if (result) Originalpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp"; else return; } else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ng_Time) { if (!result) Originalpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp"; else return; } else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Formula_ProductSN_Time) { // 当前产品配方名(过滤非法字符) string formulaName = _productService.GetCurrentProduct().Name; foreach (char c in Path.GetInvalidFileNameChars()) formulaName = formulaName.Replace(c, '_'); // 产品SN(过滤非法字符) string productSN = _productService.CurrentProductCode; foreach (char c in Path.GetInvalidFileNameChars()) productSN = productSN.Replace(c, '_'); string resultStr = result ? "OK" : "NG"; Originalpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.bmp"; } if (!Directory.Exists(Path.GetDirectoryName(Originalpath))) Directory.CreateDirectory(Path.GetDirectoryName(Originalpath)); using (CogImageFileBMP _cogImageFileTool = new CogImageFileBMP()) { _cogImageFileTool.Open(Originalpath, CogImageFileModeConstants.Write); _cogImageFileTool.Append(image); _cogImageFileTool.Close(); } } else if (saveImageModel == ProcedureSaveImageModel.Recorded) { string Recordedpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp"; if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_OkNG_Time) { Recordedpath = result ? $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp" : $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp"; } else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ok_Time) { if (result) Recordedpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp"; else return; } else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ng_Time) { if (!result) Recordedpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp"; else return; } else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Formula_ProductSN_Time) { string formulaName = _productService.GetCurrentProduct().Name; foreach (char c in Path.GetInvalidFileNameChars()) formulaName = formulaName.Replace(c, '_'); string productSN = _productService.CurrentProductCode; foreach (char c in Path.GetInvalidFileNameChars()) productSN = productSN.Replace(c, '_'); string resultStr = result ? "OK" : "NG"; Recordedpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.bmp"; } if (!Directory.Exists(Path.GetDirectoryName(Recordedpath))) Directory.CreateDirectory(Path.GetDirectoryName(Recordedpath)); if (isCompress) { ImageHelper.CompressImage(reimage, Recordedpath, 20); } else { reimage.Save(Recordedpath); } } else if (saveImageModel == ProcedureSaveImageModel.OriginalAndRecorded) { string Originalpath = ""; if (is3Dmodel==true) { Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.idb"; } else { Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp"; } string Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp"; if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_OkNG_Time) { if (result) { Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp"; Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp"; } else { Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp"; Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp"; } } else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ok_Time) { if (result) { Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp"; Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp"; } else { return; } } else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ng_Time) { if (!result) { Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp"; Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp"; } else { return; } } else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Formula_ProductSN_Time) { string formulaName = _productService.GetCurrentProduct().Name; foreach (char c in Path.GetInvalidFileNameChars()) formulaName = formulaName.Replace(c, '_'); string productSN = _productService.CurrentProductCode; if(productSN!=null ) { foreach (char c in Path.GetInvalidFileNameChars()) productSN = productSN.Replace(c, '_'); } string resultStr = result ? "OK" : "NG"; if (is3Dmodel == true) { Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.idb"; //Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.idb"; } else { Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.bmp"; //Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp"; } Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.bmp"; } if (!Directory.Exists(Path.GetDirectoryName(Originalpath))) Directory.CreateDirectory(Path.GetDirectoryName(Originalpath)); //using (CogImageFileBMP _cogImageFileTool = new CogImageFileBMP()) //{ // _cogImageFileTool.Open(Originalpath, CogImageFileModeConstants.Write); // _cogImageFileTool.Append(image); // _cogImageFileTool.Close(); //} using (CogImageFile _cogImageFileTool = new CogImageFile()) { _cogImageFileTool.Open(Originalpath, CogImageFileModeConstants.Write); _cogImageFileTool.Append(image); _cogImageFileTool.Close(); } if (!Directory.Exists(Path.GetDirectoryName(Recordedpath))) Directory.CreateDirectory(Path.GetDirectoryName(Recordedpath)); if (isCompress) { ImageHelper.CompressImage(reimage, Recordedpath, 20); } else { reimage.Save(Recordedpath); } } } catch (Exception ex) { LogHelper.WriteLogError("保存流程运行结果的图片时出错!", ex); } finally { // ======================= 【关键修复】无论是否压缩都释放Bitmap ======================= try { reimage?.Dispose(); } catch { } } }); } private void ProductChanged(ProductModel product) { this.gridRender.Dispatcher.BeginInvoke(new Action(() => { var is3DEnabled = GetView3DUse(); foreach (var item in vmRenders) { try { // 2D:永远清理 var display2D = item.Value.Child as Cognex.VisionPro.CogRecordDisplay; if (display2D != null) { display2D.Record = null; display2D.Image = null; display2D.StaticGraphics.Clear(); continue; } // 3D:仅在启用 3D 时清理 if (!is3DEnabled) continue; var display3D = item.Value.Child as Cognex.VisionPro3D.Cog3DDisplayV2WF; if (display3D != null) { display3D.Clear(); } } catch (System.Windows.Forms.AxHost.InvalidActiveXStateException) { // 控件句柄/ActiveX 未就绪时忽略 } catch (Exception ex) { LogHelper.WriteLogError(Lang.切换产品清除主页图像时出错, ex); } } })); } private void OnDisplayDoubleClick(CogRecordDisplay disp) { if (disp == null) return; try { // 直接把当前 CogRecordDisplay 传给对话框 VM(VM 内部读取 Image/Record) var parameters = new Prism.Services.Dialogs.DialogParameters { { "Cog", disp } }; // Prism Dialog 必须在 WPF UI 线程调用 Dispatcher.BeginInvoke(new Action(() => { try { _dialogService.ShowDialog("ImagePreviewWindow", parameters, r => { }); } catch (Exception ex) { LogHelper.WriteLogError("打开 ImagePreviewWindow 失败", ex); } })); } catch (Exception ex) { LogHelper.WriteLogError("双击打开预览窗口失败", ex); } } } }