alielie
2025-03-18 a061384ba628a09bf4df91f50321ab22c03129aa
Winform支持遮罩层;
54个文件已修改
23个文件已添加
2210 ■■■■■ 已修改文件
HMI.AlermInfoManage/HMI.AlarmInfoManage.csproj 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.AlermInfoManage/packages.config 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.Base/HMI.Base.csproj 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.Base/PluginControl.cs 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.Base/PluginInfo.cs 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.Base/PluginLoader.cs 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.Base/packages.config 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.Core/Api/IFolderOwner.cs 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.Core/Api/IPlugin.cs 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.Core/Api/PluginPackage.cs 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.Core/HMI.Core.csproj 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.Core/packages.config 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.DataViewer/HMI.DataViewer.csproj 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.DataViewer/packages.config 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.IOMonitor/HMI.IOMonitor.csproj 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.IOMonitor/IOMonitor.xaml.cs 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.IOMonitor/packages.config 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.LogViewer/HMI.LogViewer.csproj 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.LogViewer/packages.config 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.MenuManage/HMI.MenuManage.csproj 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.MenuManage/Modal/MenuModal.xaml 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.MenuManage/packages.config 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.ParameterManage/HMI.ParameterManage.csproj 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.ParameterManage/SettingModal.xaml.cs 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.ParameterManage/TestItem.xaml.cs 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.ParameterManage/packages.config 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.SettingControl/HMI.SettingControl.csproj 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.SettingControl/packages.config 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.UI/Converter/VisibilityBoolConverter.cs 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.UI/HMI.UI.csproj 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.UI/Style/Colors.xaml 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.UI/Style/MsgBoxStyle.xaml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.UI/Style/PanuonResource.xaml 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.UI/Util/MsgBoxHelper2.cs 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.UI/Util/ToastHelper.cs 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.UI/packages.config 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.UnitTest/HMI.UnitTest.csproj 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.UnitTest/packages.config 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Libs/Microsoft.DwayneNeed.Win32.dll 补丁 | 查看 | 原始文档 | blame | 历史
Libs/Microsoft.DwayneNeed.dll 补丁 | 查看 | 原始文档 | blame | 历史
Plugin.ServoManage/Plugin.ServoManage.csproj 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugin.ServoManage/Properties/AssemblyInfo.cs 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugin.ServoManage/Properties/Resources.Designer.cs 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugin.ServoManage/Properties/Resources.resx 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugin.ServoManage/Properties/Settings.Designer.cs 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugin.ServoManage/Properties/Settings.settings 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugin.ServoManage/ServoManage.xaml 371 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugin.ServoManage/ServoManage.xaml.cs 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugin.ServoManage/packages.config 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugin.TestResult/DataTable.xaml.cs 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugin.TestResult/Plugin.TestResult.csproj 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugin.TestResult/TestResultView.xaml.cs 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugin.TestResult/app.config 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugin.TestResult/packages.config 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugin.TsExecution/Plugin.TsExecution.csproj 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugin.TsExecution/TsExecution.xaml.cs 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugin.TsExecution/packages.config 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject/App.config 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject/App.xaml 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject/App.xaml.cs 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject/Controls/HolderForm.Designer.cs 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject/Controls/HolderForm.cs 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject/Controls/HolderForm.resx 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject/Controls/MainTabControl.xaml 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject/Controls/MainTabControl.xaml.cs 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject/Controls/MaskControl.Designer.cs 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject/Controls/MaskControl.cs 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject/Controls/MenuTabControl.xaml.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject/Controls/WinFormHolder.xaml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject/Controls/WinFormHolder.xaml.cs 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject/Lang/zh-CN/ServoManage.json 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject/PanuonWindow.xaml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject/PanuonWindow.xaml.cs 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject/TextFile1.txt 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject/WPFProject.csproj 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject/WPFProject.sln 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject/packages.config 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HMI.AlermInfoManage/HMI.AlarmInfoManage.csproj
@@ -53,8 +53,8 @@
    <Reference Include="ICSharpCode.SharpZipLib, Version=1.0.0.999, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\SharpZipLib.1.0.0\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
    </Reference>
    <Reference Include="log4net, Version=3.0.3.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.3\lib\net462\log4net.dll</HintPath>
    <Reference Include="log4net, Version=3.0.4.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.4\lib\net462\log4net.dll</HintPath>
    </Reference>
    <Reference Include="NPOI, Version=2.4.1.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\NPOI.2.4.1\lib\net45\NPOI.dll</HintPath>
@@ -69,7 +69,7 @@
      <HintPath>..\WPFProject\packages\NPOI.2.4.1\lib\net45\NPOI.OpenXmlFormats.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF, Version=1.1.2.2, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.2.2\lib\net472\Panuon.WPF.dll</HintPath>
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.3\lib\net472\Panuon.WPF.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF.UI, Version=1.2.4.8, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.UI.1.2.4.9\lib\net472\Panuon.WPF.UI.dll</HintPath>
HMI.AlermInfoManage/packages.config
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="log4net" version="3.0.3" targetFramework="net472" />
  <package id="log4net" version="3.0.4" targetFramework="net472" />
  <package id="NPOI" version="2.4.1" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.2.2" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.3" targetFramework="net472" />
  <package id="Panuon.WPF.UI" version="1.2.4.9" targetFramework="net472" />
  <package id="SharpZipLib" version="1.0.0" targetFramework="net472" />
</packages>
HMI.Base/HMI.Base.csproj
@@ -50,8 +50,8 @@
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="log4net, Version=3.0.3.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.3\lib\net462\log4net.dll</HintPath>
    <Reference Include="log4net, Version=3.0.4.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.4\lib\net462\log4net.dll</HintPath>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Configuration" />
HMI.Base/PluginControl.cs
@@ -31,19 +31,19 @@
        protected ILog log;
        protected string BaseFolder;
        public virtual object Active()
        public virtual void Active()
        {
            return null;
        }
        public virtual object DeActive()
        public virtual void DeActive()
        {
            return null;
        }
        public virtual object Init()
        public virtual void Init()
        {
            return null;
        }
        public virtual void OnTabChange(object sender, object args)
@@ -63,12 +63,12 @@
        public virtual void InitFinish()
        {
        }
        public virtual void OnClose(object sender, CancelEventArgs e)
        {
        }
        public virtual void DoClose(object sender, EventArgs e)
HMI.Base/PluginInfo.cs
@@ -1,4 +1,5 @@
using System.Collections.ObjectModel;
using HMI.Core.Api;
using System.Collections.ObjectModel;
using System.Windows.Media.Imaging;
namespace HMI.Base
@@ -12,6 +13,7 @@
        public bool IsFont { get; set; }
        public string Code { get; set; }
        public string Name { get; set; }
        public string Type { get; set; }
        public string ParentCode { get; set; }
        public string DllPath { get; set; }
        public string ClassName { get; set; }
HMI.Base/PluginLoader.cs
@@ -97,31 +97,36 @@
                        {
                            string dllPath = Path.Combine(PluginFolder, menu.DllPath);
                            Assembly ass = Assembly.LoadFrom(dllPath);
                            var tss = ass.GetTypes();
                            Type ClassType = ass.GetType(menu.ClassName);
                            object Instance = Activator.CreateInstance(ClassType);
                            menu.Content = Instance;
                            if (Instance is IPlugin plugin)
                            {
                                plugin.SetLogger(LogManager.GetLogger(menu.Code));
                                string configFolder = Path.Combine(PathHelper.ConfigFolder, menu.Code);
                                if (!Directory.Exists(configFolder))
                            }
                            else
                            {
                                plugin = new PluginPackage(Instance);
                            }
                            plugin.SetLogger(LogManager.GetLogger(menu.Code));
                            string configFolder = Path.Combine(PathHelper.ConfigFolder, menu.Code);
                            if (!Directory.Exists(configFolder))
                            {
                                Directory.CreateDirectory(configFolder);
                            }
                            plugin.SetBaseFolder(configFolder);
                            plugin.InitFinish();
                            pluginContainer.OnCloseEvent += plugin.OnClose;
                            pluginContainer.DoCloseEvent += plugin.DoClose;
                            Type SettingType = ass.GetType($"{menu.ClassName}_Setting");
                            if (SettingType != null)
                            {
                                object SettingInstance = Activator.CreateInstance(SettingType);
                                if (SettingInstance is IFolderOwner fo)
                                {
                                    Directory.CreateDirectory(configFolder);
                                    fo.SetBaseFolder(configFolder);
                                }
                                plugin.SetBaseFolder(configFolder);
                                plugin.InitFinish();
                                pluginContainer.OnCloseEvent += plugin.OnClose;
                                pluginContainer.DoCloseEvent += plugin.DoClose;
                                Type SettingType = ass.GetType($"{menu.ClassName}_Setting");
                                if (SettingType != null)
                                {
                                    object SettingInstance = Activator.CreateInstance(SettingType);
                                    if (SettingInstance is IFolderOwner fo)
                                    {
                                        fo.SetBaseFolder(configFolder);
                                    }
                                    menu.SettingControl = SettingInstance;
                                }
                                menu.SettingControl = SettingInstance;
                            }
                        }
                        LoadMessageAppend?.Invoke(this,
@@ -184,6 +189,7 @@
                            {
                                Code = dr["code"].ToString(),
                                Name = dr["name"].ToString(),
                                Type = dr["type"].ToString(),
                                ParentCode = dr["parentCode"].ToString(),
                                DllPath = dr["dllPath"].ToString(),
                                ClassName = dr["className"].ToString(),
HMI.Base/packages.config
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="log4net" version="3.0.3" targetFramework="net472" />
  <package id="log4net" version="3.0.4" targetFramework="net472" />
</packages>
HMI.Core/Api/IFolderOwner.cs
@@ -8,6 +8,10 @@
{
    public interface IFolderOwner
    {
        /// <summary>
        /// 基础路径
        /// </summary>
        /// <param name="folder"></param>
        void SetBaseFolder(string folder);
    }
}
HMI.Core/Api/IPlugin.cs
@@ -10,32 +10,29 @@
        /// 初始化
        /// </summary>
        /// <returns></returns>
        object Init();
        void Init();
        /// <summary>
        /// 初始化完成(执行完构造器)
        /// 初始化完成(执行完构造器,并且设置好logger folder等资源之后执行)
        /// </summary>
        void InitFinish();
        /// <summary>
        /// 插件面板被激活时的操作
        /// 插件被激活时的操作
        /// </summary>
        /// <returns></returns>
        object Active();
        void Active();
        /// <summary>
        /// 失活时的操作
        /// </summary>
        /// <returns></returns>
        object DeActive();
        void DeActive();
        /// <summary>
        /// 面板切换事件
        /// 分配日志logger(log4net)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        void OnTabChange(object sender, object args);
        /// <param name="logger"></param>
        void SetLogger(ILog logger);
        /// <summary>
@@ -49,5 +46,17 @@
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void DoClose(object sender, EventArgs e);
        /// <summary>
        /// 面板切换事件(预留)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        void OnTabChange(object sender, object args);
        /// <summary>
        /// 插件加载完之后会分配一个路径,可以存放一些独立的文件
        /// </summary>
        /// <param name="folder"></param>
        void SetBaseFolder(string folder);
    }
}
HMI.Core/Api/PluginPackage.cs
New file
@@ -0,0 +1,97 @@
using log4net;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Web.UI.WebControls;
namespace HMI.Core.Api
{
    public class PluginPackage : IPlugin
    {
        public static Dictionary<object, IPlugin> Cache = new Dictionary<object, IPlugin>();
        public static IPlugin Get(object obj)
        {
            if(obj is null) return null;
            if (obj is IPlugin plugin)
            {
                return plugin;
            }
            if (Cache.ContainsKey(obj)) return Cache[obj];
            PluginPackage pluginPackage = new PluginPackage(obj);
            Cache.Add(obj, pluginPackage);
            return pluginPackage;
        }
        private object Content;
        private MethodInfo ActiveMethod;
        private MethodInfo DeActiveMethod;
        private MethodInfo DoCloseMethod;
        private MethodInfo InitMethod;
        private MethodInfo InitFinishMethod;
        private MethodInfo OnCloseMethod;
        private MethodInfo OnTabChangeMethod;
        private MethodInfo SetBaseFolderMethod;
        private MethodInfo SetLoggerMethod;
        public PluginPackage(object content)
        {
            this.Content = content;
            ActiveMethod = content.GetType().GetMethod("Active");
            DeActiveMethod = content.GetType().GetMethod("DeActive");
            DoCloseMethod = content.GetType().GetMethod("DoClose", new Type[] { typeof(object), typeof(EventArgs) });
            InitMethod = content.GetType().GetMethod("Init");
            InitFinishMethod = content.GetType().GetMethod("InitFinish");
            OnCloseMethod = content.GetType().GetMethod("OnClose", new Type[] { typeof(object), typeof(CancelEventArgs) });
            OnTabChangeMethod = content.GetType().GetMethod("OnTabChange", new Type[] { typeof(object), typeof(object) });
            SetBaseFolderMethod = content.GetType().GetMethod("SetBaseFolder", new Type[] { typeof(string) });
            SetLoggerMethod = content.GetType().GetMethod("SetLogger", new Type[] { typeof(ILog) });
        }
        public void Active()
        {
            ActiveMethod?.Invoke(Content, null);
        }
        public void DeActive()
        {
            DeActiveMethod?.Invoke(Content, null);
        }
        public void DoClose(object sender, EventArgs e)
        {
            DoCloseMethod?.Invoke(Content, new object[] { sender, e });
        }
        public void Init()
        {
            InitMethod?.Invoke(Content, null);
        }
        public void InitFinish()
        {
            InitFinishMethod?.Invoke(Content, null);
        }
        public void OnClose(object sender, CancelEventArgs e)
        {
            OnCloseMethod?.Invoke(Content, new object[] { sender, e });
        }
        public void OnTabChange(object sender, object args)
        {
            OnTabChangeMethod?.Invoke(Content, new object[] { sender, args });
        }
        public void SetBaseFolder(string folder)
        {
            SetBaseFolderMethod?.Invoke(Content, new object[] { folder });
        }
        public void SetLogger(ILog logger)
        {
            SetLoggerMethod?.Invoke(Content, new object[] { logger });
        }
    }
}
HMI.Core/HMI.Core.csproj
@@ -52,8 +52,8 @@
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="log4net, Version=3.0.3.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.3\lib\net462\log4net.dll</HintPath>
    <Reference Include="log4net, Version=3.0.4.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.4\lib\net462\log4net.dll</HintPath>
    </Reference>
    <Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
@@ -96,6 +96,7 @@
    <Compile Include="Api\IStep.cs" />
    <Compile Include="Api\IStepRunner.cs" />
    <Compile Include="Annotation\InitAttribute.cs" />
    <Compile Include="Api\PluginPackage.cs" />
    <Compile Include="Entity\LangInfo.cs" />
    <Compile Include="Entity\NotifyBase.cs" />
    <Compile Include="Entity\Param.cs" />
HMI.Core/packages.config
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="log4net" version="3.0.3" targetFramework="net472" />
  <package id="log4net" version="3.0.4" targetFramework="net472" />
  <package id="Newtonsoft.Json" version="13.0.3" targetFramework="net472" />
</packages>
HMI.DataViewer/HMI.DataViewer.csproj
@@ -53,8 +53,8 @@
    <Reference Include="ICSharpCode.SharpZipLib, Version=1.0.0.999, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\SharpZipLib.1.0.0\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
    </Reference>
    <Reference Include="log4net, Version=3.0.3.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.3\lib\net462\log4net.dll</HintPath>
    <Reference Include="log4net, Version=3.0.4.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.4\lib\net462\log4net.dll</HintPath>
    </Reference>
    <Reference Include="NPOI, Version=2.4.1.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\NPOI.2.4.1\lib\net45\NPOI.dll</HintPath>
@@ -69,7 +69,7 @@
      <HintPath>..\WPFProject\packages\NPOI.2.4.1\lib\net45\NPOI.OpenXmlFormats.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF, Version=1.1.2.2, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.2.2\lib\net472\Panuon.WPF.dll</HintPath>
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.3\lib\net472\Panuon.WPF.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF.UI, Version=1.2.4.8, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.UI.1.2.4.9\lib\net472\Panuon.WPF.UI.dll</HintPath>
HMI.DataViewer/packages.config
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="log4net" version="3.0.3" targetFramework="net472" />
  <package id="log4net" version="3.0.4" targetFramework="net472" />
  <package id="NPOI" version="2.4.1" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.2.2" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.3" targetFramework="net472" />
  <package id="Panuon.WPF.UI" version="1.2.4.9" targetFramework="net472" />
  <package id="SharpZipLib" version="1.0.0" targetFramework="net472" />
</packages>
HMI.IOMonitor/HMI.IOMonitor.csproj
@@ -53,8 +53,8 @@
    <Reference Include="ICSharpCode.SharpZipLib, Version=1.0.0.999, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\SharpZipLib.1.0.0\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
    </Reference>
    <Reference Include="log4net, Version=3.0.3.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.3\lib\net462\log4net.dll</HintPath>
    <Reference Include="log4net, Version=3.0.4.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.4\lib\net462\log4net.dll</HintPath>
    </Reference>
    <Reference Include="NPOI, Version=2.4.1.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\NPOI.2.4.1\lib\net45\NPOI.dll</HintPath>
@@ -72,7 +72,7 @@
      <HintPath>..\Libs\OpcInterface.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF, Version=1.1.2.2, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.2.2\lib\net472\Panuon.WPF.dll</HintPath>
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.3\lib\net472\Panuon.WPF.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF.UI, Version=1.2.4.8, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.UI.1.2.4.9\lib\net472\Panuon.WPF.UI.dll</HintPath>
HMI.IOMonitor/IOMonitor.xaml.cs
@@ -416,7 +416,7 @@
            this.DataFilePath = Path.Combine(BaseFolder, "Data.xml");
        }
        public override object Active()
        public override void Active()
        {
            try
            {
@@ -454,7 +454,6 @@
                log.Error("Active Execute Failed.", ex);
                MsgBoxHelper.ErrorMessage(this, $"{this.lang("DIO.ActivateFailed")}: {ex.Message}");
            }
            return null;
        }
        private void CollectionViewSource_Filter(object sender, System.Windows.Data.FilterEventArgs e)
HMI.IOMonitor/packages.config
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="log4net" version="3.0.3" targetFramework="net472" />
  <package id="log4net" version="3.0.4" targetFramework="net472" />
  <package id="NPOI" version="2.4.1" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.2.2" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.3" targetFramework="net472" />
  <package id="Panuon.WPF.UI" version="1.2.4.9" targetFramework="net472" />
  <package id="SharpZipLib" version="1.0.0" targetFramework="net472" />
</packages>
HMI.LogViewer/HMI.LogViewer.csproj
@@ -50,11 +50,11 @@
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="log4net, Version=3.0.3.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.3\lib\net462\log4net.dll</HintPath>
    <Reference Include="log4net, Version=3.0.4.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.4\lib\net462\log4net.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF, Version=1.1.2.2, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.2.2\lib\net472\Panuon.WPF.dll</HintPath>
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.3\lib\net472\Panuon.WPF.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF.UI, Version=1.2.4.8, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.UI.1.2.4.9\lib\net472\Panuon.WPF.UI.dll</HintPath>
HMI.LogViewer/packages.config
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="log4net" version="3.0.3" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.2.2" targetFramework="net472" />
  <package id="log4net" version="3.0.4" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.3" targetFramework="net472" />
  <package id="Panuon.WPF.UI" version="1.2.4.9" targetFramework="net472" />
</packages>
HMI.MenuManage/HMI.MenuManage.csproj
@@ -53,14 +53,14 @@
    <Reference Include="DatabaseHelper">
      <HintPath>..\Libs\DatabaseHelper.dll</HintPath>
    </Reference>
    <Reference Include="log4net, Version=3.0.3.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.3\lib\net462\log4net.dll</HintPath>
    <Reference Include="log4net, Version=3.0.4.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.4\lib\net462\log4net.dll</HintPath>
    </Reference>
    <Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF, Version=1.1.2.2, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.2.2\lib\net472\Panuon.WPF.dll</HintPath>
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.3\lib\net472\Panuon.WPF.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF.UI, Version=1.2.4.8, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.UI.1.2.4.9\lib\net472\Panuon.WPF.UI.dll</HintPath>
HMI.MenuManage/Modal/MenuModal.xaml
@@ -58,6 +58,7 @@
                          Style="{StaticResource InputFormGroupStyle}" Header="{DynamicResource HMI.Menu.Type}" GroupName="MyFormGroup">
                <ComboBox x:Name="TbType" Style="{StaticResource FormComboxStyle}">
                    <ComboBoxItem>WPF</ComboBoxItem>
                    <ComboBoxItem>WinForm</ComboBoxItem>
                    <ComboBoxItem>LV</ComboBoxItem>
                </ComboBox>
            </pu:FormGroup>
HMI.MenuManage/packages.config
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="log4net" version="3.0.3" targetFramework="net472" />
  <package id="log4net" version="3.0.4" targetFramework="net472" />
  <package id="Newtonsoft.Json" version="13.0.3" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.2.2" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.3" targetFramework="net472" />
  <package id="Panuon.WPF.UI" version="1.2.4.9" targetFramework="net472" />
</packages>
HMI.ParameterManage/HMI.ParameterManage.csproj
@@ -50,18 +50,20 @@
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="log4net">
      <HintPath>..\WPFProject\packages\log4net.3.0.3\lib\net462\log4net.dll</HintPath>
    <Reference Include="log4net, Version=3.0.4.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.4\lib\net462\log4net.dll</HintPath>
    </Reference>
    <Reference Include="NPOI, Version=2.4.1.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1" />
    <Reference Include="Panuon.WPF">
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.2.2\lib\net472\Panuon.WPF.dll</HintPath>
    <Reference Include="Panuon.WPF, Version=1.1.2.2, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.3\lib\net472\Panuon.WPF.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF.UI">
    <Reference Include="Panuon.WPF.UI, Version=1.2.4.8, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.UI.1.2.4.9\lib\net472\Panuon.WPF.UI.dll</HintPath>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Configuration" />
    <Reference Include="System.Data" />
    <Reference Include="System.Web" />
    <Reference Include="System.Xml" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Core" />
@@ -152,6 +154,7 @@
      <Generator>ResXFileCodeGenerator</Generator>
      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
    </EmbeddedResource>
    <None Include="packages.config" />
    <None Include="Properties\Settings.settings">
      <Generator>SettingsSingleFileGenerator</Generator>
      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
HMI.ParameterManage/SettingModal.xaml.cs
@@ -67,7 +67,8 @@
        public bool ValidateName(object value, out string err)
        {
            err = null;
            if (Datasource?.FirstOrDefault(e => e.Name == value.ToString()) != null)
            var data = Datasource?.FirstOrDefault(e => e.Name == value.ToString());
            if (data != null && data != Data)
            {
                err = this.lang("App.MustBeUnique", this.lang("Pm.Parameter.Name"));
                return false;
HMI.ParameterManage/TestItem.xaml.cs
@@ -52,7 +52,7 @@
        bool isActivated;
        public static string FileFolder { get; private set; }
        public override object Active()
        public override void Active()
        {
            if (!isActivated)
            {
@@ -62,7 +62,6 @@
                FileFolder = folder;
                isActivated = true;
            }
            return null;
        }
        private void Button_Click(object sender, RoutedEventArgs e)
HMI.ParameterManage/packages.config
New file
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="log4net" version="3.0.4" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.3" targetFramework="net472" />
  <package id="Panuon.WPF.UI" version="1.2.4.9" targetFramework="net472" />
</packages>
HMI.SettingControl/HMI.SettingControl.csproj
@@ -50,11 +50,11 @@
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="log4net, Version=3.0.3.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.3\lib\net462\log4net.dll</HintPath>
    <Reference Include="log4net, Version=3.0.4.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.4\lib\net462\log4net.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF, Version=1.1.2.2, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.2.2\lib\net472\Panuon.WPF.dll</HintPath>
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.3\lib\net472\Panuon.WPF.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF.UI, Version=1.2.4.8, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.UI.1.2.4.9\lib\net472\Panuon.WPF.UI.dll</HintPath>
HMI.SettingControl/packages.config
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="log4net" version="3.0.3" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.2.2" targetFramework="net472" />
  <package id="log4net" version="3.0.4" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.3" targetFramework="net472" />
  <package id="Panuon.WPF.UI" version="1.2.4.9" targetFramework="net472" />
</packages>
HMI.UI/Converter/VisibilityBoolConverter.cs
New file
@@ -0,0 +1,24 @@
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace HMI.UI.Converter
{
    public class VisibilityBoolConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is bool flag && flag == true)
            {
                return Visibility.Visible;
            }
            return Visibility.Collapsed;
        }
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }
    }
}
HMI.UI/HMI.UI.csproj
@@ -59,7 +59,7 @@
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="Panuon.WPF, Version=1.1.2.2, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.2.2\lib\net472\Panuon.WPF.dll</HintPath>
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.3\lib\net472\Panuon.WPF.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF.UI, Version=1.2.4.8, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.UI.1.2.4.9\lib\net472\Panuon.WPF.UI.dll</HintPath>
@@ -80,6 +80,7 @@
    <Reference Include="PresentationFramework" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Converter\VisibilityBoolConverter.cs" />
    <Compile Include="Converter\DataGridRowFlagConverter.cs" />
    <Compile Include="Converter\DataGridRowNumberConverter.cs" />
    <Compile Include="Converter\PathImageConverter.cs" />
@@ -100,6 +101,7 @@
    <Compile Include="Util\IValueValidator.cs" />
    <Compile Include="Util\MaskHolder.cs" />
    <Compile Include="Util\MsgBoxHelper.cs" />
    <Compile Include="Util\MsgBoxHelper2.cs" />
    <Compile Include="Util\ToastHelper.cs" />
    <Resource Include="Resources\Font\Font.xaml">
      <Generator>MSBuild:Compile</Generator>
@@ -173,6 +175,5 @@
      <Name>HMI.Core</Name>
    </ProjectReference>
  </ItemGroup>
  <ItemGroup />
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
HMI.UI/Style/Colors.xaml
@@ -66,8 +66,32 @@
        <GradientStop Color="#aa0e00" Offset="1"/>
    </LinearGradientBrush>
    <RadialGradientBrush x:Key="Normal" GradientOrigin="0.5,0.5"
                             RadiusX="0.75"
                             RadiusY="0.75">
        <RadialGradientBrush.GradientStops>
            <GradientStop Color="White" Offset="0" />
            <GradientStop Color="Gray" Offset="0.7" />
            <GradientStop Color="Gray" Offset="1" />
        </RadialGradientBrush.GradientStops>
    </RadialGradientBrush>
    <RadialGradientBrush x:Key="Ok" GradientOrigin="0.5,0.5"
                                 RadiusX="0.75"
                                 RadiusY="0.75">
        <RadialGradientBrush.GradientStops>
            <GradientStop Color="White" Offset="0" />
            <GradientStop Color="Green" Offset="1" />
        </RadialGradientBrush.GradientStops>
    </RadialGradientBrush>
    <RadialGradientBrush x:Key="Ng" GradientOrigin="0.5,0.5"
                             RadiusX="0.75"
                             RadiusY="0.75">
        <RadialGradientBrush.GradientStops>
            <GradientStop Color="White" Offset="0" />
            <GradientStop Color="Red" Offset="1" />
        </RadialGradientBrush.GradientStops>
    </RadialGradientBrush>
</ResourceDictionary>
HMI.UI/Style/MsgBoxStyle.xaml
@@ -11,6 +11,8 @@
            <Style TargetType="pu:WindowX" BasedOn="{StaticResource {x:Static pu:MessageBoxX.WindowXStyleKey}}">
                <Setter Property="pu:WindowXCaption.Background" Value="{StaticResource WarningColor}" />
                <Setter Property="pu:WindowXCaption.Foreground" Value="{StaticResource WarningColorContract}" />
                <Setter Property="Width" Value="350" />
                <Setter Property="Height" Value="200" />
            </Style>
        </pu:MessageBoxXSettings.WindowXStyle>
@@ -47,6 +49,8 @@
            <Style TargetType="pu:WindowX" BasedOn="{StaticResource {x:Static pu:MessageBoxX.WindowXStyleKey}}">
                <Setter Property="pu:WindowXCaption.Background" Value="{StaticResource DangerColor}" />
                <Setter Property="pu:WindowXCaption.Foreground" Value="{StaticResource DangerColorContrast}" />
                <Setter Property="Width" Value="350" />
                <Setter Property="Height" Value="200" />
            </Style>
        </pu:MessageBoxXSettings.WindowXStyle>
@@ -83,6 +87,8 @@
            <Style TargetType="pu:WindowX" BasedOn="{StaticResource {x:Static pu:MessageBoxX.WindowXStyleKey}}">
                <Setter Property="pu:WindowXCaption.Background" Value="{StaticResource PrimaryColor}" />
                <Setter Property="pu:WindowXCaption.Foreground" Value="{StaticResource PrimaryColorContract}" />
                <Setter Property="Width" Value="350" />
                <Setter Property="Height" Value="200" />
            </Style>
        </pu:MessageBoxXSettings.WindowXStyle>
HMI.UI/Style/PanuonResource.xaml
@@ -8,7 +8,6 @@
                    xmlns:sys="clr-namespace:System;assembly=mscorlib"
                    xmlns:pw="https://opensource.panuon.com/wpf"
                    xmlns:pu="https://opensource.panuon.com/wpf-ui"
             xmlns:hc="clr-namespace:HMI.Core;assembly=HMI.Core"
             xmlns:uic="clr-namespace:HMI.UI.Converter;assembly=HMI.UI"
             xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI">
    <ResourceDictionary.MergedDictionaries>
@@ -16,8 +15,6 @@
        <pu:StyleDictionary Includes="PasswordBox,TextBox,ComboBox,Button,DataGrid,TreeView,Menu" />
        <ResourceDictionary Source="/HMI.UI;component/Resources/Font/Font.xaml"/>
    </ResourceDictionary.MergedDictionaries>
    <hc:LangConverter x:Key="lc"/>
    <sys:Double x:Key="TitleFontSize">20</sys:Double>
    <sys:Double x:Key="ContentFontSize">16</sys:Double>
    <sys:Double x:Key="ContentFontSize2">14</sys:Double>
@@ -286,4 +283,11 @@
                Value="{DynamicResource App.Save}"/>
        <Setter Property="pu:WindowXModalDialog.ButtonPanelMargin" Value="0,30,10,10"/>
    </Style>
    <Popup x:Key="testPop" Placement="Relative" StaysOpen="True" Width="1920" Height="1080">
        <Rectangle x:Name="RectMask"
           Fill="Red"
           Opacity="0"
           Visibility="Visible" />
    </Popup>
</ResourceDictionary>
HMI.UI/Util/MsgBoxHelper2.cs
New file
@@ -0,0 +1,98 @@
using HMI.Core.Util;
using Panuon.WPF.UI;
using Panuon.WPF.UI.Configurations;
using System.Windows;
namespace HMI.UI.Util
{
    public class MsgBoxHelper2
    {
        public static MessageBoxResult Warn(string message,
            string caption = null,
            MessageBoxButton button = MessageBoxButton.OK,
            MessageBoxIcon icon = MessageBoxIcon.Warning,
            DefaultButton defaultButton = DefaultButton.Unset, int? countdown = null)
        {
            caption = caption ?? LangUtil.Get("App.Warn");
            var setting = Application.Current.FindResource("MsgBoxWarn") as MessageBoxXSetting;
            return ShowMessage(message, caption, button, icon, defaultButton, setting, countdown);
        }
        public static MessageBoxResult Error(string message,
            string caption = null,
            MessageBoxButton button = MessageBoxButton.OK,
            MessageBoxIcon icon = MessageBoxIcon.Error,
            DefaultButton defaultButton = DefaultButton.Unset, int? countdown = null)
        {
            caption = caption ?? LangUtil.Get("App.Error");
            var setting = Application.Current.FindResource("MsgBoxError") as MessageBoxXSetting;
            return ShowMessage(message, caption, button, icon, defaultButton, setting, countdown);
        }
        public static MessageBoxResult Info(string message,
            string caption = null,
            MessageBoxButton button = MessageBoxButton.OK,
            MessageBoxIcon icon = MessageBoxIcon.Info,
            DefaultButton defaultButton = DefaultButton.Unset, int? countdown = null)
        {
            caption = caption ?? LangUtil.Get("App.Info");
            var setting = Application.Current.FindResource("MsgBoxInfo") as MessageBoxXSetting;
            return ShowMessage(message, caption, button, icon, defaultButton, setting, countdown);
        }
        public static MessageBoxResult WarnChoose(string message,
            string caption = null,
            MessageBoxButton button = MessageBoxButton.OKCancel,
            MessageBoxIcon icon = MessageBoxIcon.Warning,
            DefaultButton defaultButton = DefaultButton.Unset, int? countdown = null)
        {
            caption = caption ?? LangUtil.Get("App.Warn");
            var setting = Application.Current.FindResource("MsgBoxWarn") as MessageBoxXSetting;
            return ShowMessage(message, caption, button, icon, defaultButton, setting, countdown);
        }
        public static MessageBoxResult ErrorChoose(string message,
            string caption = null,
            MessageBoxButton button = MessageBoxButton.OKCancel,
            MessageBoxIcon icon = MessageBoxIcon.Error,
            DefaultButton defaultButton = DefaultButton.Unset, int? countdown = null)
        {
            caption = caption ?? LangUtil.Get("App.Error");
            var setting = Application.Current.FindResource("MsgBoxError") as MessageBoxXSetting;
            return ShowMessage(message, caption, button, icon, defaultButton, setting, countdown);
        }
        public static MessageBoxResult InfoChoose(string message,
            string caption = null,
            MessageBoxButton button = MessageBoxButton.OKCancel,
            MessageBoxIcon icon = MessageBoxIcon.Info,
            DefaultButton defaultButton = DefaultButton.Unset, int? countdown = null)
        {
            caption = caption ?? LangUtil.Get("App.Info");
            var setting = Application.Current.FindResource("MsgBoxInfo") as MessageBoxXSetting;
            return ShowMessage(message, caption, button, icon, defaultButton, setting, countdown);
        }
        public static MessageBoxResult ShowMessage(string message,
            string caption,
            MessageBoxButton button,
            MessageBoxIcon icon,
            DefaultButton defaultButton, MessageBoxXSetting setting, int? countdown)
        {
            MessageBoxResult res = MessageBoxResult.None;
            var window = Application.Current.MainWindow;
            if (window is WindowX)
            {
                window.Dispatcher.Invoke(() =>
                {
                    res = MessageBoxX.Show(window, message, caption, button, icon, defaultButton, setting, countdown);
                });
                return res;
            }
            else
            {
                return MessageBox.Show(message, caption);
            }
        }
    }
}
HMI.UI/Util/ToastHelper.cs
@@ -1,4 +1,6 @@
using Panuon.WPF.UI;
using HMI.Core.Util;
using Panuon.WPF.UI;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
@@ -40,6 +42,73 @@
            if (Instance == null) { Instance = helper; }
        }
        public static void Success(string message,
            MessageBoxIcon icon = MessageBoxIcon.Success,
            ToastPosition position = ToastPosition.Top, double offset = 0, int durationMs = 3000,
            ToastWindow targetWindow = ToastWindow.ActiveWindow)
        {
            var window = Application.Current.MainWindow;
            if (window is WindowX)
            {
                Instance.Success(window, message, icon, position, offset, durationMs, targetWindow);
            }
            else
            {
                MessageBox.Show(message, LangUtil.Get("App.Success"));
            }
        }
        public static void Warning(string message,
            MessageBoxIcon icon = MessageBoxIcon.Warning,
            ToastPosition position = ToastPosition.Top, double offset = 0, int durationMs = 3000,
            ToastWindow targetWindow = ToastWindow.ActiveWindow)
        {
            var window = Application.Current.MainWindow;
            if (window is WindowX)
            {
                Instance.Warning(window, message, icon, position, offset, durationMs, targetWindow);
            }
            else
            {
                MessageBox.Show(message, LangUtil.Get("App.Warn"));
            }
        }
        public static void Error(string message,
            MessageBoxIcon icon = MessageBoxIcon.Error,
            ToastPosition position = ToastPosition.Top, double offset = 0, int durationMs = 3000,
            ToastWindow targetWindow = ToastWindow.ActiveWindow)
        {
            var window = Application.Current.MainWindow;
            if (window is WindowX)
            {
                Instance.Error(window, message, icon, position, offset, durationMs, targetWindow);
            }
            else
            {
                MessageBox.Show(message, LangUtil.Get("App.Error"));
            }
        }
        public static void Info(string message,
            MessageBoxIcon icon = MessageBoxIcon.Info,
            ToastPosition position = ToastPosition.Top, double offset = 0, int durationMs = 3000,
            ToastWindow targetWindow = ToastWindow.ActiveWindow)
        {
            var window = Application.Current.MainWindow;
            if (window is WindowX)
            {
                Instance.Info(window, message, icon, position, offset, durationMs, targetWindow);
            }
            else
            {
                MessageBox.Show(message, LangUtil.Get("App.Info"));
            }
        }
        public static void Success(DependencyObject dp,
            string message,
            MessageBoxIcon icon = MessageBoxIcon.Success,
HMI.UI/packages.config
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Panuon.WPF" version="1.1.2.2" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.3" targetFramework="net472" />
  <package id="Panuon.WPF.UI" version="1.2.4.9" targetFramework="net472" />
</packages>
HMI.UnitTest/HMI.UnitTest.csproj
@@ -55,11 +55,11 @@
    <Prefer32Bit>true</Prefer32Bit>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="log4net, Version=3.0.3.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.3\lib\net462\log4net.dll</HintPath>
    <Reference Include="log4net, Version=3.0.4.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.4\lib\net462\log4net.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF, Version=1.1.2.2, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.2.2\lib\net472\Panuon.WPF.dll</HintPath>
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.3\lib\net472\Panuon.WPF.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF.UI, Version=1.2.4.8, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.UI.1.2.4.9\lib\net472\Panuon.WPF.UI.dll</HintPath>
HMI.UnitTest/packages.config
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="log4net" version="3.0.3" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.2.2" targetFramework="net472" />
  <package id="log4net" version="3.0.4" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.3" targetFramework="net472" />
  <package id="Panuon.WPF.UI" version="1.2.4.9" targetFramework="net472" />
</packages>
Libs/Microsoft.DwayneNeed.Win32.dll
Binary files differ
Libs/Microsoft.DwayneNeed.dll
Binary files differ
Plugin.ServoManage/Plugin.ServoManage.csproj
New file
@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{1853E00F-6865-4BC6-974B-6A5E1C00BAFE}</ProjectGuid>
    <OutputType>library</OutputType>
    <RootNamespace>Plugin.ServoManage</RootNamespace>
    <AssemblyName>Plugin.ServoManage</AssemblyName>
    <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
    <WarningLevel>4</WarningLevel>
    <Deterministic>true</Deterministic>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>bin\x64\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <DebugType>full</DebugType>
    <PlatformTarget>x64</PlatformTarget>
    <LangVersion>7.3</LangVersion>
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
    <OutputPath>bin\x64\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <Optimize>true</Optimize>
    <DebugType>pdbonly</DebugType>
    <PlatformTarget>x64</PlatformTarget>
    <LangVersion>7.3</LangVersion>
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="log4net, Version=3.0.4.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.4\lib\net462\log4net.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF, Version=1.1.2.2, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.3\lib\net472\Panuon.WPF.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF.UI, Version=1.2.4.8, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.UI.1.2.4.9\lib\net472\Panuon.WPF.UI.dll</HintPath>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Configuration" />
    <Reference Include="System.Data" />
    <Reference Include="System.Web" />
    <Reference Include="System.Xml" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="System.Net.Http" />
    <Reference Include="System.Xaml">
      <RequiredTargetFramework>4.0</RequiredTargetFramework>
    </Reference>
    <Reference Include="WindowsBase" />
    <Reference Include="PresentationCore" />
    <Reference Include="PresentationFramework" />
  </ItemGroup>
  <ItemGroup>
    <Page Include="ServoManage.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </Page>
    <Compile Include="ServoManage.xaml.cs">
      <DependentUpon>ServoManage.xaml</DependentUpon>
      <SubType>Code</SubType>
    </Compile>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Properties\AssemblyInfo.cs">
      <SubType>Code</SubType>
    </Compile>
    <Compile Include="Properties\Resources.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>Resources.resx</DependentUpon>
    </Compile>
    <Compile Include="Properties\Settings.Designer.cs">
      <AutoGen>True</AutoGen>
      <DependentUpon>Settings.settings</DependentUpon>
      <DesignTimeSharedInput>True</DesignTimeSharedInput>
    </Compile>
    <EmbeddedResource Include="Properties\Resources.resx">
      <Generator>ResXFileCodeGenerator</Generator>
      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
    </EmbeddedResource>
    <None Include="packages.config" />
    <None Include="Properties\Settings.settings">
      <Generator>SettingsSingleFileGenerator</Generator>
      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
    </None>
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\HMI.Base\HMI.Base.csproj">
      <Project>{2a6f9720-a890-4036-9d73-41a0dae28341}</Project>
      <Name>HMI.Base</Name>
    </ProjectReference>
    <ProjectReference Include="..\HMI.Core\HMI.Core.csproj">
      <Project>{3e3bf44a-0b69-45c5-9512-528cb48a7106}</Project>
      <Name>HMI.Core</Name>
    </ProjectReference>
    <ProjectReference Include="..\HMI.UI\HMI.UI.csproj">
      <Project>{f17de6b5-af1d-48c6-94a0-6b763a6546a6}</Project>
      <Name>HMI.UI</Name>
    </ProjectReference>
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
Plugin.ServoManage/Properties/AssemblyInfo.cs
New file
@@ -0,0 +1,52 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("Plugin.ServoManage")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Plugin.ServoManage")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
//若要开始生成可本地化的应用程序,请设置
//.csproj 文件中的 <UICulture>CultureYouAreCodingWith</UICulture>
//在 <PropertyGroup> 中。例如,如果你使用的是美国英语。
//使用的是美国英语,请将 <UICulture> 设置为 en-US。  然后取消
//对以下 NeutralResourceLanguage 特性的注释。  更新
//以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly:ThemeInfo(
    ResourceDictionaryLocation.None, //主题特定资源词典所处位置
                             //(未在页面中找到资源时使用,
                             //或应用程序资源字典中找到时使用)
    ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
                                      //(未在页面中找到资源时使用,
                                      //、应用程序或任何主题专用资源字典中找到时使用)
)]
// 程序集的版本信息由下列四个值组成:
//
//      主版本
//      次版本
//      生成号
//      修订号
//
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Plugin.ServoManage/Properties/Resources.Designer.cs
New file
@@ -0,0 +1,62 @@
//------------------------------------------------------------------------------
// <auto-generated>
//     此代码由工具生成。
//     运行时版本: 4.0.30319.42000
//
//     对此文件的更改可能导致不正确的行为,如果
//     重新生成代码,则所做更改将丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace Plugin.ServoManage.Properties {
    /// <summary>
    ///   强类型资源类,用于查找本地化字符串等。
    /// </summary>
    // 此类是由 StronglyTypedResourceBuilder
    // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
    // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
    // (以 /str 作为命令选项),或重新生成 VS 项目。
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    internal class Resources {
        private static global::System.Resources.ResourceManager resourceMan;
        private static global::System.Globalization.CultureInfo resourceCulture;
        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
        internal Resources() {
        }
        /// <summary>
        ///   返回此类使用的缓存 ResourceManager 实例。
        /// </summary>
        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
        internal static global::System.Resources.ResourceManager ResourceManager {
            get {
                if ((resourceMan == null)) {
                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Plugin.ServoManage.Properties.Resources", typeof(Resources).Assembly);
                    resourceMan = temp;
                }
                return resourceMan;
            }
        }
        /// <summary>
        ///   重写当前线程的 CurrentUICulture 属性,对
        ///   使用此强类型资源类的所有资源查找执行重写。
        /// </summary>
        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
        internal static global::System.Globalization.CultureInfo Culture {
            get {
                return resourceCulture;
            }
            set {
                resourceCulture = value;
            }
        }
    }
}
Plugin.ServoManage/Properties/Resources.resx
New file
@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
  <!--
    Microsoft ResX Schema
    Version 2.0
    The primary goals of this format is to allow a simple XML format
    that is mostly human readable. The generation and parsing of the
    various data types are done through the TypeConverter classes
    associated with the data types.
    Example:
    ... ado.net/XML headers & schema ...
    <resheader name="resmimetype">text/microsoft-resx</resheader>
    <resheader name="version">2.0</resheader>
    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
        <value>[base64 mime encoded serialized .NET Framework object]</value>
    </data>
    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
        <comment>This is a comment</comment>
    </data>
    There are any number of "resheader" rows that contain simple
    name/value pairs.
    Each data row contains a name, and value. The row also contains a
    type or mimetype. Type corresponds to a .NET class that support
    text/value conversion through the TypeConverter architecture.
    Classes that don't support this are serialized and stored with the
    mimetype set.
    The mimetype is used for serialized objects, and tells the
    ResXResourceReader how to depersist the object. This is currently not
    extensible. For a given mimetype the value must be set accordingly:
    Note - application/x-microsoft.net.object.binary.base64 is the format
    that the ResXResourceWriter will generate, however the reader can
    read any of the formats listed below.
    mimetype: application/x-microsoft.net.object.binary.base64
    value   : The object must be serialized with
            : System.Serialization.Formatters.Binary.BinaryFormatter
            : and then encoded with base64 encoding.
    mimetype: application/x-microsoft.net.object.soap.base64
    value   : The object must be serialized with
            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
            : and then encoded with base64 encoding.
    mimetype: application/x-microsoft.net.object.bytearray.base64
    value   : The object must be serialized into a byte array
            : using a System.ComponentModel.TypeConverter
            : and then encoded with base64 encoding.
    -->
  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xsd:element name="root" msdata:IsDataSet="true">
      <xsd:complexType>
        <xsd:choice maxOccurs="unbounded">
          <xsd:element name="metadata">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" />
              <xsd:attribute name="type" type="xsd:string" />
              <xsd:attribute name="mimetype" type="xsd:string" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="assembly">
            <xsd:complexType>
              <xsd:attribute name="alias" type="xsd:string" />
              <xsd:attribute name="name" type="xsd:string" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="data">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="resheader">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" />
            </xsd:complexType>
          </xsd:element>
        </xsd:choice>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <resheader name="resmimetype">
    <value>text/microsoft-resx</value>
  </resheader>
  <resheader name="version">
    <value>2.0</value>
  </resheader>
  <resheader name="reader">
    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <resheader name="writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
</root>
Plugin.ServoManage/Properties/Settings.Designer.cs
New file
@@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.42000
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Plugin.ServoManage.Properties
{
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
    {
        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
        public static Settings Default
        {
            get
            {
                return defaultInstance;
            }
        }
    }
}
Plugin.ServoManage/Properties/Settings.settings
New file
@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
  <Profiles>
    <Profile Name="(Default)" />
  </Profiles>
  <Settings />
</SettingsFile>
Plugin.ServoManage/ServoManage.xaml
New file
@@ -0,0 +1,371 @@
<UserControl x:Class="Plugin.ServoManage.ServoManage"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:Plugin.ServoManage"
             mc:Ignorable="d"
             xmlns:hb="clr-namespace:HMI.Base;assembly=HMI.Base"
             xmlns:uic="clr-namespace:HMI.UI.Converter;assembly=HMI.UI"
             xmlns:pw="https://opensource.panuon.com/wpf"
             xmlns:pu="https://opensource.panuon.com/wpf-ui"
             xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI"
             xmlns:cc="clr-namespace:HMI.Core;assembly=HMI.Core"
             Loaded="UserControl_Loaded"
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.Resources>
        <Style x:Key="Desc" TargetType="Label">
            <Setter Property="Padding" Value="10"/>
            <Setter Property="FontSize" Value="12"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="BorderBrush" Value="#3a3a3a"/>
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
        </Style>
        <Style x:Key="LabelText" TargetType="Label" BasedOn="{StaticResource Desc}">
            <Setter Property="BorderThickness" Value="1,0,1,1"/>
        </Style>
        <Style x:Key="BDesc" TargetType="Label" BasedOn="{StaticResource Desc}">
            <Setter Property="Background" Value="#afeeee"/>
        </Style>
        <Style x:Key="YDesc" TargetType="Label" BasedOn="{StaticResource Desc}">
            <Setter Property="Background" Value="#ffff00"/>
        </Style>
    </UserControl.Resources>
    <Border Style="{StaticResource CardBoarder}">
        <Grid dp:GridHelper.Space="10">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="7*"/>
                <ColumnDefinition Width="3*"/>
            </Grid.ColumnDefinitions>
            <DockPanel Grid.ColumnSpan="2">
                <StackPanel DockPanel.Dock="Right" Style="{StaticResource ButtonGroup}">
                    <Button Style="{StaticResource AddBtn}" x:Name="addBtn" Click="Button_Click"/>
                    <Button Style="{StaticResource EditBtn}" x:Name="editBtn" Click="Button_Click"/>
                    <Button Style="{StaticResource RfhBtn}" x:Name="rfhBtn" Click="Button_Click"/>
                    <Button Style="{StaticResource DelBtn}" x:Name="delBtn" Click="Button_Click"/>
                </StackPanel>
                <TextBlock Style="{StaticResource TitleBox}" Text="{DynamicResource svo.title}"/>
            </DockPanel>
            <DockPanel Grid.Row="2" Grid.ColumnSpan="2" Margin="0,10,0,0">
                <pu:Drawer DockPanel.Dock="Left" x:Name="DrwMenu" MinWidth="35" MaxWidth="400"
                           Padding="0"
                           ShadowColor="{x:Null}"
                           AnimationDuration="0" BorderThickness="2,0,0,2" BorderBrush="{StaticResource CommonBoarder}">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition Width="Auto"/>
                        </Grid.ColumnDefinitions>
                        <Border Grid.ColumnSpan="2" BorderThickness="2" BorderBrush="{StaticResource CommonBoarder}" Background="{StaticResource VerBar}">
                            <DockPanel Height="35">
                                <ToggleButton x:Name="drawerBtn" BorderThickness="0"
                  DockPanel.Dock="Right"
                  Background="Transparent"
                  Width="35" Height="35" HorizontalAlignment="Right"
                  RenderTransformOrigin="0.5,0.5"
                                              Foreground="{StaticResource PrimaryColorContract}"
                  FontFamily="{StaticResource iconfont}"
                  Content="&#xe60e;" IsChecked="{Binding IsOpen, ElementName=DrwMenu, Mode=TwoWay}">
                                    <ToggleButton.Style>
                                        <Style TargetType="ToggleButton" BasedOn="{StaticResource CommonToggle}">
                                            <Style.Triggers>
                                                <DataTrigger Binding="{Binding IsOpen, ElementName=DrwMenu}" Value="False">
                                                    <Setter Property="RenderTransform">
                                                        <Setter.Value>
                                                            <RotateTransform Angle="-90"/>
                                                        </Setter.Value>
                                                    </Setter>
                                                </DataTrigger>
                                                <DataTrigger Binding="{Binding IsOpen, ElementName=DrwMenu}" Value="True">
                                                    <Setter Property="Background" Value="Red"/>
                                                    <Setter Property="RenderTransform">
                                                        <Setter.Value>
                                                            <RotateTransform Angle="90"/>
                                                        </Setter.Value>
                                                    </Setter>
                                                </DataTrigger>
                                                <Trigger Property="IsChecked" Value="True">
                                                    <Setter Property="Background" Value="Red"/>
                                                </Trigger>
                                            </Style.Triggers>
                                        </Style>
                                    </ToggleButton.Style>
                                </ToggleButton>
                                <TextBlock Text="{DynamicResource svo.list}" FontSize="16"
                                           Foreground="{StaticResource PrimaryColorContract}"
                                           VerticalAlignment="Center" HorizontalAlignment="Center"/>
                            </DockPanel>
                        </Border>
                        <Grid Grid.Row="1">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition/>
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition/>
                            </Grid.ColumnDefinitions>
                            <DataGrid Grid.Row="1" Grid.ColumnSpan="2" Style="{StaticResource DefaultDataGrid}"
                                      IsReadOnly="False"
                                      SelectionMode="Single"
                                      BorderThickness="0"
                                      ItemsSource="{Binding Datas}">
                                <DataGrid.Columns>
                                    <DataGridTemplateColumn Header="#" IsReadOnly="True" CanUserResize="False">
                                        <DataGridTemplateColumn.CellTemplate>
                                            <DataTemplate>
                                                <TextBlock Text="{Binding Converter={StaticResource rowNumber},
RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridRow},AncestorLevel=1}}"/>
                                            </DataTemplate>
                                        </DataGridTemplateColumn.CellTemplate>
                                    </DataGridTemplateColumn>
                                    <DataGridTextColumn IsReadOnly="True" Width="*" Binding="{Binding Name}">
                                        <DataGridTextColumn.Header>
                                            <TextBlock Text="{DynamicResource svo.name}"/>
                                        </DataGridTextColumn.Header>
                                    </DataGridTextColumn>
                                    <DataGridTemplateColumn Width="100" IsReadOnly="True" CanUserResize="False">
                                        <DataGridTemplateColumn.Header>
                                            <TextBlock Text="{DynamicResource App.Opt}"/>
                                        </DataGridTemplateColumn.Header>
                                        <DataGridTemplateColumn.CellTemplate>
                                            <DataTemplate>
                                                <StackPanel Orientation="Horizontal" dp:StackPanelHelper.ChildSpace="10">
                                                    <Button x:Name="editServoBtn" Style="{StaticResource EditLink}"  DataContext="{Binding }"
Click="Button_Click"/>
                                                    <Button x:Name="delServoBtn" Style="{StaticResource DeleteLink}"
DataContext="{Binding }"
Click="Button_Click"/>
                                                </StackPanel>
                                            </DataTemplate>
                                        </DataGridTemplateColumn.CellTemplate>
                                    </DataGridTemplateColumn>
                                </DataGrid.Columns>
                            </DataGrid>
                        </Grid>
                        <Label Grid.Row="1" Grid.Column="1"  Width="100" Height="34"
                               VerticalContentAlignment="Center"
                               HorizontalContentAlignment="Center"
                                   Content="{DynamicResource svo.list}"
                                   FontSize="16">
                            <Label.LayoutTransform>
                                <RotateTransform CenterX="25" CenterY="25" Angle="270"/>
                            </Label.LayoutTransform>
                            <Label.Style>
                                <Style TargetType="Label">
                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding IsOpen, ElementName=DrwMenu,Mode=OneWay}" Value="True">
                                            <Setter Property="Visibility" Value="Collapsed"/>
                                        </DataTrigger>
                                        <DataTrigger Binding="{Binding IsOpen, ElementName=DrwMenu}" Value="False">
                                            <Setter Property="Visibility" Value="Visible"/>
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </Label.Style>
                        </Label>
                    </Grid>
                </pu:Drawer>
                <Border BorderThickness="2" BorderBrush="{StaticResource CommonBoarder}">
                    <Grid dp:GridHelper.Space="10">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        <DockPanel>
                            <StackPanel Style="{StaticResource ButtonGroup}">
                                <TextBlock Style="{StaticResource TitleBox}"
                                           FontSize="{StaticResource ContentFontSize2}"
                                           Text="{DynamicResource svo.product}"/>
                                <ComboBox x:Name="productInput" Style="{StaticResource FormComboxStyle}" MinWidth="180" />
                                <Button Style="{StaticResource AddBtn}" Click="Button_Click"/>
                                <Button Style="{StaticResource EditBtn}" Click="Button_Click"/>
                                <Button Style="{StaticResource RfhBtn}" Click="Button_Click"/>
                                <Button Style="{StaticResource DelBtn}" Click="Button_Click"/>
                            </StackPanel>
                        </DockPanel>
                        <WrapPanel Grid.Row="1">
                            <GroupBox Header="报警" Padding="10">
                                <StackPanel Style="{StaticResource ButtonGroup}">
                                    <StackPanel>
                                        <Label Style="{StaticResource YDesc}" Content="控制报警"/>
                                        <Label Style="{StaticResource LabelText}" Content="控制报警"/>
                                    </StackPanel>
                                    <StackPanel>
                                        <Label Style="{StaticResource YDesc}" Content="驱动报警"/>
                                        <Label Style="{StaticResource LabelText}" Content="控制报警"/>
                                    </StackPanel>
                                    <StackPanel>
                                        <Label Style="{StaticResource YDesc}" Content="故障驱动"/>
                                        <Label Style="{StaticResource LabelText}" Content="0"/>
                                    </StackPanel>
                                </StackPanel>
                            </GroupBox>
                            <GroupBox Header="位置" Padding="10">
                                <StackPanel Style="{StaticResource ButtonGroup}">
                                    <StackPanel>
                                        <Label Style="{StaticResource BDesc}" Content="当前位置"/>
                                        <Label Style="{StaticResource LabelText}" Content="0"/>
                                    </StackPanel>
                                    <StackPanel>
                                        <Label Style="{StaticResource BDesc}" Content="当前速度"/>
                                        <Label Style="{StaticResource LabelText}" Content="0"/>
                                    </StackPanel>
                                    <StackPanel>
                                        <Label Style="{StaticResource BDesc}" Content="加速度"/>
                                        <Label Style="{StaticResource LabelText}" Content="0"/>
                                    </StackPanel>
                                    <StackPanel>
                                        <Label Style="{StaticResource BDesc}" Content="减速度"/>
                                        <Label Style="{StaticResource LabelText}" Content="0"/>
                                    </StackPanel>
                                </StackPanel>
                            </GroupBox>
                            <GroupBox Header="状态" Padding="10">
                                <StackPanel Style="{StaticResource ButtonGroup}">
                                    <StackPanel>
                                        <Label Style="{StaticResource YDesc}" Content="使能"/>
                                        <Label Style="{StaticResource LabelText}">
                                            <Ellipse Height="30" Width="30" Fill="{StaticResource Normal}" />
                                        </Label>
                                    </StackPanel>
                                    <StackPanel>
                                        <Label Style="{StaticResource YDesc}" Content="准备好"/>
                                        <Label Style="{StaticResource LabelText}">
                                            <Ellipse Height="30" Width="30" Fill="{StaticResource Normal}" />
                                        </Label>
                                    </StackPanel>
                                    <StackPanel>
                                        <Label Style="{StaticResource YDesc}" Content="运行中"/>
                                        <Label Style="{StaticResource LabelText}">
                                            <Ellipse Height="30" Width="30" Fill="{StaticResource Normal}" />
                                        </Label>
                                    </StackPanel>
                                    <StackPanel>
                                        <Label Style="{StaticResource YDesc}" Content="故障"/>
                                        <Label Style="{StaticResource LabelText}">
                                            <Ellipse Height="30" Width="30" Fill="{StaticResource Normal}" />
                                        </Label>
                                    </StackPanel>
                                    <StackPanel>
                                        <Label Style="{StaticResource YDesc}" Content="轴报警"/>
                                        <Label Style="{StaticResource LabelText}">
                                            <Ellipse Height="30" Width="30" Fill="{StaticResource Normal}" />
                                        </Label>
                                    </StackPanel>
                                    <StackPanel>
                                        <Label Style="{StaticResource YDesc}" Content="代码"/>
                                        <Label Style="{StaticResource LabelText}">
                                            <Ellipse Height="30" Width="30" Fill="{StaticResource Normal}" />
                                        </Label>
                                    </StackPanel>
                                </StackPanel>
                            </GroupBox>
                            <GroupBox Header="限位传感器" Padding="10">
                                <StackPanel Style="{StaticResource ButtonGroup}" Orientation="Vertical">
                                    <StackPanel Orientation="Horizontal">
                                        <Label Style="{StaticResource YDesc}" Content="使能"/>
                                        <Label Style="{StaticResource LabelText}" BorderThickness="0,1,1,1" >
                                            <Ellipse Height="30" Width="30" Fill="{StaticResource Normal}" />
                                        </Label>
                                    </StackPanel>
                                    <StackPanel Orientation="Horizontal">
                                        <Label Style="{StaticResource YDesc}" Content="准备好"/>
                                        <Label Style="{StaticResource LabelText}" BorderThickness="0,1,1,1" >
                                            <Ellipse Height="30" Width="30" Fill="{StaticResource Normal}" />
                                        </Label>
                                    </StackPanel>
                                    <StackPanel Orientation="Horizontal">
                                        <Label Style="{StaticResource YDesc}" Content="运行中"/>
                                        <Label Style="{StaticResource LabelText}" BorderThickness="0,1,1,1" >
                                            <Ellipse Height="30" Width="30" Fill="{StaticResource Normal}" />
                                        </Label>
                                    </StackPanel>
                                </StackPanel>
                            </GroupBox>
                            <GroupBox Header="寸动" Padding="10">
                                <StackPanel Style="{StaticResource ButtonGroup}">
                                    <Button Style="{StaticResource PrimaryButton}">寸动</Button>
                                    <Label Style="{StaticResource LabelText}" BorderThickness="1" Content="准备好"/>
                                    <Button Style="{StaticResource PrimaryButton}">正向</Button>
                                </StackPanel>
                            </GroupBox>
                            <GroupBox Header="操作" Padding="10">
                                <Grid dp:GridHelper.Space="10">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto"/>
                                        <RowDefinition Height="Auto"/>
                                        <RowDefinition Height="Auto"/>
                                        <RowDefinition Height="Auto"/>
                                        <RowDefinition Height="Auto"/>
                                    </Grid.RowDefinitions>
                                    <Button Style="{StaticResource PrimaryButton}">调试模式</Button>
                                    <UniformGrid Grid.Row="1" Columns="2">
                                        <Button Style="{StaticResource PrimaryButton}"
                                                Margin="0,0,5,0">调试模式</Button>
                                        <Button Style="{StaticResource PrimaryButton}"
                                                Margin="5,0,0,0">调试模式</Button>
                                    </UniformGrid>
                                    <Button Grid.Row="2" Style="{StaticResource PrimaryButton}">初始化</Button>
                                    <Button Grid.Row="3" Style="{StaticResource PrimaryButton}">停止</Button>
                                    <UniformGrid Grid.Row="4" Columns="3">
                                        <Button Style="{StaticResource PrimaryButton}">调试模式</Button>
                                        <Label Style="{StaticResource LabelText}"
                                               Margin="10,0,10,0"
                                               BorderThickness="1" Content="准备好"/>
                                        <Button Style="{StaticResource PrimaryButton}">调试模式</Button>
                                    </UniformGrid>
                                </Grid>
                            </GroupBox>
                        </WrapPanel>
                    </Grid>
                </Border>
            </DockPanel>
        </Grid>
    </Border>
</UserControl>
Plugin.ServoManage/ServoManage.xaml.cs
New file
@@ -0,0 +1,39 @@
using HMI.Base;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Plugin.ServoManage
{
    /// <summary>
    /// UserControl1.xaml 的交互逻辑
    /// </summary>
    public partial class ServoManage: UserControl
    {
        public ServoManage()
        {
            InitializeComponent();
        }
        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
        }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
        }
    }
}
Plugin.ServoManage/packages.config
New file
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="log4net" version="3.0.4" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.3" targetFramework="net472" />
  <package id="Panuon.WPF.UI" version="1.2.4.9" targetFramework="net472" />
</packages>
Plugin.TestResult/DataTable.xaml.cs
@@ -3,7 +3,9 @@
using Plugin.TestResult_WPF.Model;
using SuperSocket.SocketBase.Protocol;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
@@ -76,6 +78,11 @@
        private TcpServer tcpServer;
        private string CountIniPath;
        // 平均温度
        public List<double> tempratures = new List<double>();
        public Dictionary<string, List<double>> detailTempratures
            = new Dictionary<string, List<double>>();
        public DataTable(TestResultView parent, int index, string title,
            string countIniPath,
            BaseConfig config)
@@ -126,11 +133,23 @@
        public void SetTemperature(double t)
        {
            infoTable.temperature = t;
            tempratures.Add(t);
            chart.AddData(t);
        }
        public void SetTemperature(string name, double t)
        {
            List<double> list;
            if (detailTempratures.ContainsKey(name))
            {
                list = detailTempratures[name];
            }
            else
            {
                list = new List<double>();
                detailTempratures.Add(name, list);
            }
            list.Add(t);
            multiChart.AddData(name, t);
        }
@@ -201,6 +220,9 @@
        {
            chart.Clear();
            multiChart.Clear();
            tempratures.Clear();
            detailTempratures.Clear();
        }
        /// <summary>
@@ -363,5 +385,46 @@
        {
            StartTcpServer();
        }
        public void SaveTempFile(string filePath)
        {
            try
            {
                FileInfo fi = new FileInfo(filePath);
                if (!fi.Directory.Exists)
                {
                    fi.Directory.Create();  //文件不存在,创建文件
                }
                using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
                using (StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.UTF8))
                {
                    string title = string.Join(",", detailTempratures.Keys) + ",平均值";
                    sw.WriteLine(title);
                    for (int i = 0; i < tempratures.Count; i++)
                    {
                        string line = "";
                        foreach (string key in detailTempratures.Keys)
                        {
                            if (detailTempratures[key] == null || detailTempratures[key].Count <= i)
                            {
                                line += ",";
                            }
                            else
                            {
                                line += $"{detailTempratures[key][i]},";
                            }
                        }
                        line += tempratures[i];
                        sw.WriteLine(line);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
    }
}
Plugin.TestResult/Plugin.TestResult.csproj
@@ -58,8 +58,8 @@
    <Reference Include="HarfBuzzSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\HarfBuzzSharp.7.3.0.3\lib\net462\HarfBuzzSharp.dll</HintPath>
    </Reference>
    <Reference Include="log4net, Version=3.0.3.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.3\lib\net462\log4net.dll</HintPath>
    <Reference Include="log4net, Version=3.0.4.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.4\lib\net462\log4net.dll</HintPath>
    </Reference>
    <Reference Include="NationalInstruments.TestStand.Interop.AdapterAPI, Version=20.0.0.49158, Culture=neutral, PublicKeyToken=ad9244eb3b825cd8, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
@@ -97,7 +97,7 @@
      <HintPath>..\WPFProject\packages\OpenTK.3.3.1\lib\net20\OpenTK.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF, Version=1.1.2.2, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.2.2\lib\net472\Panuon.WPF.dll</HintPath>
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.3\lib\net472\Panuon.WPF.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF.UI, Version=1.2.4.8, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.UI.1.2.4.9\lib\net472\Panuon.WPF.UI.dll</HintPath>
Plugin.TestResult/TestResultView.xaml.cs
@@ -383,6 +383,17 @@
                    tables[ovenIndex].GetSingleCell(cellIndex).ClearInfo();
                    return;
                }
                if (MethodCode == 12)
                {
                    /// 保存温度文件
                    ///
                    strData = e.uiMsg.StringData;
                    string[] datas = strData.Split(';');
                    int ovenIndex = int.Parse(datas[0]);
                    string folder = datas[1];
                    tables[ovenIndex].SaveTempFile(folder);
                    return;
                }
            }
            catch (Exception ex)
            {
Plugin.TestResult/app.config
@@ -4,7 +4,7 @@
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.3.0" newVersion="3.0.3.0" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.4.0" newVersion="3.0.4.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
Plugin.TestResult/packages.config
@@ -4,10 +4,10 @@
  <package id="HarfBuzzSharp.NativeAssets.Linux" version="7.3.0.3" targetFramework="net472" />
  <package id="HarfBuzzSharp.NativeAssets.macOS" version="7.3.0.3" targetFramework="net472" />
  <package id="HarfBuzzSharp.NativeAssets.Win32" version="7.3.0.3" targetFramework="net472" />
  <package id="log4net" version="3.0.3" targetFramework="net472" />
  <package id="log4net" version="3.0.4" targetFramework="net472" />
  <package id="OpenTK" version="3.3.1" targetFramework="net472" />
  <package id="OpenTK.GLWpfControl" version="3.3.0" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.2.2" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.3" targetFramework="net472" />
  <package id="Panuon.WPF.UI" version="1.2.4.9" targetFramework="net472" />
  <package id="ScottPlot" version="5.0.47" targetFramework="net472" />
  <package id="ScottPlot.WPF" version="5.0.47" targetFramework="net472" />
Plugin.TsExecution/Plugin.TsExecution.csproj
@@ -58,8 +58,8 @@
    <Reference Include="HarfBuzzSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\HarfBuzzSharp.7.3.0.3\lib\net462\HarfBuzzSharp.dll</HintPath>
    </Reference>
    <Reference Include="log4net, Version=3.0.3.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.3\lib\net462\log4net.dll</HintPath>
    <Reference Include="log4net, Version=3.0.4.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\log4net.3.0.4\lib\net462\log4net.dll</HintPath>
    </Reference>
    <Reference Include="NationalInstruments.TestStand.Interop.API, Version=20.0.0.49158, Culture=neutral, PublicKeyToken=ad9244eb3b825cd8, processorArchitecture=MSIL">
      <EmbedInteropTypes>True</EmbedInteropTypes>
@@ -72,7 +72,7 @@
      <HintPath>..\WPFProject\packages\OpenTK.3.3.1\lib\net20\OpenTK.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF, Version=1.1.2.2, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.2.2\lib\net472\Panuon.WPF.dll</HintPath>
      <HintPath>..\WPFProject\packages\Panuon.WPF.1.1.3\lib\net472\Panuon.WPF.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF.UI, Version=1.2.4.8, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\WPFProject\packages\Panuon.WPF.UI.1.2.4.9\lib\net472\Panuon.WPF.UI.dll</HintPath>
Plugin.TsExecution/TsExecution.xaml.cs
@@ -238,16 +238,21 @@
        private void RefershUI()
        {
            if (this.tsSockets.Count == 0)
            panel.Children.Clear();
            //重新生成子面板
            for (int i = 0; i < this.socketNum; i++)
            {
                panel.Children.Clear();
                //重新生成子面板
                for (int i = 0; i < this.socketNum; i++)
                {
                    SingleControl control = new SingleControl(i, CountIniPath);
                    panel.Children.Add(control);
                    tsSockets.Add(control);
                }
                SingleControl control = new SingleControl(i, CountIniPath);
                panel.Children.Add(control);
                tsSockets.Add(control);
            }
            if (tsSockets.Count == 1)
            {
                panel.Columns = 1;
            }
            else
            {
                panel.Columns = 2;
            }
        }
@@ -500,100 +505,106 @@
        /// <param name="e"></param>
        private void AxApplicationMgr_UIMessageEvent(object sender, _ApplicationMgrEvents_UIMessageEventEvent e)
        {
            int EventCase = Convert.ToInt32(e.uiMsg.Event);
            int Index = Convert.ToInt16(e.uiMsg.NumericData);//SocketIndex
            switch (EventCase)
            try
            {
                case 10001://传递SocketContext
                    tsSockets[Index].SequenceFileContext = (SequenceContext)e.uiMsg.ActiveXData;
                    break;
                int EventCase = Convert.ToInt32(e.uiMsg.Event);
                int Index = Convert.ToInt16(e.uiMsg.NumericData);//SocketIndex
                switch (EventCase)
                {
                    case 10001://传递SocketContext
                        tsSockets[Index].SequenceFileContext = (SequenceContext)e.uiMsg.ActiveXData;
                        break;
                case 10002://更新测试状态
                    string status = e.uiMsg.StringData;
                    this.tsSockets[Index].UpdateStatus(status);
                    this.UpdateTestCounter();
                    break;
                    case 10002://更新测试状态
                        string status = e.uiMsg.StringData;
                        this.tsSockets[Index].UpdateStatus(status);
                        this.UpdateTestCounter();
                        break;
                case 10003://发送测试数据
                    string[] TestItems = e.uiMsg.StringData.Split('\t');
                    tsSockets[Index].AddTestData(TestItems[0], TestItems[4], TestItems[1], TestItems[2], TestItems[3], TestItems[5]);
                    case 10003://发送测试数据
                        string[] TestItems = e.uiMsg.StringData.Split('\t');
                        tsSockets[Index].AddTestData(TestItems[0], TestItems[4], TestItems[1], TestItems[2], TestItems[3], TestItems[5]);
                    break;
                        break;
                case 10004://发送测试过程信息
                    this.tsSockets[Index].CurrentStep = e.uiMsg.StringData;
                    break;
                    case 10004://发送测试过程信息
                        this.tsSockets[Index].CurrentStep = e.uiMsg.StringData;
                        break;
                case 10005://初始化测试数据,清空测试数据
                    this.tsSockets[Index].IniTestData();
                    break;
                    case 10005://初始化测试数据,清空测试数据
                        this.tsSockets[Index].IniTestData();
                        break;
                case 10006://发送产品条码
                    this.tsSockets[Index].Barcode = e.uiMsg.StringData;
                    break;
                    case 10006://发送产品条码
                        this.tsSockets[Index].Barcode = e.uiMsg.StringData;
                        break;
                case 10007://开始测试计时
                    tsSockets[Index].ElapseTime = "Start Timing";
                    BtnStopSeq.IsEnabled = false;
                    break;
                    case 10007://开始测试计时
                        tsSockets[Index].ElapseTime = "Start Timing";
                        BtnStopSeq.IsEnabled = false;
                        break;
                case 10008://停止测试计时
                    tsSockets[Index].ElapseTime = "Stop Timing";
                    BtnStopSeq.IsEnabled = true;
                    break;
                    case 10008://停止测试计时
                        tsSockets[Index].ElapseTime = "Stop Timing";
                        BtnStopSeq.IsEnabled = true;
                        break;
                case 10009:
                    // reset the value of controls units failed/pass rate
                    break;
                    case 10009:
                        //
                        break;
                case 10010:
                    case 10010:
                    //PropertyObj.SetValBoolean("Locals.MD5_Used", 0, true);
                    //PropertyObj.SetValVariant("FileGlobals.MD5_Value", 0, MD5_DATA);
                    //PropertyObj.SetValVariant("StationGlobals.MD5", 0, MD5_DATA);
                    break;
                        //PropertyObj.SetValBoolean("Locals.MD5_Used", 0, true);
                        //PropertyObj.SetValVariant("FileGlobals.MD5_Value", 0, MD5_DATA);
                        //PropertyObj.SetValVariant("StationGlobals.MD5", 0, MD5_DATA);
                        break;
                case 10011:
                    // write model
                    case 10011:
                        // write model
                    break;
                        break;
                case 10012:
                    // read model
                    case 10012:
                        // read model
                    break;
                        break;
                case 10013:
                    // read continue
                    case 10013:
                        // read continue
                    break;
                        break;
                case 10014:
                    case 10014:
                    break;
                        break;
                case 10015:
                    case 10015:
                    break;
                case 10016://显示3D拼接图片
                        break;
                    case 10016://显示3D拼接图片
                    break;
                case 10017://更新测试计时,针对部分计时有PLC完成的项目
                    this.tsSockets[Index].ElapseTime = e.uiMsg.StringData;
                    break;
                case (int)UIMessageCodes.UIMsg_EndExecution://执行结束
                    this.BtnStartSeq.IsEnabled = true;
                    this.BtnStopSeq.IsEnabled = true;
                    // this.ReleaseSequenceFile();
                    break;
                case 10030://显示测试进度
                    int ProcessVal = Convert.ToInt32(e.uiMsg.StringData);
                    this.tsSockets[Index].SetTestProcess(ProcessVal);
                    break;
                default:
                    break;
                        break;
                    case 10017://更新测试计时,针对部分计时有PLC完成的项目
                        this.tsSockets[Index].ElapseTime = e.uiMsg.StringData;
                        break;
                    case (int)UIMessageCodes.UIMsg_EndExecution://执行结束
                        this.BtnStartSeq.IsEnabled = true;
                        this.BtnStopSeq.IsEnabled = true;
                        // this.ReleaseSequenceFile();
                        break;
                    case 10030://显示测试进度
                        int ProcessVal = Convert.ToInt32(e.uiMsg.StringData);
                        this.tsSockets[Index].SetTestProcess(ProcessVal);
                        break;
                    default:
                        break;
                }
            }
            catch (Exception ex)
            {
                log.Warn("Ts Event Error.", ex);
            }
        }
Plugin.TsExecution/packages.config
@@ -4,10 +4,10 @@
  <package id="HarfBuzzSharp.NativeAssets.Linux" version="7.3.0.3" targetFramework="net472" />
  <package id="HarfBuzzSharp.NativeAssets.macOS" version="7.3.0.3" targetFramework="net472" />
  <package id="HarfBuzzSharp.NativeAssets.Win32" version="7.3.0.3" targetFramework="net472" />
  <package id="log4net" version="3.0.3" targetFramework="net472" />
  <package id="log4net" version="3.0.4" targetFramework="net472" />
  <package id="OpenTK" version="3.3.1" targetFramework="net472" />
  <package id="OpenTK.GLWpfControl" version="3.3.0" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.2.2" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.3" targetFramework="net472" />
  <package id="Panuon.WPF.UI" version="1.2.4.9" targetFramework="net472" />
  <package id="ScottPlot" version="5.0.54" targetFramework="net472" />
  <package id="ScottPlot.WPF" version="5.0.54" targetFramework="net472" />
WPFProject/App.config
@@ -5,7 +5,7 @@
    </startup>
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <probing privatePath="Libs;ThirdParty;Plugin;3rds;" />
            <probing privatePath="Libs;ThirdParty;Plugin;3rds;"/>
            <dependentAssembly>
                <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
                <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
@@ -24,7 +24,7 @@
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
                <bindingRedirect oldVersion="0.0.0.0-3.0.3.0" newVersion="3.0.3.0" />
                <bindingRedirect oldVersion="0.0.0.0-3.0.4.0" newVersion="3.0.4.0" />
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
WPFProject/App.xaml
@@ -21,6 +21,7 @@
            <Style TargetType="{x:Type pu:FormGroup}" BasedOn="{StaticResource InputFormGroupStyle}"></Style>
            <uic:PathImageConverter x:Key="path2Image"/>
            <uic:DataGridRowNumberConverter x:Key="rowNumber"/>
            <uic:VisibilityBoolConverter x:Key="vbConverter"/>
            <uic:DataGridRowFlagConverter x:Key="rowFlag"/>
            <hc:LangConverter x:Key="lc"/>
        </ResourceDictionary>
WPFProject/App.xaml.cs
@@ -4,6 +4,8 @@
using log4net;
using Panuon.WPF.UI;
using System;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Windows;
using WPFProject.Utils;
@@ -34,9 +36,11 @@
        private static Mutex mutex;
        private void Application_Startup(object sender, StartupEventArgs e)
        {
            mutex = new System.Threading.Mutex(true, "TestPlatform_OnlyRun_CRNS");
            mutex = new Mutex(true, "TestPlatform_OnlyRun_CRNS");
            if (mutex.WaitOne(0, false))
            {
                AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
                LangUtil.Load();
                SystemSetting.SystemSettingChanged += SystemSetting_SystemSettingChanged;
                ToastHelper.Register(new MainToastHandler());
@@ -51,6 +55,26 @@
            }
        }
        private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            // 获取请求加载的程序集名称
            string assemblyName = new AssemblyName(args.Name).Name;
            string[] dirs = new string[] { "3rds", "Libs" };
            foreach (string dir in dirs)
            {
                string dllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, dir, $"{assemblyName}.dll");
                if (File.Exists(dllPath))
                {
                    // 如果依赖 DLL 存在,则加载并返回它
                    return Assembly.LoadFrom(dllPath);
                }
            }
            // 否则返回 null
            return null;
        }
        private void SystemSetting_SystemSettingChanged(object sender, SystemSetting e)
        {
            LangUtil.LoadLang();
WPFProject/Controls/HolderForm.Designer.cs
New file
@@ -0,0 +1,59 @@
namespace WPFProject.Controls
{
    partial class HolderForm
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.panel1 = new System.Windows.Forms.Panel();
            this.SuspendLayout();
            //
            // panel1
            //
            this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.panel1.Location = new System.Drawing.Point(0, 0);
            this.panel1.Name = "panel1";
            this.panel1.Size = new System.Drawing.Size(800, 450);
            this.panel1.TabIndex = 0;
            //
            // HolderForm
            //
            this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(800, 450);
            this.Controls.Add(this.panel1);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            this.Name = "HolderForm";
            this.Text = "HolderForm";
            this.ResumeLayout(false);
        }
        #endregion
        private System.Windows.Forms.Panel panel1;
    }
}
WPFProject/Controls/HolderForm.cs
New file
@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Threading;
namespace WPFProject.Controls
{
    public partial class HolderForm : Form
    {
        private MaskControl maskPanel = new MaskControl
        {
            Dock = DockStyle.Fill,
            Visible = false
        };
        public HolderForm()
        {
            InitializeComponent();
            this.Controls.Add(maskPanel);
        }
        public object Content { get; private set; }
        public void UpdateChild(object content)
        {
            this.Content = content;
            if (content is Form form)
            {
                form.TopLevel = false;
                form.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
                form.Dock = System.Windows.Forms.DockStyle.Fill;
                this.Controls.Clear();
                this.Controls.Add(maskPanel);
                this.Controls.Add(form);
                form.Show();
            }
        }
        public void ShowMask()
        {
            maskPanel.ShowLoad(this.Location, this.Size);
        }
        public void HideMask()
        {
            maskPanel.HideLoad();
        }
    }
}
WPFProject/Controls/HolderForm.resx
New file
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
  <!--
    Microsoft ResX Schema
    Version 2.0
    The primary goals of this format is to allow a simple XML format
    that is mostly human readable. The generation and parsing of the
    various data types are done through the TypeConverter classes
    associated with the data types.
    Example:
    ... ado.net/XML headers & schema ...
    <resheader name="resmimetype">text/microsoft-resx</resheader>
    <resheader name="version">2.0</resheader>
    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
        <value>[base64 mime encoded serialized .NET Framework object]</value>
    </data>
    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
        <comment>This is a comment</comment>
    </data>
    There are any number of "resheader" rows that contain simple
    name/value pairs.
    Each data row contains a name, and value. The row also contains a
    type or mimetype. Type corresponds to a .NET class that support
    text/value conversion through the TypeConverter architecture.
    Classes that don't support this are serialized and stored with the
    mimetype set.
    The mimetype is used for serialized objects, and tells the
    ResXResourceReader how to depersist the object. This is currently not
    extensible. For a given mimetype the value must be set accordingly:
    Note - application/x-microsoft.net.object.binary.base64 is the format
    that the ResXResourceWriter will generate, however the reader can
    read any of the formats listed below.
    mimetype: application/x-microsoft.net.object.binary.base64
    value   : The object must be serialized with
            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
            : and then encoded with base64 encoding.
    mimetype: application/x-microsoft.net.object.soap.base64
    value   : The object must be serialized with
            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
            : and then encoded with base64 encoding.
    mimetype: application/x-microsoft.net.object.bytearray.base64
    value   : The object must be serialized into a byte array
            : using a System.ComponentModel.TypeConverter
            : and then encoded with base64 encoding.
    -->
  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
    <xsd:element name="root" msdata:IsDataSet="true">
      <xsd:complexType>
        <xsd:choice maxOccurs="unbounded">
          <xsd:element name="metadata">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" />
              </xsd:sequence>
              <xsd:attribute name="name" use="required" type="xsd:string" />
              <xsd:attribute name="type" type="xsd:string" />
              <xsd:attribute name="mimetype" type="xsd:string" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="assembly">
            <xsd:complexType>
              <xsd:attribute name="alias" type="xsd:string" />
              <xsd:attribute name="name" type="xsd:string" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="data">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="resheader">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" />
            </xsd:complexType>
          </xsd:element>
        </xsd:choice>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <resheader name="resmimetype">
    <value>text/microsoft-resx</value>
  </resheader>
  <resheader name="version">
    <value>2.0</value>
  </resheader>
  <resheader name="reader">
    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <resheader name="writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
</root>
WPFProject/Controls/MainTabControl.xaml
@@ -5,6 +5,7 @@
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WPFProject.Controls"
             mc:Ignorable="d" 
             Loaded="UserControl_Loaded"
             Foreground="#51555f"
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.Resources>
WPFProject/Controls/MainTabControl.xaml.cs
@@ -1,10 +1,15 @@
using System.Collections.ObjectModel;
using HMI.Base;
using HMI.Core.Api;
using Microsoft.DwayneNeed.Interop;
using Panuon.WPF.UI;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using HMI.Base;
using HMI.Core.Api;
using System.Windows.Data;
using System.Windows.Forms.Integration;
using System.Windows.Media;
using WPFProject.UI;
namespace WPFProject.Controls
@@ -33,12 +38,14 @@
        }
        #endregion
        private WinFormHolder winFormHolder;
        public MainTabControl()
        {
            IPlugin plugin = new WorkControl();
            MenuItems = new ObservableCollection<PluginInfo>( PluginLoader.GetLoader().Menus);
            MenuItems = new ObservableCollection<PluginInfo>(PluginLoader.GetLoader().Menus);
            SubMenuItems = MenuItems[0].Children;
            this.DataContext = this;
            winFormHolder = new WinFormHolder();
            InitializeComponent();
        }
@@ -145,12 +152,40 @@
            if (e.AddedItems?.Count > 0)
            {
                var data = (PluginInfo)e.AddedItems[0];
                var content = (UIElement)data.Content;
                var last = (IPlugin)page.Child;
                last?.DeActive();
                page.Child = content;
                ((IPlugin)content)?.Active();
                var content = data.Content;
                var last = page.Child;
                PluginPackage.Get(last)?.DeActive();
                if (data.Type == "WinForm")
                {
                    if (content is System.Windows.Forms.Form form)
                    {
                        winFormHolder.Content = form;
                    }
                    else
                    {
                        winFormHolder.Content = content;
                    }
                    page.Child = winFormHolder;
                }
                else
                {
                    page.Child = (UIElement)content;
                }
                PluginPackage.Get(content)?.Active();
            }
        }
        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            var ss = ((WindowX)Window.GetWindow(this));
            Binding binding = new Binding("IsMaskVisible")
            {
                Source = ((WindowX)Window.GetWindow(this)),
                Mode = BindingMode.TwoWay,
                UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
            };
            winFormHolder.SetBinding(WinFormHolder.MaskVisiableProperty, binding);
        }
    }
}
WPFProject/Controls/MaskControl.Designer.cs
New file
@@ -0,0 +1,36 @@
namespace WPFProject.Controls
{
    partial class MaskControl
    {
        /// <summary>
        /// 必需的设计器变量。
        /// </summary>
        private System.ComponentModel.IContainer components = null;
        /// <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
        #region 组件设计器生成的代码
        /// <summary>
        /// 设计器支持所需的方法 - 不要修改
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
            components = new System.ComponentModel.Container();
        }
        #endregion
    }
}
WPFProject/Controls/MaskControl.cs
New file
@@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WPFProject.Controls
{
    public partial class MaskControl : Panel
    {
        public MaskControl()
        {
            SetStyle(ControlStyles.Opaque, true);//设置背景透明
            SetStyle(ControlStyles.SupportsTransparentBackColor, true);//设置背景透明
            base.CreateControl();
            this.BackColor = Color.White;
            this.Visible = false;
        }
        //protected override CreateParams CreateParams
        //{
        //    get
        //    {
        //        CreateParams cp = base.CreateParams;
        //        cp.ExStyle |= 0x00000020; // 开启 WS_EX_TRANSPARENT,使控件支持透明
        //        return cp;
        //    }
        //}
        protected override void OnPaint(PaintEventArgs pe)
        {
            Pen labelBorderPen;
            SolidBrush labelBackColorBrush;
            Color cl = Color.FromArgb(128, this.BackColor);
            labelBorderPen = new Pen(cl, 0);
            labelBackColorBrush = new SolidBrush(cl);
            base.OnPaint(pe);
            pe.Graphics.DrawRectangle(labelBorderPen, 0, 0, this.Width, this.Height);
            pe.Graphics.FillRectangle(labelBackColorBrush, 0, 0, this.Width, this.Height);
        }
        /// <summary>
        /// 显示加载
        /// </summary>
        public void ShowLoad(Point location, Size size)
        {
            this.Location = location;
            this.Size = size;
            this.BringToFront();
            this.Dock = DockStyle.Fill;
            this.Visible = true;
        }
        /// <summary>
        /// 隐藏加载
        /// </summary>
        public void HideLoad()
        {
            this.Visible = false;
        }
    }
}
WPFProject/Controls/MenuTabControl.xaml.cs
@@ -156,8 +156,10 @@
            foreach (IconTabItem item in Items)
            {
                item.Visibility = ItemVisibility;
                if (item.Children != null) {
                    foreach (var child in item.Children) {
                if (item.Children != null)
                {
                    foreach (var child in item.Children)
                    {
                        child.Visibility = ItemVisibility;
                    }
                }
WPFProject/Controls/WinFormHolder.xaml
New file
@@ -0,0 +1,13 @@
<UserControl x:Class="WPFProject.Controls.WinFormHolder"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:WPFProject.Controls"
             mc:Ignorable="d"
             x:Name="control"
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <WindowsFormsHost x:Name="host"/>
    </Grid>
</UserControl>
WPFProject/Controls/WinFormHolder.xaml.cs
New file
@@ -0,0 +1,63 @@
using System.Windows;
using System.Windows.Controls;
namespace WPFProject.Controls
{
    /// <summary>
    /// WinFormHolder.xaml 的交互逻辑
    /// </summary>
    public partial class WinFormHolder : UserControl
    {
        private HolderForm holderForm;
        public WinFormHolder()
        {
            holderForm = new HolderForm();
            InitializeComponent();
            holderForm.TopLevel = false;
            holderForm.Dock = System.Windows.Forms.DockStyle.Fill;
            host.Child = holderForm;
        }
        public object Content
        {
            get => holderForm?.Content;
            set => holderForm?.UpdateChild(value);
        }
        public bool MaskVisiable
        {
            get => GetMaskVisiable(this);
            set => SetMaskVisiable(this, value);
        }
        public static bool GetMaskVisiable(WinFormHolder obj)
        {
            return (bool)obj.GetValue(MaskVisiableProperty);
        }
        public static void SetMaskVisiable(WinFormHolder obj, bool? value)
        {
            obj.SetValue(MaskVisiableProperty, value);
        }
        public static readonly DependencyProperty MaskVisiableProperty =
            DependencyProperty.RegisterAttached("MaskVisiable", typeof(bool?), typeof(WinFormHolder)
                , new PropertyMetadata(null, OnSpaceChanged));
        private static void OnSpaceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is WinFormHolder obj)
            {
                if (e.NewValue is bool flag && flag == true)
                {
                    obj.holderForm.ShowMask();
                }
                else
                {
                    obj.holderForm.HideMask();
                }
            }
        }
    }
}
WPFProject/Lang/zh-CN/ServoManage.json
New file
@@ -0,0 +1,6 @@
{
  "svo.title": "伺服管理",
  "svo.list": "伺服列表",
  "svo.name": "名称",
  "svo.product": "产品型号",
}
WPFProject/PanuonWindow.xaml
@@ -12,15 +12,16 @@
            WindowState="Maximized"
            x:Name="window"
            BorderBrush="Transparent"
            Loaded="window_Loaded"
            pu:WindowXCaption.Buttons="All"
            xmlns:sys="clr-namespace:System;assembly=mscorlib"
            xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI"
            xmlns:hc="clr-namespace:HMI.Core;assembly=HMI.Core"
            Closed="window_Closed"
            Topmost="False"
            pu:WindowXCaption.Background="Transparent"
            pu:WindowXCaption.Height="80"
            pu:WindowXCaption.Foreground="#FFF" >
            IsOverlayerVisible="True"
            pu:WindowXCaption.Foreground="#FFF">
    <Window.Resources>
        <hc:LangConverter x:Key="lc"/>
        <Style x:Key="UserMenu" TargetType="Menu" BasedOn="{StaticResource {x:Static pu:StyleKeys.MenuStyle}}">
WPFProject/PanuonWindow.xaml.cs
@@ -22,7 +22,7 @@
    {
        public PanuonWindow()
        {
            Loaded += PanuonWindow_Loaded;
            this.Loaded += PanuonWindow_Loaded;
        }
        private UserInfo currentUser;
@@ -41,7 +41,9 @@
            RefrshConfig();
            InitializeComponent();
            userMenu.Header = this.lang("App.Welcome", UserInfo.User.Name);
            ShowMenu = true;
            ShowMenu = true;
            Application.Current.MainWindow = this;
            SystemSetting.SystemSettingChanged += SystemSetting_SystemSettingChanged;
        }
        private void RefrshConfig()
@@ -100,11 +102,6 @@
            //ScaleTransform verticalFlipTransform = new ScaleTransform(1, temp * -1);
            //btn.RenderTransform = verticalFlipTransform;
            //menuTab.ChangeItemVisibility();
        }
        private void window_Loaded(object sender, RoutedEventArgs e)
        {
            SystemSetting.SystemSettingChanged += SystemSetting_SystemSettingChanged;
        }
        private void SystemSetting_SystemSettingChanged(object sender, SystemSetting e)
WPFProject/TextFile1.txt
@@ -11,6 +11,7 @@
move /y "$(TargeDir)HMI.SettingControl.dll" $(TargeDir)Plugin\HMI.SettingControl.dll"
move /y "$(TargeDir)Plugin.TestResult.dll" $(TargeDir)Plugin\Plugin.TestResult.dll"
move /y "$(TargeDir)Plugin.TsExecution.dll" $(TargeDir)Plugin\Plugin.TsExecution.dll"
move /y "$(TargeDir)Plugin.ServoManage.dll" $(TargeDir)Plugin\Plugin.ServoManage.dll"
setlocal enabledelayedexpansion
WPFProject/WPFProject.csproj
@@ -107,8 +107,14 @@
    <Reference Include="HandyControl, Version=3.4.0.0, Culture=neutral, PublicKeyToken=45be8712787a1e5b, processorArchitecture=MSIL">
      <HintPath>packages\HandyControl.3.4.0\lib\net472\HandyControl.dll</HintPath>
    </Reference>
    <Reference Include="log4net, Version=3.0.3.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>packages\log4net.3.0.3\lib\net462\log4net.dll</HintPath>
    <Reference Include="log4net, Version=3.0.4.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
      <HintPath>packages\log4net.3.0.4\lib\net462\log4net.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.DwayneNeed">
      <HintPath>..\Libs\Microsoft.DwayneNeed.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.DwayneNeed.Win32">
      <HintPath>..\Libs\Microsoft.DwayneNeed.Win32.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Xaml.Behaviors, Version=1.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <HintPath>packages\Microsoft.Xaml.Behaviors.Wpf.1.1.39\lib\net45\Microsoft.Xaml.Behaviors.dll</HintPath>
@@ -117,7 +123,7 @@
      <HintPath>packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF, Version=1.1.2.2, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>packages\Panuon.WPF.1.1.2.2\lib\net472\Panuon.WPF.dll</HintPath>
      <HintPath>packages\Panuon.WPF.1.1.3\lib\net472\Panuon.WPF.dll</HintPath>
    </Reference>
    <Reference Include="Panuon.WPF.UI, Version=1.2.4.8, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>packages\Panuon.WPF.UI.1.2.4.9\lib\net472\Panuon.WPF.UI.dll</HintPath>
@@ -190,14 +196,29 @@
      <SubType>Designer</SubType>
    </ApplicationDefinition>
    <Compile Include="Controls\DpPlugin.cs" />
    <Compile Include="Controls\HolderForm.cs">
      <SubType>Form</SubType>
    </Compile>
    <Compile Include="Controls\HolderForm.Designer.cs">
      <DependentUpon>HolderForm.cs</DependentUpon>
    </Compile>
    <Compile Include="Controls\InnerWindow.xaml.cs">
      <DependentUpon>InnerWindow.xaml</DependentUpon>
    </Compile>
    <Compile Include="Controls\MainTabControl.xaml.cs">
      <DependentUpon>MainTabControl.xaml</DependentUpon>
    </Compile>
    <Compile Include="Controls\MaskControl.cs">
      <SubType>Component</SubType>
    </Compile>
    <Compile Include="Controls\MaskControl.Designer.cs">
      <DependentUpon>MaskControl.cs</DependentUpon>
    </Compile>
    <Compile Include="Controls\MinInnerWindow.xaml.cs">
      <DependentUpon>MinInnerWindow.xaml</DependentUpon>
    </Compile>
    <Compile Include="Controls\WinFormHolder.xaml.cs">
      <DependentUpon>WinFormHolder.xaml</DependentUpon>
    </Compile>
    <Compile Include="Entity\PluginLoadMessage.cs" />
    <Compile Include="Entity\PluginSettingInfo.cs" />
@@ -276,6 +297,10 @@
      <Generator>MSBuild:Compile</Generator>
    </Page>
    <Page Include="Controls\MinInnerWindow.xaml">
      <SubType>Designer</SubType>
      <Generator>MSBuild:Compile</Generator>
    </Page>
    <Page Include="Controls\WinFormHolder.xaml">
      <SubType>Designer</SubType>
      <Generator>MSBuild:Compile</Generator>
    </Page>
@@ -404,6 +429,9 @@
    </Content>
    <Resource Include="Resources\Background.png" />
    <Resource Include="Resources\JingCeLogo.png" />
    <EmbeddedResource Include="Controls\HolderForm.resx">
      <DependentUpon>HolderForm.cs</DependentUpon>
    </EmbeddedResource>
    <EmbeddedResource Include="Forms\Form1.resx">
      <DependentUpon>Form1.cs</DependentUpon>
    </EmbeddedResource>
@@ -463,6 +491,9 @@
    <Content Include="Lang\en-US\TestResult.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
    <Content Include="Lang\zh-CN\ServoManage.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
    <None Include="packages.config" />
    <None Include="Properties\app.manifest" />
    <None Include="Properties\Settings.settings">
@@ -514,6 +545,10 @@
      <Project>{de4205c6-5923-46fd-a4b9-65169bf61c75}</Project>
      <Name>HMI.MenuManage</Name>
    </ProjectReference>
    <ProjectReference Include="..\Plugin.ServoManage\Plugin.ServoManage.csproj">
      <Project>{1853e00f-6865-4bc6-974b-6a5e1c00bafe}</Project>
      <Name>Plugin.ServoManage</Name>
    </ProjectReference>
    <ProjectReference Include="..\Plugin.TestResult\Plugin.TestResult.csproj">
      <Project>{7375b74c-b6bf-4814-9838-e1caacad1897}</Project>
      <Name>Plugin.TestResult</Name>
@@ -555,6 +590,7 @@
move /y "$(TargeDir)HMI.SettingControl.dll" $(TargeDir)Plugin\HMI.SettingControl.dll"
move /y "$(TargeDir)Plugin.TestResult.dll" $(TargeDir)Plugin\Plugin.TestResult.dll"
move /y "$(TargeDir)Plugin.TsExecution.dll" $(TargeDir)Plugin\Plugin.TsExecution.dll"
move /y "$(TargeDir)Plugin.ServoManage.dll" $(TargeDir)Plugin\Plugin.ServoManage.dll"
setlocal enabledelayedexpansion
WPFProject/WPFProject.sln
@@ -39,6 +39,8 @@
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HMI.Util", "..\HMI.Util\HMI.Util.csproj", "{AFEA100A-9223-448D-AB10-3015D93DD98C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugin.ServoManage", "..\Plugin.ServoManage\Plugin.ServoManage.csproj", "{1853E00F-6865-4BC6-974B-6A5E1C00BAFE}"
EndProject
Global
    GlobalSection(SolutionConfigurationPlatforms) = preSolution
        Debug|Any CPU = Debug|Any CPU
@@ -191,6 +193,14 @@
        {AFEA100A-9223-448D-AB10-3015D93DD98C}.Release|Any CPU.Build.0 = Release|Any CPU
        {AFEA100A-9223-448D-AB10-3015D93DD98C}.Release|x64.ActiveCfg = Release|Any CPU
        {AFEA100A-9223-448D-AB10-3015D93DD98C}.Release|x64.Build.0 = Release|Any CPU
        {1853E00F-6865-4BC6-974B-6A5E1C00BAFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {1853E00F-6865-4BC6-974B-6A5E1C00BAFE}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {1853E00F-6865-4BC6-974B-6A5E1C00BAFE}.Debug|x64.ActiveCfg = Debug|x64
        {1853E00F-6865-4BC6-974B-6A5E1C00BAFE}.Debug|x64.Build.0 = Debug|x64
        {1853E00F-6865-4BC6-974B-6A5E1C00BAFE}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {1853E00F-6865-4BC6-974B-6A5E1C00BAFE}.Release|Any CPU.Build.0 = Release|Any CPU
        {1853E00F-6865-4BC6-974B-6A5E1C00BAFE}.Release|x64.ActiveCfg = Release|Any CPU
        {1853E00F-6865-4BC6-974B-6A5E1C00BAFE}.Release|x64.Build.0 = Release|Any CPU
    EndGlobalSection
    GlobalSection(SolutionProperties) = preSolution
        HideSolutionNode = FALSE
WPFProject/packages.config
@@ -3,10 +3,10 @@
  <package id="AIStudio.Wpf.Controls" version="1.2.2" targetFramework="net472" />
  <package id="gong-wpf-dragdrop" version="3.2.1" targetFramework="net472" />
  <package id="HandyControl" version="3.4.0" targetFramework="net472" />
  <package id="log4net" version="3.0.3" targetFramework="net472" />
  <package id="log4net" version="3.0.4" targetFramework="net472" />
  <package id="Microsoft.Xaml.Behaviors.Wpf" version="1.1.39" targetFramework="net472" />
  <package id="Newtonsoft.Json" version="13.0.3" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.2.2" targetFramework="net472" />
  <package id="Panuon.WPF" version="1.1.3" targetFramework="net472" />
  <package id="Panuon.WPF.UI" version="1.2.4.9" targetFramework="net472" />
  <package id="System.IO" version="4.3.0" targetFramework="net472" />
  <package id="System.Net.Http" version="4.3.4" targetFramework="net472" />