ShowVisionRender.xaml.cs 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954
  1. using Cognex.VisionPro;
  2. using Cognex.VisionPro.ImageFile;
  3. using Cognex.VisionPro3D;
  4. using log4net.Core;
  5. using MahApps.Metro.Controls;
  6. using Prism.Events;
  7. using Prism.Ioc;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Drawing;
  11. using System.IO;
  12. using System.Threading.Tasks;
  13. using System.Windows;
  14. using System.Windows.Controls;
  15. using System.Windows.Forms.Integration;
  16. using System.Windows.Interop;
  17. using TeamAAS_VP;
  18. using TeamAAS_VP.Core;
  19. using TeamAAS_VP.Enums;
  20. using TeamAAS_VP.Events;
  21. using TeamAAS_VP.Interfaces;
  22. using TeamAAS_VP.Models;
  23. using TeamAAS_VP.Resources.Languages;
  24. using TeamAAS_VP.ViewModels;
  25. using TeamAAS_VP.ViewModels.Home;
  26. //using static MaterialDesignThemes.Wtf.ToolBar;
  27. namespace TeamAAS_VP.Views.Home
  28. {
  29. /// <summary>
  30. /// Interaction logic for ShowVisionRender
  31. /// </summary>
  32. public partial class ShowVisionRender : UserControl
  33. {
  34. private const string Render2DKeySuffix = ":2D";
  35. private const string Render3DKeySuffix = ":3D";
  36. private static string Get2DKey(Guid id) => id.ToString() + Render2DKeySuffix;
  37. private static string Get3DKey(Guid id) => id.ToString() + Render3DKeySuffix;
  38. ShowVisionRenderViewModel viewModel;
  39. Dictionary<string, WindowsFormsHost> vmRenders;
  40. Dictionary<Guid, TextBlock> Titles;
  41. IEventAggregator _eventAggregator;
  42. private readonly IProductService _productService;
  43. private readonly Prism.Services.Dialogs.IDialogService _dialogService;
  44. public ShowVisionRender()
  45. {
  46. InitializeComponent();
  47. vmRenders = new Dictionary<string, WindowsFormsHost>();
  48. Titles = new Dictionary<Guid, TextBlock>();
  49. viewModel = DataContext as ShowVisionRenderViewModel;
  50. _eventAggregator = viewModel._eventAggregator;
  51. _productService = ((Prism.PrismApplicationBase)App.Current).Container.Resolve<IProductService>();
  52. // 新增:DialogService
  53. _dialogService = ((Prism.PrismApplicationBase)App.Current).Container.Resolve<Prism.Services.Dialogs.IDialogService>();
  54. viewModel.UpdateLayout += ViewModel_UpdateLayout;
  55. _eventAggregator.GetEvent<RenderUpdateNotification>().Subscribe(UpdateRenderModuleSource);
  56. _eventAggregator.GetEvent<ProductChangedNotification>().Subscribe(ProductChanged);
  57. }
  58. private bool GetView3DUse()
  59. {
  60. try
  61. {
  62. var configService = ((Prism.PrismApplicationBase)App.Current).Container.Resolve<IConfigService>();
  63. if(configService.GetSystemConfiguration().PickPointNum==0)
  64. {
  65. return false;
  66. }
  67. else
  68. {
  69. return true;
  70. }
  71. //return true;
  72. }
  73. catch
  74. {
  75. return false;
  76. }
  77. }
  78. private void UpdateRenderModuleSource(ShowRender render)
  79. {
  80. //foreach (var item in vmRenders)
  81. //{
  82. // if (item.Key== render.Id)
  83. // {
  84. // App.Current.Dispatcher.Invoke(new Action(() =>
  85. // {
  86. // item.Value.ModuleSource = render.ModuleSource;
  87. // }));
  88. // break;
  89. // }
  90. //}
  91. this.gridRender.Dispatcher.BeginInvoke(new Action(() =>
  92. {
  93. if (render == null)
  94. return;
  95. if (render.Is3DModel == true && GetView3DUse()==true)
  96. {
  97. //if (!GetView3DUse())
  98. // return;
  99. if (!vmRenders.TryGetValue(Get3DKey(render.Id), out var host))
  100. return;
  101. var display = host.Child as Cognex.VisionPro3D.Cog3DDisplayV2WF;
  102. if (display == null)
  103. return;
  104. try
  105. {
  106. display.Clear();
  107. if (render.RangeImage == null || render.GreyImage == null)
  108. return;
  109. var rImgG = new Cog3DRangeImageGraphic(render.RangeImage, render.GreyImage);
  110. display.Add(rImgG, "__default");
  111. display.FitView();
  112. }
  113. catch (System.Windows.Forms.AxHost.InvalidActiveXStateException)
  114. {
  115. }
  116. //return;
  117. }
  118. if (!vmRenders.TryGetValue(Get2DKey(render.Id), out var host2D))
  119. return;
  120. var recordDisplay = host2D.Child as Cognex.VisionPro.CogRecordDisplay;
  121. if (recordDisplay == null)
  122. return;
  123. try
  124. {
  125. recordDisplay.Record = null;
  126. recordDisplay.Image = render.Image;
  127. recordDisplay.StaticGraphics.Clear();
  128. if (render.Graphic != null)
  129. recordDisplay.StaticGraphics.AddList(render.Graphic, "");
  130. if (render.Record != null)
  131. recordDisplay.Record = render.Record;
  132. if (render.IsSaveImage)
  133. {
  134. Bitmap bitmap = null;
  135. try
  136. {
  137. bitmap = (Bitmap)recordDisplay.CreateContentBitmap(Cognex.VisionPro.Display.CogDisplayContentBitmapConstants.Custom);
  138. SaveImage(
  139. render.SaveImageModel,
  140. render.SaveImagePathModel,
  141. render.SavePath,
  142. render.Image,
  143. bitmap,
  144. render.Result,
  145. render.IsCompress,
  146. render.ImageFileName,
  147. render.Is3DModel
  148. );
  149. }
  150. catch
  151. {
  152. try { bitmap?.Dispose(); } catch { }
  153. throw;
  154. }
  155. }
  156. }
  157. catch (System.Windows.Forms.AxHost.InvalidActiveXStateException)
  158. {
  159. }
  160. }));
  161. }
  162. private void AddRenderPair(Guid id, string displayName)
  163. {
  164. // 2D
  165. var display2D = new Cognex.VisionPro.CogRecordDisplay() { Tag = displayName };
  166. display2D.HandleCreated += (s, e) =>
  167. {
  168. try
  169. {
  170. display2D.HorizontalScrollBar = false;
  171. display2D.VerticalScrollBar = false;
  172. display2D.AutoFit = true;
  173. display2D.BackColor = System.Drawing.SystemColors.ActiveCaption;
  174. }
  175. catch (System.Windows.Forms.AxHost.InvalidActiveXStateException)
  176. {
  177. }
  178. };
  179. // 绑定双击:弹出预览窗口
  180. display2D.DoubleClick += (s, e) => OnDisplayDoubleClick(display2D);
  181. vmRenders.Add(Get2DKey(id), new WindowsFormsHost() { Tag = displayName, Child = display2D });
  182. // 3D:按配置创建
  183. if (!GetView3DUse())
  184. return;
  185. // 3D
  186. var display3D = new Cognex.VisionPro3D.Cog3DDisplayV2WF() { Tag = displayName };
  187. display3D.HandleCreated += (s, e) =>
  188. {
  189. try
  190. {
  191. display3D.BackColor = System.Drawing.SystemColors.ActiveCaption;
  192. }
  193. catch (System.Windows.Forms.AxHost.InvalidActiveXStateException)
  194. {
  195. }
  196. };
  197. vmRenders.Add(Get3DKey(id), new WindowsFormsHost() { Tag = displayName, Child = display3D });
  198. }
  199. private Grid CreateCellGrid(Guid id, string displayName, System.Windows.Media.FontFamily font)
  200. {
  201. var is3DEnabled = GetView3DUse();
  202. var cell = new Grid();
  203. cell.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
  204. cell.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  205. var title = new TextBlock()
  206. {
  207. Text = displayName,
  208. HorizontalAlignment = System.Windows.HorizontalAlignment.Center,
  209. FontWeight = FontWeights.Bold,
  210. FontFamily = font,
  211. FontSize = 12,
  212. Foreground = System.Windows.Media.Brushes.Black
  213. };
  214. Titles[id] = title;
  215. var content = new Grid();
  216. if(is3DEnabled)
  217. {
  218. content.ColumnDefinitions.Add(new ColumnDefinition()); // 2D
  219. content.ColumnDefinitions.Add(new ColumnDefinition()); // 3D
  220. content.Children.Add(vmRenders[Get2DKey(id)]);
  221. content.Children.Add(vmRenders[Get3DKey(id)]);
  222. Grid.SetColumn(vmRenders[Get2DKey(id)], 0);
  223. Grid.SetColumn(vmRenders[Get3DKey(id)], 1);
  224. }
  225. else
  226. {
  227. content.ColumnDefinitions.Add(new ColumnDefinition()); // 仅 2D
  228. content.Children.Add(vmRenders[Get2DKey(id)]);
  229. Grid.SetColumn(vmRenders[Get2DKey(id)], 0);
  230. }
  231. cell.Children.Add(title);
  232. cell.Children.Add(content);
  233. Grid.SetRow(title, 0);
  234. Grid.SetRow(content, 1);
  235. return cell;
  236. }
  237. Grid grid1 = new Grid();
  238. Grid grid2 = new Grid();
  239. Grid grid3 = new Grid();
  240. Grid grid4 = new Grid();
  241. Grid grid5 = new Grid();
  242. Grid grid6 = new Grid();
  243. Grid grid7 = new Grid();
  244. Grid grid8 = new Grid();
  245. Grid grid9 = new Grid();
  246. Grid grid10 = new Grid();
  247. Grid grid11 = new Grid();
  248. Grid grid12 = new Grid();
  249. Grid grid13 = new Grid();
  250. Grid grid14 = new Grid();
  251. Grid grid15 = new Grid();
  252. Grid grid16 = new Grid();
  253. Grid grid17 = new Grid();
  254. Grid grid18 = new Grid();
  255. Grid grid19 = new Grid();
  256. Grid grid20 = new Grid();
  257. private void ViewModel_UpdateLayout(System.Collections.ObjectModel.ObservableCollection<Models.ShowRender> obj)
  258. {
  259. System.Windows.Media.FontFamily font = Application.Current.Resources["DefaultFont"] as System.Windows.Media.FontFamily;
  260. if (vmRenders.Count > 0)
  261. {
  262. foreach (var render in vmRenders)
  263. {
  264. render.Value.Dispose();
  265. }
  266. }
  267. vmRenders.Clear();
  268. gridRender.Children.Clear();
  269. gridRender.RowDefinitions.Clear();
  270. gridRender.ColumnDefinitions.Clear();
  271. Titles.Clear();
  272. if (obj == null || obj.Count == 0)
  273. return;
  274. // 先创建所有相机的 2D/3D 对
  275. for (int i = 0; i < obj.Count; i++)
  276. AddRenderPair(obj[i].Id, obj[i].DisplayName);
  277. switch (obj.Count)
  278. {
  279. case 1:
  280. {
  281. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  282. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  283. var cell = CreateCellGrid(obj[0].Id, obj[0].DisplayName, font);
  284. gridRender.Children.Add(cell);
  285. Grid.SetRow(cell, 0);
  286. Grid.SetColumn(cell, 0);
  287. gridRender.ShowGridLines = false;
  288. break;
  289. }
  290. case 2:
  291. {
  292. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  293. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  294. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  295. gridRender.ShowGridLines = true;
  296. var cell0 = CreateCellGrid(obj[0].Id, obj[0].DisplayName, font);
  297. var cell1 = CreateCellGrid(obj[1].Id, obj[1].DisplayName, font);
  298. gridRender.Children.Add(cell0);
  299. gridRender.Children.Add(cell1);
  300. Grid.SetRow(cell0, 0);
  301. Grid.SetColumn(cell0, 0);
  302. Grid.SetRow(cell1, 0);
  303. Grid.SetColumn(cell1, 1);
  304. break;
  305. }
  306. case 3:
  307. {
  308. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  309. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  310. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  311. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  312. gridRender.ShowGridLines = true;
  313. var cell0 = CreateCellGrid(obj[0].Id, obj[0].DisplayName, font);
  314. var cell1 = CreateCellGrid(obj[1].Id, obj[1].DisplayName, font);
  315. var cell2 = CreateCellGrid(obj[2].Id, obj[2].DisplayName, font);
  316. gridRender.Children.Add(cell0);
  317. gridRender.Children.Add(cell1);
  318. gridRender.Children.Add(cell2);
  319. Grid.SetRow(cell0, 0);
  320. Grid.SetColumn(cell0, 0);
  321. Grid.SetRow(cell1, 0);
  322. Grid.SetColumn(cell1, 1);
  323. Grid.SetRow(cell2, 1);
  324. Grid.SetColumn(cell2, 0);
  325. Grid.SetColumnSpan(cell2, 2);
  326. break;
  327. }
  328. case 4:
  329. {
  330. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  331. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  332. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  333. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  334. gridRender.ShowGridLines = true;
  335. for (int i = 0; i < 4; i++)
  336. {
  337. var cell = CreateCellGrid(obj[i].Id, obj[i].DisplayName, font);
  338. gridRender.Children.Add(cell);
  339. Grid.SetRow(cell, i / 2);
  340. Grid.SetColumn(cell, i % 2);
  341. }
  342. break;
  343. }
  344. case 5:
  345. {
  346. // 你的原布局:上面2个,下面3个(通过嵌套grid6)
  347. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  348. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  349. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  350. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  351. gridRender.ShowGridLines = true;
  352. var top0 = CreateCellGrid(obj[0].Id, obj[0].DisplayName, font);
  353. var top1 = CreateCellGrid(obj[1].Id, obj[1].DisplayName, font);
  354. var bottom = new Grid();
  355. bottom.ColumnDefinitions.Add(new ColumnDefinition());
  356. bottom.ColumnDefinitions.Add(new ColumnDefinition());
  357. bottom.ColumnDefinitions.Add(new ColumnDefinition());
  358. var b0 = CreateCellGrid(obj[2].Id, obj[2].DisplayName, font);
  359. var b1 = CreateCellGrid(obj[3].Id, obj[3].DisplayName, font);
  360. var b2 = CreateCellGrid(obj[4].Id, obj[4].DisplayName, font);
  361. bottom.Children.Add(b0);
  362. bottom.Children.Add(b1);
  363. bottom.Children.Add(b2);
  364. Grid.SetColumn(b0, 0);
  365. Grid.SetColumn(b1, 1);
  366. Grid.SetColumn(b2, 2);
  367. gridRender.Children.Add(top0);
  368. gridRender.Children.Add(top1);
  369. gridRender.Children.Add(bottom);
  370. Grid.SetRow(top0, 0);
  371. Grid.SetColumn(top0, 0);
  372. Grid.SetRow(top1, 0);
  373. Grid.SetColumn(top1, 1);
  374. Grid.SetRow(bottom, 1);
  375. Grid.SetColumn(bottom, 0);
  376. Grid.SetColumnSpan(bottom, 2);
  377. break;
  378. }
  379. case 6:
  380. {
  381. // 你的原布局:2行3列
  382. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  383. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  384. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  385. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  386. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  387. gridRender.ShowGridLines = true;
  388. for (int i = 0; i < 6; i++)
  389. {
  390. var cell = CreateCellGrid(obj[i].Id, obj[i].DisplayName, font);
  391. gridRender.Children.Add(cell);
  392. Grid.SetRow(cell, i / 3);
  393. Grid.SetColumn(cell, i % 3);
  394. }
  395. break;
  396. }
  397. case 7:
  398. {
  399. // 你的原布局:第一行4个,第二行3个(但原来只放到 col 0/1/2)
  400. // 这里保持原样:第一行4列,第二行3列(第4列留空)
  401. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  402. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  403. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  404. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  405. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  406. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  407. gridRender.ShowGridLines = true;
  408. for (int i = 0; i < 7; i++)
  409. {
  410. var cell = CreateCellGrid(obj[i].Id, obj[i].DisplayName, font);
  411. gridRender.Children.Add(cell);
  412. if (i < 4)
  413. {
  414. Grid.SetRow(cell, 0);
  415. Grid.SetColumn(cell, i);
  416. }
  417. else
  418. {
  419. Grid.SetRow(cell, 1);
  420. Grid.SetColumn(cell, i - 4);
  421. }
  422. }
  423. break;
  424. }
  425. case 8:
  426. {
  427. // 2行4列
  428. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  429. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  430. for (int i = 0; i < 4; i++)
  431. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  432. gridRender.ShowGridLines = true;
  433. for (int i = 0; i < 8; i++)
  434. {
  435. var cell = CreateCellGrid(obj[i].Id, obj[i].DisplayName, font);
  436. gridRender.Children.Add(cell);
  437. Grid.SetRow(cell, i / 4);
  438. Grid.SetColumn(cell, i % 4);
  439. }
  440. break;
  441. }
  442. case 9:
  443. {
  444. // 3行3列
  445. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  446. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  447. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  448. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  449. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  450. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  451. gridRender.ShowGridLines = true;
  452. for (int i = 0; i < 9; i++)
  453. {
  454. var cell = CreateCellGrid(obj[i].Id, obj[i].DisplayName, font);
  455. gridRender.Children.Add(cell);
  456. Grid.SetRow(cell, i / 3);
  457. Grid.SetColumn(cell, i % 3);
  458. }
  459. break;
  460. }
  461. case 12:
  462. {
  463. // 3行4列
  464. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  465. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  466. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  467. for (int i = 0; i < 4; i++)
  468. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  469. gridRender.ShowGridLines = true;
  470. for (int i = 0; i < 12; i++)
  471. {
  472. var cell = CreateCellGrid(obj[i].Id, obj[i].DisplayName, font);
  473. gridRender.Children.Add(cell);
  474. Grid.SetRow(cell, i / 4);
  475. Grid.SetColumn(cell, i % 4);
  476. }
  477. break;
  478. }
  479. case 16:
  480. {
  481. // 4行4列
  482. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  483. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  484. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  485. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  486. for (int i = 0; i < 4; i++)
  487. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  488. gridRender.ShowGridLines = true;
  489. for (int i = 0; i < 16; i++)
  490. {
  491. var cell = CreateCellGrid(obj[i].Id, obj[i].DisplayName, font);
  492. gridRender.Children.Add(cell);
  493. Grid.SetRow(cell, i / 4);
  494. Grid.SetColumn(cell, i % 4);
  495. }
  496. break;
  497. }
  498. case 20:
  499. {
  500. // 5行4列
  501. for (int r = 0; r < 5; r++)
  502. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  503. for (int c = 0; c < 4; c++)
  504. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  505. gridRender.ShowGridLines = true;
  506. for (int i = 0; i < 20; i++)
  507. {
  508. var cell = CreateCellGrid(obj[i].Id, obj[i].DisplayName, font);
  509. gridRender.Children.Add(cell);
  510. Grid.SetRow(cell, i / 4);
  511. Grid.SetColumn(cell, i % 4);
  512. }
  513. break;
  514. }
  515. default:
  516. {
  517. // 未覆盖的数量:先用简单的 1列多行兜底(避免空白)
  518. gridRender.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
  519. gridRender.ColumnDefinitions.Add(new ColumnDefinition());
  520. gridRender.ShowGridLines = false;
  521. var cell = CreateCellGrid(obj[0].Id, obj[0].DisplayName, font);
  522. gridRender.Children.Add(cell);
  523. Grid.SetRow(cell, 0);
  524. Grid.SetColumn(cell, 0);
  525. break;
  526. }
  527. }
  528. }
  529. /// <summary>
  530. /// 保存图像(保持你原有逻辑不变,补充 Dispose 兜底,防止压缩分支不释放导致闪退)
  531. /// </summary>
  532. private void SaveImage(ProcedureSaveImageModel saveImageModel, ProcedureSaveImagePathModel saveImagePathModel, string path, ICogImage image, Bitmap reimage, bool result, bool isCompress, string imageFileName,bool is3Dmodel)
  533. {
  534. if (string.IsNullOrEmpty(path) || string.IsNullOrWhiteSpace(path) || !Path.IsPathRooted(path))
  535. {
  536. _eventAggregator.GetEvent<TaskMessageNotification>()
  537. .Publish(new Models.MessageStruct() { Message = "保存图像路径为无效的路径!", level = MessageLevel.Alarm });
  538. return;
  539. }
  540. Task.Run(() =>
  541. {
  542. try
  543. {
  544. DateTime now = DateTime.Now;
  545. //图片名
  546. string imgName = now.ToString("yyyy-MM-dd HH_mm_ss");
  547. if (!string.IsNullOrEmpty(imageFileName))
  548. {
  549. imgName = imageFileName;
  550. }
  551. if (saveImageModel == ProcedureSaveImageModel.Original)
  552. {
  553. string Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp";
  554. if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_OkNG_Time)
  555. {
  556. Originalpath = result
  557. ? $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp"
  558. : $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
  559. }
  560. else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ok_Time)
  561. {
  562. if (result)
  563. Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
  564. else
  565. return;
  566. }
  567. else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ng_Time)
  568. {
  569. if (!result)
  570. Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
  571. else
  572. return;
  573. }
  574. else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Formula_ProductSN_Time)
  575. {
  576. // 当前产品配方名(过滤非法字符)
  577. string formulaName = _productService.GetCurrentProduct().Name;
  578. foreach (char c in Path.GetInvalidFileNameChars())
  579. formulaName = formulaName.Replace(c, '_');
  580. // 产品SN(过滤非法字符)
  581. string productSN = _productService.CurrentProductCode;
  582. foreach (char c in Path.GetInvalidFileNameChars())
  583. productSN = productSN.Replace(c, '_');
  584. string resultStr = result ? "OK" : "NG";
  585. Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.bmp";
  586. }
  587. if (!Directory.Exists(Path.GetDirectoryName(Originalpath)))
  588. Directory.CreateDirectory(Path.GetDirectoryName(Originalpath));
  589. using (CogImageFileBMP _cogImageFileTool = new CogImageFileBMP())
  590. {
  591. _cogImageFileTool.Open(Originalpath, CogImageFileModeConstants.Write);
  592. _cogImageFileTool.Append(image);
  593. _cogImageFileTool.Close();
  594. }
  595. }
  596. else if (saveImageModel == ProcedureSaveImageModel.Recorded)
  597. {
  598. string Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp";
  599. if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_OkNG_Time)
  600. {
  601. Recordedpath = result
  602. ? $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp"
  603. : $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
  604. }
  605. else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ok_Time)
  606. {
  607. if (result)
  608. Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
  609. else
  610. return;
  611. }
  612. else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ng_Time)
  613. {
  614. if (!result)
  615. Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
  616. else
  617. return;
  618. }
  619. else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Formula_ProductSN_Time)
  620. {
  621. string formulaName = _productService.GetCurrentProduct().Name;
  622. foreach (char c in Path.GetInvalidFileNameChars())
  623. formulaName = formulaName.Replace(c, '_');
  624. string productSN = _productService.CurrentProductCode;
  625. foreach (char c in Path.GetInvalidFileNameChars())
  626. productSN = productSN.Replace(c, '_');
  627. string resultStr = result ? "OK" : "NG";
  628. Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.bmp";
  629. }
  630. if (!Directory.Exists(Path.GetDirectoryName(Recordedpath)))
  631. Directory.CreateDirectory(Path.GetDirectoryName(Recordedpath));
  632. if (isCompress)
  633. {
  634. ImageHelper.CompressImage(reimage, Recordedpath, 20);
  635. }
  636. else
  637. {
  638. reimage.Save(Recordedpath);
  639. }
  640. }
  641. else if (saveImageModel == ProcedureSaveImageModel.OriginalAndRecorded)
  642. {
  643. string Originalpath = "";
  644. if (is3Dmodel==true)
  645. {
  646. Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.idb";
  647. }
  648. else
  649. {
  650. Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp";
  651. }
  652. string Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp";
  653. if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_OkNG_Time)
  654. {
  655. if (result)
  656. {
  657. Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
  658. Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
  659. }
  660. else
  661. {
  662. Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
  663. Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
  664. }
  665. }
  666. else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ok_Time)
  667. {
  668. if (result)
  669. {
  670. Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
  671. Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
  672. }
  673. else
  674. {
  675. return;
  676. }
  677. }
  678. else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ng_Time)
  679. {
  680. if (!result)
  681. {
  682. Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
  683. Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
  684. }
  685. else
  686. {
  687. return;
  688. }
  689. }
  690. else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Formula_ProductSN_Time)
  691. {
  692. string formulaName = _productService.GetCurrentProduct().Name;
  693. foreach (char c in Path.GetInvalidFileNameChars())
  694. formulaName = formulaName.Replace(c, '_');
  695. string productSN = _productService.CurrentProductCode;
  696. if(productSN!=null )
  697. {
  698. foreach (char c in Path.GetInvalidFileNameChars())
  699. productSN = productSN.Replace(c, '_');
  700. }
  701. string resultStr = result ? "OK" : "NG";
  702. if (is3Dmodel == true)
  703. {
  704. Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.idb";
  705. //Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.idb";
  706. }
  707. else
  708. {
  709. Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.bmp";
  710. //Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp";
  711. }
  712. Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.bmp";
  713. }
  714. if (!Directory.Exists(Path.GetDirectoryName(Originalpath)))
  715. Directory.CreateDirectory(Path.GetDirectoryName(Originalpath));
  716. //using (CogImageFileBMP _cogImageFileTool = new CogImageFileBMP())
  717. //{
  718. // _cogImageFileTool.Open(Originalpath, CogImageFileModeConstants.Write);
  719. // _cogImageFileTool.Append(image);
  720. // _cogImageFileTool.Close();
  721. //}
  722. using (CogImageFile _cogImageFileTool = new CogImageFile())
  723. {
  724. _cogImageFileTool.Open(Originalpath, CogImageFileModeConstants.Write);
  725. _cogImageFileTool.Append(image);
  726. _cogImageFileTool.Close();
  727. }
  728. if (!Directory.Exists(Path.GetDirectoryName(Recordedpath)))
  729. Directory.CreateDirectory(Path.GetDirectoryName(Recordedpath));
  730. if (isCompress)
  731. {
  732. ImageHelper.CompressImage(reimage, Recordedpath, 20);
  733. }
  734. else
  735. {
  736. reimage.Save(Recordedpath);
  737. }
  738. }
  739. }
  740. catch (Exception ex)
  741. {
  742. LogHelper.WriteLogError("保存流程运行结果的图片时出错!", ex);
  743. }
  744. finally
  745. {
  746. // ======================= 【关键修复】无论是否压缩都释放Bitmap =======================
  747. try { reimage?.Dispose(); } catch { }
  748. }
  749. });
  750. }
  751. private void ProductChanged(ProductModel product)
  752. {
  753. this.gridRender.Dispatcher.BeginInvoke(new Action(() =>
  754. {
  755. var is3DEnabled = GetView3DUse();
  756. foreach (var item in vmRenders)
  757. {
  758. try
  759. {
  760. // 2D:永远清理
  761. var display2D = item.Value.Child as Cognex.VisionPro.CogRecordDisplay;
  762. if (display2D != null)
  763. {
  764. display2D.Record = null;
  765. display2D.Image = null;
  766. display2D.StaticGraphics.Clear();
  767. continue;
  768. }
  769. // 3D:仅在启用 3D 时清理
  770. if (!is3DEnabled)
  771. continue;
  772. var display3D = item.Value.Child as Cognex.VisionPro3D.Cog3DDisplayV2WF;
  773. if (display3D != null)
  774. {
  775. display3D.Clear();
  776. }
  777. }
  778. catch (System.Windows.Forms.AxHost.InvalidActiveXStateException)
  779. {
  780. // 控件句柄/ActiveX 未就绪时忽略
  781. }
  782. catch (Exception ex)
  783. {
  784. LogHelper.WriteLogError(Lang.切换产品清除主页图像时出错, ex);
  785. }
  786. }
  787. }));
  788. }
  789. private void OnDisplayDoubleClick(CogRecordDisplay disp)
  790. {
  791. if (disp == null)
  792. return;
  793. try
  794. {
  795. // 直接把当前 CogRecordDisplay 传给对话框 VM(VM 内部读取 Image/Record)
  796. var parameters = new Prism.Services.Dialogs.DialogParameters
  797. {
  798. { "Cog", disp }
  799. };
  800. // Prism Dialog 必须在 WPF UI 线程调用
  801. Dispatcher.BeginInvoke(new Action(() =>
  802. {
  803. try
  804. {
  805. _dialogService.ShowDialog("ImagePreviewWindow", parameters, r => { });
  806. }
  807. catch (Exception ex)
  808. {
  809. LogHelper.WriteLogError("打开 ImagePreviewWindow 失败", ex);
  810. }
  811. }));
  812. }
  813. catch (Exception ex)
  814. {
  815. LogHelper.WriteLogError("双击打开预览窗口失败", ex);
  816. }
  817. }
  818. }
  819. }