using OpenVinoSharp.Extensions; using Sunny.UI; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Reflection.Emit; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using static System.Windows.Forms.VisualStyles.VisualStyleElement.Button; using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window; using static System.Windows.Forms.VisualStyles.VisualStyleElement; using MyCameras; using System.Collections.Concurrent; using MyVision.Forms.Pages; using MyVision.Forms; using MyProcesses; using MyProcesses.Communicators; using Newtonsoft.Json; using SharpCompress.Common; using OpenVinoSharp; using System.Text.RegularExpressions; using HalconDotNet; using MyProcesses.Alogrithms.Halcon; using MyCommunicators; namespace MyVision { /// /// Windows10、Windows11 建议用UIForm2,更接近原生窗体使用体验,用UIForm也可以 /// WindowsXP、Windows7 建议使用UIForm /// public partial class MainForm : UIForm2 { ICamera camera = new MindCamera(); /// /// 相机集合(Key:相机SN,Value:相机句柄) /// ConcurrentDictionary dicCameras = new ConcurrentDictionary(); int CamerasPageIndex = 2000; /// /// 流程集合(Key:相机SN,Value:object为IProcess时,string为ID,object为ICamera时,string为SN) /// ConcurrentDictionary> dicProcesses = new ConcurrentDictionary>(); int ProcessesPageIndex = 3000; /// /// 通讯集合(Key:通讯名,Value:通讯句柄) /// ConcurrentDictionary dicCommunicator = new ConcurrentDictionary(); ConcurrentDictionary allCommunicatorsConnectionString = new ConcurrentDictionary(); string allCommunicatorsConnectionStringPath = ".\\CommunicatorsConnection.json"; public MainForm() { InitializeComponent(); //关联窗体承载多页面框架的容器UITabControl //窗体上如果只有一个UITabControl,也会自动关联,超过一个需要手动关联 this.MainTabControl = uiTabControl1; uiNavBar1.TabControl = uiTabControl1; uiNavMenu1.TabControl = uiTabControl1; //uiNavBar1设置节点,也可以在Nodes属性里配置 uiNavBar1.Nodes.Add("测试"); uiNavBar1.Nodes.Add("相机"); uiNavBar1.Nodes.Add("流程"); uiNavBar1.Nodes.Add("通讯"); uiNavBar1.Nodes.Add("设置"); uiNavBar1.Nodes.Add("主题"); //设置初始页面索引(关联页面,唯一不重复即可) int pageIndex = 1000; uiNavBar1.SetNodePageIndex(uiNavBar1.Nodes[0], pageIndex); uiNavBar1.SetNodeSymbol(uiNavBar1.Nodes[0], 61764); TreeNode parent = uiNavMenu1.CreateNode("测试", 61764, 24, pageIndex); //通过设置GUID关联,节点字体图标和大小由UIPage设置 uiNavMenu1.CreateChildNode(parent, AddPage(new UIPage(), Guid.NewGuid())); //uiNavMenu1.CreateChildNode(parent, AddPage(new FDialogs(), Guid.NewGuid())); //uiNavMenu1.CreateChildNode(parent, AddPage(new FEditor(), Guid.NewGuid())); //uiNavMenu1.CreateChildNode(parent, AddPage(new FFrames(), Guid.NewGuid())); pageIndex = 2000; uiNavBar1.SetNodePageIndex(uiNavBar1.Nodes[1], pageIndex); uiNavBar1.SetNodeSymbol(uiNavBar1.Nodes[1], 61501); parent = uiNavMenu1.CreateNode("相机", 61501, 24, pageIndex); CamerasPageIndex = pageIndex; //通过设置PageIndex关联,节点文字、图标由相应的Page的Text、Symbol提供 int iCameraCount = 0; foreach (var item in ((MindCamera)camera).GetListEnum()) { MindCamera camera = new MindCamera(); if (camera.InitDevice(item.ToString(), this.Handle)) { dicCameras.TryAdd(camera.SN, camera); dicProcesses.TryAdd(camera.SN, new List()); uiNavMenu1.CreateChildNode(parent, AddPage(new CameraPage(dicCameras[camera.SN]), ++pageIndex)); //设置相机连接成功的小绿点提示 uiNavMenu1.SetNodeTipsText(parent.Nodes[iCameraCount], " ", Color.Green, Color.White); } iCameraCount++; } //设置相机连接的个数显示 uiNavMenu1.ShowTips = true; uiNavMenu1.SetNodeTipsText(uiNavMenu1.Nodes[1], iCameraCount.ToString(), iCameraCount == 0 ? Color.Red : Color.Green, Color.White); pageIndex = 3000; uiNavBar1.SetNodePageIndex(uiNavBar1.Nodes[2], pageIndex); uiNavBar1.SetNodeSymbol(uiNavBar1.Nodes[2], 61451); parent = uiNavMenu1.CreateNode("流程", 61451, 24, pageIndex); ProcessesPageIndex = pageIndex; //从数据库中读取流程 ProcessDatabasePage processDatabasePage = new ProcessDatabasePage(dicCameras, dicProcesses); uiNavMenu1.CreateChildNode(parent, AddPage(processDatabasePage, ++pageIndex)); //直接关联(默认自动生成GUID) foreach (var item in dicCameras.Values) { uiNavMenu1.CreateChildNode(parent, AddPage(new ProcessPage(item, processDatabasePage.dicProcesses[((BaseCamera)item).SN], dicCameras, dicCommunicator), ++pageIndex)); } //uiNavMenu1.CreateChildNode(parent, AddPage(new FBarChart())); //uiNavMenu1.CreateChildNode(parent, AddPage(new FDoughnutChart())); //uiNavMenu1.CreateChildNode(parent, AddPage(new FLineChart())); //uiNavMenu1.CreateChildNode(parent, AddPage(new FPieChart())); pageIndex = 4000; uiNavBar1.SetNodePageIndex(uiNavBar1.Nodes[3], pageIndex); uiNavBar1.SetNodeSymbol(uiNavBar1.Nodes[3], 61971); parent = uiNavMenu1.CreateNode("通讯", 61971, 24, pageIndex); //直接关联(默认自动生成GUID) LoadAllCommunicator(); uiNavMenu1.CreateChildNode(parent, AddPage(new CommunicatorsPage(dicCommunicator), ++pageIndex)); //uiNavMenu1.CreateChildNode(parent, AddPage(CreateInstance("Sunny.UI.Demo.FPipe"))); //uiNavMenu1.CreateChildNode(parent, AddPage(CreateInstance("Sunny.UI.Demo.FMeter"))); //uiNavMenu1.CreateChildNode(parent, AddPage(CreateInstance("Sunny.UI.Demo.FLed"))); //uiNavMenu1.CreateChildNode(parent, AddPage(CreateInstance("Sunny.UI.Demo.FLight"))); //uiNavMenu1.CreateChildNode(parent, AddPage(CreateInstance("Sunny.UI.Demo.FSwitch"))); pageIndex = 5000; uiNavBar1.SetNodePageIndex(uiNavBar1.Nodes[4], pageIndex); uiNavBar1.SetNodeSymbol(uiNavBar1.Nodes[4], 61459); parent = uiNavMenu1.CreateNode("设置", 61459, 24, pageIndex); //直接关联(默认自动生成GUID) uiNavMenu1.CreateChildNode(parent, AddPage(new UIPage(), ++pageIndex)); uiNavBar1.SetNodeSymbol(uiNavBar1.Nodes[5], 61502); var styles = UIStyles.PopularStyles(); foreach (UIStyle style in styles) { uiNavBar1.CreateChildNode(uiNavBar1.Nodes[5], style.DisplayText(), style.Value()); } //var node = uiNavBar1.CreateChildNode(uiNavBar1.Nodes[4], "字体图标", 99999); //uiNavBar1.SetNodeSymbol(node, 558426); //node = uiNavBar1.CreateChildNode(uiNavBar1.Nodes[5], "多彩主题", UIStyle.Colorful.Value()); //uiNavBar1.SetNodeSymbol(node, 558295); //左侧导航主节点关联页面 //uiNavMenu1.CreateNode(AddPage(new UIPage(), 99999)); //uiNavMenu1.CreateNode(AddPage(new FSymbols(), 99999)); //uiNavMenu1.CreateNode(AddPage(new FColorful(), UIStyle.Colorful.Value())); //直接增加一个页面,不在左侧列表显示 //AddPage(new FCommon()); //选中第1001个节点("测试节点下的第一个节点") uiNavMenu1.SelectPage(1001); uiPanel2.Text = Text = Version; RegisterHotKey(Sunny.UI.ModifierKeys.Shift, Keys.F8); //根据页面类型获取页面 //FButton page = GetPage(); //if (page != null) // page.Text.WriteConsole(); //根据页面索引获取页面 UIPage page1 = GetPage(1001); if (page1 != null) page1.Text.WriteConsole(); timer1.Start(); timer60.Start(); } public bool LoadAllCommunicator() { if (!File.Exists(allCommunicatorsConnectionStringPath)) { Console.WriteLine("文件不存在创建空文件"); // 获取不带文件名的目录路径 string directoryPath = Path.GetDirectoryName(allCommunicatorsConnectionStringPath); SaveAllCommunicator(); return true; } string strJson = string.Empty; using (StreamReader streamReader = new StreamReader(allCommunicatorsConnectionStringPath, Encoding.UTF8)) { strJson = streamReader.ReadToEnd(); streamReader.Close(); } allCommunicatorsConnectionString = JsonConvert.DeserializeObject>(strJson); if (allCommunicatorsConnectionString == null) { UIMessageBox.ShowError("通讯端口加载失败"); return false; } foreach (var CommunicatorConnectionString in allCommunicatorsConnectionString) { string CommunicatorName = CommunicatorConnectionString.Key; string CommunicatorAddress = CommunicatorConnectionString.Value; // 定义正则表达式以提取协议、IP 地址和端口 //1. \((.*?)\):\(和 \) 是用于匹配括号的转义字符。 // (.*?) 是一个非贪婪的匹配,用来匹配类名(MyProcesses.Communicators.TCPServer 或 MyProcesses.Communicators.UARTPort)。 //2. ([^:] +):匹配冒号之前的部分,即地址(127.0.0.1 或 COM5)。这里使用了[^:] 来匹配除了冒号之外的任意字符。 //3. (\d +) :匹配端口号,确保它匹配一个或多个数字。 var regex = new Regex(@"\((.*?)\)([^:]+):(\d+)"); var match = regex.Match(CommunicatorAddress); if (match.Success) { string ClassName = match.Groups[1].Value; // "TCP" string IP = match.Groups[2].Value; // "127.0.0.1" string PORT = match.Groups[3].Value; // "1111" if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(PORT)) break; //利用反射创建实例 Type type = ICommunicator.GetExecutingAssembly().GetType(ClassName); if (type == null) { Console.WriteLine("Class not found."); return false; } var Communicator = Activator.CreateInstance(type) as BaseCommunicator; if (Communicator == null) { Console.WriteLine("BaseCommunicator not found."); return false; } Communicator.CommunicatorConnections.Add("名称", CommunicatorName); Communicator.CommunicatorConnections.Add("地址", IP); Communicator.CommunicatorConnections.Add("端口", PORT); if (!Communicator.Connect()) UIMessageBox.ShowError(Communicator.strMsg); dicCommunicator.TryAdd(CommunicatorName, Communicator); } else { Console.WriteLine("No match found."); } } return true; } public bool SaveAllCommunicator() { try { string strJson = string.Empty; allCommunicatorsConnectionString = new ConcurrentDictionary(); foreach (var item in dicCommunicator) { string ClassName = item.Value.GetType().FullName;// "TCP" string IP = item.Value.CommunicatorConnections["地址"].ToString();//"127.0.0.1" string PORT = item.Value.CommunicatorConnections["端口"].ToString();//"1111" if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(PORT)) break; string CommunicatorConnectionString = $"({ClassName}){IP}:{PORT}"; allCommunicatorsConnectionString.TryAdd(item.Key, CommunicatorConnectionString); } strJson = JsonConvert.SerializeObject(allCommunicatorsConnectionString); BaseCommunicator.JsonFormatting(ref strJson); //判断文件夹是否存在,防呆输入为文件名称 string directoryPath = Path.GetDirectoryName(allCommunicatorsConnectionStringPath); if (!Directory.Exists(directoryPath)) { try { Directory.CreateDirectory(directoryPath); } catch (Exception) { } } File.WriteAllText(allCommunicatorsConnectionStringPath, strJson, Encoding.UTF8); return true; } catch { return false; } } /// /// 创建对象实例 /// /// /// 命名空间.类型名 /// public static T CreateInstance(string fullName) { Type o = Type.GetType(fullName); dynamic obj = Activator.CreateInstance(o, true); return (T)obj;//类型转换并返回 } int lastMenuIndex = 0; private void uiNavBar1_MenuItemClick(string itemText, int menuIndex, int pageIndex) { switch (lastMenuIndex) { //第一个节点是相机 //上一个节点是相机的话需要取消显示回调 case 1: for (int i = CamerasPageIndex + 1; ; i++) { //根据页面索引获取页面 object page1 = GetPage(i); if (page1 == null) break; if (page1 is CameraPage) { ((CameraPage)page1).Unsubscribe(); ((CameraPage)page1).StopContinueGrabbing(); } } break; default: break; } switch (menuIndex) { //第一个节点是相机 //当前选择的节点是相机的话需要重新加载显示回调 case 1: //根据页面索引获取页面 object page1 = GetPage(pageIndex); if (page1 == null) break; if (page1 is CameraPage) ((CameraPage)page1).Subscribe(); break; //第五个节点是切换语言 case 5: UIStyle style = (UIStyle)pageIndex; if (pageIndex < UIStyle.Colorful.Value()) StyleManager.Style = style; else uiNavMenu1.SelectPage(pageIndex); break; default: uiNavMenu1.SelectPage(pageIndex); break; } lastMenuIndex = menuIndex; } int lastPageIndex = 0; private void uiNavMenu1_MenuItemClick(TreeNode node, NavMenuItem item, int pageIndex) { //上一个节点是相机的话需要取消显示回调 if (lastPageIndex >= 2000 && lastPageIndex < 3000) { //根据页面索引获取页面 object page1 = GetPage(lastPageIndex); if (page1 == null) return; if (page1 is CameraPage) { ((CameraPage)page1).Unsubscribe(); ((CameraPage)page1).StopContinueGrabbing(); } } //上一个节点是相机的话需要取消显示回调 if (lastPageIndex >= 3000 && lastPageIndex < 4000) { //根据页面索引获取页面 object page1 = GetPage(lastPageIndex); if (page1 == null) return; if (page1 is ProcessPage) { ((ProcessPage)page1).Unsubscribe(); } } //当前选择的节点是相机的话需要重新加载显示回调 if (pageIndex >= 2000 && pageIndex < 3000) { //根据页面索引获取页面 object page1 = GetPage(pageIndex); if (page1 == null) return; if (page1 is CameraPage) ((CameraPage)page1).Subscribe(); } lastPageIndex = pageIndex; } private void Form1_PageSelected(object sender, UIPageEventArgs e) { if (e.Page != null) Console.WriteLine(e.Page.Text); } private void 关于ToolStripMenuItem1_Click(object sender, EventArgs e) { UIMessageBox.Show(Version, "关于", Style, UIMessageBoxButtons.OK, false); } private void 关于ToolStripMenuItem_Click(object sender, EventArgs e) { Process.Start("https://gitee.com/yhuse/SunnyUI"); } private void Form1_HotKeyEventHandler(object sender, HotKeyEventArgs e) { if (e.hotKey.ModifierKey == Sunny.UI.ModifierKeys.Shift && e.hotKey.Key == Keys.F8) { this.ShowInfoTip("您按下了全局系统热键 Shift+F8"); } } private void Form1_ReceiveParams(object sender, UIPageParamsArgs e) { Text = e.Value.ToString(); SendParamToPage(1001, "传值给页面"); } private void timer1_Tick(object sender, EventArgs e) { uiPanel3.Text = DateTime.Now.ToString(); } private void timer60_Tick(object sender, EventArgs e) { bLogin = false; } private void NZhCN_Click(object sender, EventArgs e) { UIStyles.CultureInfo = CultureInfos.zh_CN; } private void NZhTW_Click(object sender, EventArgs e) { UIStyles.CultureInfo = CultureInfos.zh_TW; } private void NEnUS_Click(object sender, EventArgs e) { UIStyles.CultureInfo = CultureInfos.en_US; } /// /// 重载多语翻译 /// public override void Translate() { //必须保留 base.Translate(); //读取翻译代码中的多语资源 CodeTranslator.Load(this); //设置多语资源 //this.CloseAskString = CodeTranslator.Current.CloseAskString; //this.uiNavMenu1.Nodes[0].Text = this.uiNavBar1.Nodes[0].Text = CodeTranslator.Current.Controls; //this.uiNavMenu1.Nodes[1].Text = this.uiNavBar1.Nodes[1].Text = CodeTranslator.Current.Forms; //this.uiNavMenu1.Nodes[2].Text = this.uiNavBar1.Nodes[2].Text = CodeTranslator.Current.Charts; //this.uiNavMenu1.Nodes[3].Text = this.uiNavBar1.Nodes[3].Text = CodeTranslator.Current.Industrial; //this.uiNavBar1.Nodes[4].Text = CodeTranslator.Current.Theme; //this.uiNavMenu1.Nodes[4].Text = CodeTranslator.Current.Symbols; //this.uiNavMenu1.Nodes[5].Text = CodeTranslator.Current.Colorful; this.uiNavBar1.Invalidate(); this.uiNavMenu1.Invalidate(); } private class CodeTranslator : IniCodeTranslator { public string CloseAskString { get; set; } = "您确认要退出程序吗?"; public string Controls { get; set; } = "相机"; public string Forms { get; set; } = "窗体"; public string Charts { get; set; } = "图表"; public string Industrial { get; set; } = "工控"; public string Theme { get; set; } = "主题"; public string Symbols { get; set; } = "字体图标"; public string Colorful { get; set; } = "多彩主题"; } bool bLogin = false; private void uiAvatar1_DoubleClick(object sender, EventArgs e) { LoginForm loginForm = new LoginForm(); loginForm.ShowDialog(); bLogin = loginForm.IsLogin; } private void MainForm_FormClosed(object sender, FormClosedEventArgs e) { foreach (ICamera camera in dicCameras.Values) { camera.Dispose(); } SaveAllCommunicator(); foreach (BaseCommunicator communicator in dicCommunicator.Values) { //communicator.Dispose(); communicator.Disconnect(); } } } }