From 0d989a75ea117767260c04f2b2aabc38dac58830 Mon Sep 17 00:00:00 2001 From: Sunny Date: Sun, 6 Apr 2025 16:42:44 +0800 Subject: [PATCH] =?UTF-8?q?*=20EnumEx:=20DisplayText=E7=89=B9=E6=80=A7?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E5=8E=9F=E7=94=9F=E7=9A=84Description?= =?UTF-8?q?=E7=89=B9=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SunnyUI/Charts/UIDoughnutChart.cs | 6 +- SunnyUI/Charts/UIPieChart.cs | 4 +- SunnyUI/Common/UBaseConfig.cs | 743 +++++++++++++++++++++++ SunnyUI/Common/UConvertEx.cs | 371 ++++++++++++ SunnyUI/Common/UDateTimeInt64.cs | 382 ++++++++++++ SunnyUI/Common/UIniFile.cs | 25 +- SunnyUI/Common/UIniFileEx.cs | 790 +++++++++++++++++++++++++ SunnyUI/Common/UMapper.cs | 203 +++++++ SunnyUI/Common/UThunder.cs | 22 +- SunnyUI/Common/UXmlConfig.cs | 163 +++++ SunnyUI/Controls/UIRoundMeter.cs | 11 +- SunnyUI/Controls/UIVerificationCode.cs | 31 +- SunnyUI/Forms/UILoginForm.cs | 13 +- SunnyUI/Style/UIMenuStyle.cs | 9 +- SunnyUI/Style/UIStyle.cs | 29 +- SunnyUI/Style/UIStyleColor.cs | 2 +- SunnyUI/Style/UTranslate.cs | 7 +- SunnyUI/SunnyUI.csproj | 2 +- 18 files changed, 2736 insertions(+), 77 deletions(-) create mode 100644 SunnyUI/Common/UBaseConfig.cs create mode 100644 SunnyUI/Common/UConvertEx.cs create mode 100644 SunnyUI/Common/UDateTimeInt64.cs create mode 100644 SunnyUI/Common/UIniFileEx.cs create mode 100644 SunnyUI/Common/UMapper.cs create mode 100644 SunnyUI/Common/UXmlConfig.cs diff --git a/SunnyUI/Charts/UIDoughnutChart.cs b/SunnyUI/Charts/UIDoughnutChart.cs index a44cb47d..9ec5716e 100644 --- a/SunnyUI/Charts/UIDoughnutChart.cs +++ b/SunnyUI/Charts/UIDoughnutChart.cs @@ -249,9 +249,9 @@ namespace Sunny.UI { Angle angle = Angles[pieIndex][azIndex]; PointF pf = angle.Center; - if (Drawing.CalcDistance(e.Location, pf) > angle.Outer) continue; - if (Drawing.CalcDistance(e.Location, pf) < angle.Inner) continue; - double az = Drawing.CalcAngle(e.Location, pf); + if (e.Location.CalcDistance(pf) > angle.Outer) continue; + if (e.Location.CalcDistance(pf) < angle.Inner) continue; + double az = e.Location.CalcAngle(pf); if (az >= angle.Start && az <= angle.Start + angle.Sweep) { SetPieAndAzIndex(pieIndex, azIndex); diff --git a/SunnyUI/Charts/UIPieChart.cs b/SunnyUI/Charts/UIPieChart.cs index 152e83c2..ae7d5809 100644 --- a/SunnyUI/Charts/UIPieChart.cs +++ b/SunnyUI/Charts/UIPieChart.cs @@ -274,9 +274,9 @@ namespace Sunny.UI if (!e.Location.InRect(rect)) continue; PointF pf = new PointF(rect.Left + rect.Width / 2.0f, rect.Top + rect.Height / 2.0f); - if (Drawing.CalcDistance(e.Location, pf) * 2 > rect.Width) continue; + if (e.Location.CalcDistance(pf) * 2 > rect.Width) continue; - double az = Drawing.CalcAngle(e.Location, pf); + double az = e.Location.CalcAngle(pf); for (int azIndex = 0; azIndex < Option.Series[pieIndex].Data.Count; azIndex++) { Angle angle = Angles[pieIndex][azIndex]; diff --git a/SunnyUI/Common/UBaseConfig.cs b/SunnyUI/Common/UBaseConfig.cs new file mode 100644 index 00000000..377a69d6 --- /dev/null +++ b/SunnyUI/Common/UBaseConfig.cs @@ -0,0 +1,743 @@ +/****************************************************************************** + * SunnyUI 开源控件库、工具类库、扩展类库、多页面开发框架。 + * CopyRight (C) 2012-2023 ShenYongHua(沈永华). + * QQ群:56829229 QQ:17612584 EMail:SunnyUI@QQ.Com + * + * Blog: https://www.cnblogs.com/yhuse + * Gitee: https://gitee.com/yhuse/SunnyUI + * GitHub: https://github.com/yhuse/SunnyUI + * + * SunnyUI.Common.dll can be used for free under the MIT license. + * If you use this code, please keep this note. + * 如果您使用此代码,请保留此说明。 + ****************************************************************************** + * 文件名称: UBaseConfig.cs + * 文件说明: 配置文件基类 + * 当前版本: V3.1 + * 创建日期: 2020-01-01 + * + * 2020-01-01: V2.2.0 增加文件说明 +******************************************************************************/ + +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.ComponentModel; +using System.Reflection; +using System.Xml.Serialization; + +namespace Sunny.UI +{ + /// + /// 配置文件基类 + /// + /// 类型 + public abstract class BaseConfig where TConfig : BaseConfig, new() + { + /// + /// 实体对象 + /// + protected static TConfig current; + + /// + /// 配置文件描述 + /// + public static string Description + { + get + { + var fileanddesc = ConfigHelper.GetConfigFile(); + return fileanddesc.Item2; + } + } + + /// + /// 配置文件名 + /// + public static string ConfigFile + { + get + { + var fileanddesc = ConfigHelper.GetConfigFile(); + return fileanddesc.Item1; + } + } + + /// + /// 当前可执行文件路径,末尾包括\ + /// + /// 结果 + private static string CurrentDir() + { + return Environment.CurrentDirectory.DealPath(); + } + + /// + /// 当前实例。通过置空可以使其重新加载。 + /// + public static TConfig Current + { + get + { + if (current != null) + { + return current; + } + + // 现在没有对象,尝试加载,若返回null则实例化一个新的 + current = CreateNew(); + if (!current.Load(CurrentDir() + ConfigFile)) + { + try + { + // 根据配置,有可能不保存,直接返回默认 + current.Save(); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + + return current; + } + + set => current = value; + } + + private static TConfig CreateNew() + { + TConfig config = new TConfig(); + config.SetDefault(); + return config; + } + + /// 保存到配置文件中去 + public void Save() + { + Save(null); + } + + /// + /// 加载指定配置文件 + /// + /// 结果 + public bool Load() + { + return Load(null); + } + + /// + /// 加密 + /// + /// 字符串 + /// 加密后字符串 + public string Encrypt(string str) + { + Random random = new Random(); + var value = random.Next(100000, 999999); + string tmp = str + value.ToString(); + return tmp.DesEncrypt(); + } + + /// + /// 解密 + /// + /// 字符串 + /// 解密后字符串 + public string Decrypt(string str) + { + string result = str.DesDecrypt(); + return result.Left(result.Length - 6); + } + + /// 加载指定配置文件 + /// 文件名 + /// 结果 + public abstract bool Load(string filename); + + /// 保存到配置文件中去 + /// 文件名 + public abstract void Save(string filename); + + /// + /// 设置默认值 + /// + public virtual void SetDefault() + { + } + } + + /// + /// 忽略此属性的配置存储 + /// + [AttributeUsage(AttributeTargets.Property)] + public class MapperIgnoreAttribute : Attribute + { + } + + /// + /// 忽略此属性的配置存储 + /// + [AttributeUsage(AttributeTargets.Property)] + public class IgnoreAttribute : Attribute + { + } + + /// + /// 配置文件帮助类 + /// + public static class ConfigHelper + { + /// + /// 类型是否能够转为指定基类 + /// + /// 类型 + /// 基类 + /// 是否能够转为指定基类 + public static bool As(this Type type, Type baseType) + { + if (type == null) + { + return false; + } + + // 如果基类是泛型定义 + if (baseType.IsGenericTypeDefinition && type.IsGenericType && !type.IsGenericTypeDefinition) + { + type = type.GetGenericTypeDefinition(); + } + + if (type == baseType) + { + return true; + } + + if (baseType.IsAssignableFrom(type)) + { + return true; + } + + var rs = false; + + // 接口 + if (baseType.IsInterface) + { + if (type.GetInterface(baseType.FullName) != null) + { + rs = true; + } + else + foreach (var e in type.GetInterfaces()) + { + if (e.IsGenericType && baseType.IsGenericTypeDefinition ? e.GetGenericTypeDefinition() == baseType : e == baseType) + { + rs = true; + break; + } + } + } + + // 判断是否子类时,支持只反射加载的程序集 + if (!rs && type.Assembly.ReflectionOnly) + { + // 反射加载时,需要特殊处理接口 + while (!rs && type != typeof(object)) + { + if (type == null) + { + continue; + } + + if (type.FullName == baseType.FullName && type.AssemblyQualifiedName == baseType.AssemblyQualifiedName) + { + rs = true; + } + + type = type.BaseType; + } + } + + return rs; + } + + /// 是否泛型字典 + /// 类型 + /// 是否泛型字典 + public static bool IsDictionary(this Type type) => type != null && type.IsGenericType && type.As(typeof(IDictionary<,>)); + + /// 是否泛型列表 + /// 类型 + /// 是否泛型列表 + public static bool IsList(this Type type) + { + return type != null && type.IsGenericType && type.As(typeof(IList<>)); + //return Array.IndexOf(type.GetInterfaces(), typeof(IEnumerable)) > -1; + } + + /// 获取成员绑定的显示名,优先DisplayName,然后Description + /// member + /// 显示名 + public static string DisplayName(this PropertyInfo member) + { + var att = member.GetCustomAttribute(); + if (att != null && !att.DisplayName.IsNullOrWhiteSpace()) + { + return att.DisplayName; + } + + return ""; + } + + /// 获取成员绑定的显示名,优先DisplayName,然后Description + /// member + /// 显示名 + public static string Description(this PropertyInfo member) + { + var att2 = member.GetCustomAttribute(); + if (att2 != null && !att2.Description.IsNullOrWhiteSpace()) + { + return att2.Description; + } + + return ""; + } + + /// + /// 获取需要的属性,删除忽略的属性 + /// + /// 类型 + /// 属性列表 + public static List GetNeedProperties(this Type type) + { + var list = type.GetProperties(); + List result = new List(); + foreach (var info in list) + { + if (info.GetCustomAttribute() != null) + { + continue; + } + + if (info.GetCustomAttribute() != null) + { + continue; + } + + if (info.GetCustomAttribute() != null) + { + continue; + } + + if (info.GetCustomAttribute() != null) + { + continue; + } + + result.Add(info); + } + + return result; + } + + /// + /// 获取配置文件路径 + /// + /// 类型 + /// 文件名 + public static Tuple GetConfigFile() + { + string filename; + string description = "配置文件"; + var att = typeof(TConfig).GetCustomAttribute(); + if (att == null || att.FileName.IsNullOrWhiteSpace()) + { + filename = $"{typeof(TConfig).Name}.cfg"; + } + else + { + filename = att.FileName; + + if (!att.Description.IsNullOrEmpty()) + { + description = att.Description; + } + } + + return new Tuple(filename, description); + } + + /// + /// 初始化属性 + /// + /// 配置类 + /// 类型 + /// 节点 + /// ApplicationException + public static ConcurrentDictionary InitIdents(TConfig config) + { + ConcurrentDictionary idents = new ConcurrentDictionary(); + var list = config.GetType().GetNeedProperties(); + foreach (PropertyInfo info in list) + { + Ident ident = new Ident + { + Key = info.Name, + Show = true, + Description = info.Description(), + IsList = info.PropertyType.IsList() + }; + + var section = info.GetCustomAttribute(); + ident.Section = section != null ? section.Section : ""; + + var propertyatt = info.GetCustomAttribute(); + ident.Caption = propertyatt != null ? propertyatt.Caption : ""; + ident.Unit = propertyatt != null ? propertyatt.Unit : ""; + ident.Description = propertyatt != null ? propertyatt.Description : ""; + + var indexatt = info.GetCustomAttribute(); + ident.Index = indexatt?.Index ?? short.MaxValue + idents.Count; + ident.Show = indexatt == null || indexatt.Show; + + if (ident.Description.IsNullOrEmpty()) + { + ident.Description = info.DisplayName() ?? info.Description(); + } + + if (ident.Description.IsNullOrEmpty()) + { + ident.Description = ""; + } + + if (!idents.ContainsKey(ident.Key)) + { + idents.TryAdd(ident.Key, ident); + } + } + + return idents; + } + + /// + /// 类型默认值 + /// + /// 类型 + /// 默认值 + public static object DefaultValue(Type targetType) + { + return targetType.IsValueType ? Activator.CreateInstance(targetType) : null; + } + + /// + /// 读取对象数值 + /// + /// 配置文件 + /// 节点 + /// 类型 + /// ApplicationException + public static void LoadConfigValue(TConfig config, ConcurrentDictionary idents) + { + var list = config.GetType().GetNeedProperties(); + foreach (PropertyInfo info in list) + { + object defaultobj = info.GetValue(config, null); + Type type = info.PropertyType; + + if (type == typeof(string)) + { + object value = idents[info.Name].Value; + info.SetValue(config, Convert.ChangeType(value == null ? defaultobj : value, type), null); + continue; + } + + if (ConvertEx.CanConvent(type)) + { + object value = ConvertEx.StringToObject(idents[info.Name].Value, type, defaultobj); + info.SetValue(config, Convert.ChangeType(value, type), null); + continue; + } + + if (type.IsList()) + { + Type[] genericTypes = type.GetGenericArguments(); + if (genericTypes.Length != 1) + { + throw new ApplicationException("转换出错: " + type.FullName); + } + + Type childtype = genericTypes[0]; + Type typeDataList = typeof(List<>).MakeGenericType(childtype); + MethodInfo methodInfo = typeDataList.GetMethod("Add", BindingFlags.Public | BindingFlags.Instance); + if (methodInfo == null) + { + continue; + } + + object listvalue = typeDataList.InvokeMember(null, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance, null, null, new object[] { }); + + foreach (string strvalue in idents[info.Name].Values) + { + if (childtype == typeof(string)) + { + object value = strvalue; + methodInfo.Invoke(listvalue, new[] { value }); + } + else if (ConvertEx.CanConvent(childtype)) + { + object value = ConvertEx.StringToObject(strvalue, childtype, DefaultValue(childtype)); + methodInfo.Invoke(listvalue, new[] { value }); + } + } + + info.SetValue(config, listvalue, null); + continue; + } + + throw new ApplicationException("不支持此类型: " + type.FullName); + } + } + + /// + /// 设置对象数值 + /// + /// 配置文件 + /// 节点 + /// 类型 + /// ApplicationException + public static void SaveConfigValue(TConfig config, ConcurrentDictionary idents) + { + var list = config.GetType().GetNeedProperties(); + foreach (PropertyInfo info in list) + { + object obj = info.GetValue(config, null); + Type type = info.PropertyType; + + if (ConvertEx.CanConvent(type)) + { + string value = ConvertEx.ObjectToString(obj, type); + idents[info.Name].Value = value; + continue; + } + + if (type.IsList()) + { + Type[] genericTypes = type.GetGenericArguments(); + if (genericTypes.Length != 1) + { + throw new ApplicationException("转换出错: " + type.FullName); + } + + Type childtype = genericTypes[0]; + IEnumerable en = obj as IEnumerable; + if (en == null) + { + throw new ApplicationException("转换出错: " + type.FullName); + } + + idents[info.Name].Values.Clear(); + foreach (object child in en) + { + if (ConvertEx.CanConvent(childtype)) + { + idents[info.Name].Values.Add(ConvertEx.ObjectToString(child, childtype)); + } + else + { + throw new ApplicationException("不支持此类型: " + type.FullName); + } + } + + continue; + } + + throw new ApplicationException("不支持此类型: " + type.FullName); + } + } + } + + /// 配置文件特性 + [AttributeUsage(AttributeTargets.Class)] + public class ConfigFileAttribute : Attribute + { + /// + /// 配置文件名 + /// + public string FileName { get; } + + /// + /// 描述 + /// + public string Description { get; } + + /// + /// 配置文件 + /// + public ConfigFileAttribute() : this(string.Empty, string.Empty) + { + } + + /// 配置文件 + /// 文件名 + /// 描述 + public ConfigFileAttribute(string fileName, string description = "") + { + FileName = fileName; + Description = description; + } + } + + /// + /// 数据节点 + /// + public class Ident + { + /// + /// 节 + /// + public string Section { get; set; } + + /// + /// 键 + /// + public string Key { get; set; } + + /// + /// 值 + /// + public string Value { get; set; } + + /// + /// 描述 + /// + public string Description { get; set; } + + /// + /// 名称 + /// + public string Caption { get; set; } + + /// + /// 单位 + /// + public string Unit { get; set; } + + /// + /// 序号 + /// + public int Index { get; set; } + + /// + /// 是否显示 + /// + public bool Show { get; set; } + + /// + /// ToString() + /// + /// String + public override string ToString() + { + return Index + " [" + Section + "] " + Key + " = ?"; + } + + /// + /// 是否是列表类型 + /// + public bool IsList { get; set; } + + /// + /// 列表值 + /// + public List Values = new List(); + } + + /// + /// 配置属性节点特性 + /// + [AttributeUsage(AttributeTargets.Property)] + public class ConfigSectionAttribute : Attribute + { + /// + /// 节 + /// + public string Section { get; } + + /// 属性节点特性 + /// 节 + public ConfigSectionAttribute(string section) + { + Section = section; + } + } + + /// + /// 配置属性描述特性 + /// + [AttributeUsage(AttributeTargets.Property)] + public class ConfigPropertyAttribute : Attribute + { + /// + /// 标题 + /// + public string Caption { get; } + + /// + /// 单位 + /// + public string Unit { get; } + + /// + /// 描述 + /// + public string Description { get; } + + /// + /// 配置文件属性 + /// + /// 标题 + /// 单位 + /// 描述 + public ConfigPropertyAttribute(string caption, string description = "", string unit = "") + { + Caption = caption; + Unit = unit; + Description = description; + } + } + + /// + /// 忽略此属性的配置存储 + /// + [AttributeUsage(AttributeTargets.Property)] + public class ConfigIgnoreAttribute : Attribute + { + } + + /// + /// 配置序号描述特性 + /// + [AttributeUsage(AttributeTargets.Property)] + public class ConfigIndexAttribute : Attribute + { + /// + /// 序号 + /// + public int Index { get; } + + /// + /// 是否显示 + /// + public bool Show { get; } + + /// 配置序号特性 + /// 序号 + /// 是否显示 + public ConfigIndexAttribute(int index, bool show = true) + { + Index = index; + Show = show; + } + } +} \ No newline at end of file diff --git a/SunnyUI/Common/UConvertEx.cs b/SunnyUI/Common/UConvertEx.cs new file mode 100644 index 00000000..e95d7ba5 --- /dev/null +++ b/SunnyUI/Common/UConvertEx.cs @@ -0,0 +1,371 @@ +/****************************************************************************** + * SunnyUI 开源控件库、工具类库、扩展类库、多页面开发框架。 + * CopyRight (C) 2012-2023 ShenYongHua(沈永华). + * QQ群:56829229 QQ:17612584 EMail:SunnyUI@QQ.Com + * + * Blog: https://www.cnblogs.com/yhuse + * Gitee: https://gitee.com/yhuse/SunnyUI + * GitHub: https://github.com/yhuse/SunnyUI + * + * SunnyUI.Common.dll can be used for free under the MIT license. + * If you use this code, please keep this note. + * 如果您使用此代码,请保留此说明。 + ****************************************************************************** + * 文件名称: UConvertEx.cs + * 文件说明: 对象转换扩展类 + * 当前版本: V3.1 + * 创建日期: 2020-01-01 + * + * 2020-11-20: V3.0.0 增加文件说明 +******************************************************************************/ + +using System; +using System.Drawing; + +namespace Sunny.UI +{ + /// + /// 对象转换扩展类 + /// + public static class ConvertEx + { + /// + /// 可以对象和字符串互相转换的类型 + /// + /// 类型 + /// 结果 + public static bool CanConvent(Type type) + { + bool result = false; + TypeCode typeCode = Type.GetTypeCode(type); + switch (typeCode) + { + case TypeCode.String: + case TypeCode.Char: + case TypeCode.SByte: + case TypeCode.Byte: + case TypeCode.Int16: + case TypeCode.UInt16: + case TypeCode.Int32: + case TypeCode.UInt32: + case TypeCode.Int64: + case TypeCode.UInt64: + case TypeCode.Single: + case TypeCode.Double: + case TypeCode.Decimal: + case TypeCode.Boolean: + case TypeCode.DateTime: + result = true; + break; + + case TypeCode.Object: + if (type == typeof(Point) || + type == typeof(PointF) || + type == typeof(Color) || + type == typeof(Size) || + type == typeof(SizeF)) + { + result = true; + } + + break; + } + + return result; + } + + /// + /// 字符串转对象 + /// + /// 字符串 + /// 类型 + /// 默认对象 + /// 对象 + public static object StringToObject(string str, Type type, object defaultobj) + { + object obj = defaultobj; + + if (type == typeof(string)) + { + return str; + } + + if (str.IsNullOrEmpty()) + { + return defaultobj; + } + + TypeCode typeCode = Type.GetTypeCode(type); + switch (typeCode) + { + case TypeCode.Char: + obj = str.ToChar((char)defaultobj); + break; + + case TypeCode.SByte: + obj = str.ToSByte((sbyte)defaultobj); + break; + + case TypeCode.Byte: + obj = str.ToByte((byte)defaultobj); + break; + + case TypeCode.Int16: + obj = str.ToShort((short)defaultobj); + break; + + case TypeCode.UInt16: + obj = str.ToUShort((ushort)defaultobj); + break; + + case TypeCode.Int32: + obj = str.ToInt((int)defaultobj); + break; + + case TypeCode.UInt32: + obj = str.ToUInt((uint)defaultobj); + break; + + case TypeCode.Int64: + obj = str.ToLong((long)defaultobj); + break; + + case TypeCode.UInt64: + obj = str.ToULong((ulong)defaultobj); + break; + + case TypeCode.Single: + obj = str.ToFloat((float)defaultobj); + break; + + case TypeCode.Double: + obj = str.ToDouble((double)defaultobj); + break; + + case TypeCode.Decimal: + obj = str.ToDecimal((decimal)defaultobj); + break; + + case TypeCode.Boolean: + if (str.ToUpper().Equals(bool.TrueString.ToUpper())) + { + obj = true; + } + + if (str.ToUpper().Equals(bool.FalseString.ToUpper())) + { + obj = false; + } + + break; + + case TypeCode.DateTime: + try + { + DateTime dt = str.ToDateTime(DateTimeEx.DateTimeFormat); + obj = dt; + } + catch (Exception e) + { + Console.WriteLine(e); + } + + break; + + case TypeCode.Object: + obj = StringToObjectEx(str, type, defaultobj); + break; + + default: + throw new ApplicationException("不支持此类型: " + type.FullName); + } + + if (type == typeof(DateTime)) + { + } + + return obj; + } + + /// + /// 字符串转对象扩展 + /// + /// 字符串 + /// 类型 + /// 默认对象 + /// 对象 + private static object StringToObjectEx(string str, Type type, object defaultobj) + { + object obj = defaultobj; + + if (type == typeof(Point)) + { + string[] strs = str.ToUpper().Replace("X:", "").Replace("Y:", "").Trim().Split(";"); + + if (strs.Length == 2) + { + if (int.TryParse(strs[0], out var x) && int.TryParse(strs[1], out var y)) + { + obj = new Point(x, y); + } + } + } + else if (type == typeof(PointF)) + { + string[] strs = str.ToUpper().Replace("X:", "").Replace("Y:", "").Trim().Split(";"); + + if (strs.Length == 2) + { + if (float.TryParse(strs[0], out var x) && float.TryParse(strs[1], out var y)) + { + obj = new PointF(x, y); + } + } + } + else if (type == typeof(Color)) + { + string[] strs = str.ToUpper().Replace("A:", "").Replace("R:", "").Replace("G:", "").Replace("B:", "").Trim().Split(";"); + + if (strs.Length == 4) + { + if (int.TryParse(strs[0], out var a) && int.TryParse(strs[1], out var r) && int.TryParse(strs[2], out var g) && int.TryParse(strs[3], out var b)) + { + if (a.InRange(0, 255) && r.InRange(0, 255) && g.InRange(0, 255) && b.InRange(0, 255)) + { + obj = Color.FromArgb(a, r, g, b); + } + } + } + } + else if (type == typeof(Size)) + { + string[] strs = str.ToUpper().Replace("W:", "").Replace("H:", "").Trim().Split(";"); + + if (strs.Length == 2) + { + if (int.TryParse(strs[0], out var x) && int.TryParse(strs[1], out var y)) + { + obj = new Size(x, y); + } + } + } + else if (type == typeof(SizeF)) + { + string[] strs = str.ToUpper().Replace("W:", "").Replace("H:", "").Trim().Split(";"); + + if (strs.Length == 2) + { + if (float.TryParse(strs[0], out var x) && float.TryParse(strs[1], out var y)) + { + obj = new SizeF(x, y); + } + } + } + else + { + throw new ApplicationException("不支持此类型: " + type.FullName); + } + + return obj; + } + + /// + /// 对象转字符串 + /// + /// 对象 + /// 类型 + /// 字符串 + public static string ObjectToString(object obj, Type type) + { + string value; + + TypeCode typeCode = Type.GetTypeCode(type); + switch (typeCode) + { + case TypeCode.String: + if (obj == null) + { + obj = ""; + } + + value = obj.ToString(); + break; + + case TypeCode.Char: + case TypeCode.SByte: + case TypeCode.Byte: + case TypeCode.Int16: + case TypeCode.UInt16: + case TypeCode.Int32: + case TypeCode.UInt32: + case TypeCode.Int64: + case TypeCode.UInt64: + case TypeCode.Single: + case TypeCode.Double: + case TypeCode.Decimal: + value = obj.ToString(); + break; + + case TypeCode.Boolean: + value = (bool)obj ? bool.TrueString : bool.FalseString; + break; + + case TypeCode.DateTime: + value = ((DateTime)obj).ToString(DateTimeEx.DateTimeFormat); + break; + + case TypeCode.Object: + value = ObjectToStringEx(obj, type); + break; + + default: + throw new ApplicationException("不支持此类型: " + type.FullName); + } + + return value; + } + + /// + /// 对象转字符串扩展 + /// + /// 对象 + /// 类型 + /// 字符串 + private static string ObjectToStringEx(object obj, Type type) + { + string value; + + if (type == typeof(Point)) + { + Point point = (Point)obj; + value = "X:" + point.X + "; Y:" + point.Y; + } + else if (type == typeof(PointF)) + { + PointF point = (PointF)obj; + value = "X:" + point.X + "; Y:" + point.Y; + } + else if (type == typeof(Color)) + { + Color color = (Color)obj; + value = "A:" + color.A + "; R:" + color.R + "; G:" + color.G + "; B:" + color.B; + } + else if (type == typeof(Size)) + { + Size size = (Size)obj; + value = "W:" + size.Width + "; H:" + size.Height; + } + else if (type == typeof(SizeF)) + { + SizeF size = (SizeF)obj; + value = "W:" + size.Width + "; H:" + size.Height; + } + else + { + throw new ApplicationException("不支持此类型: " + type.FullName); + } + + return value; + } + } +} diff --git a/SunnyUI/Common/UDateTimeInt64.cs b/SunnyUI/Common/UDateTimeInt64.cs new file mode 100644 index 00000000..c9dba06d --- /dev/null +++ b/SunnyUI/Common/UDateTimeInt64.cs @@ -0,0 +1,382 @@ +/****************************************************************************** + * SunnyUI 开源控件库、工具类库、扩展类库、多页面开发框架。 + * CopyRight (C) 2012-2023 ShenYongHua(沈永华). + * QQ群:56829229 QQ:17612584 EMail:SunnyUI@QQ.Com + * + * Blog: https://www.cnblogs.com/yhuse + * Gitee: https://gitee.com/yhuse/SunnyUI + * GitHub: https://github.com/yhuse/SunnyUI + * + * SunnyUI.dll can be used for free under the GPL-3.0 license. + * If you use this code, please keep this note. + * 如果您使用此代码,请保留此说明。 + ****************************************************************************** + * 文件名称: UDateTimeInt64.cs + * 文件说明: 日期长整型 + * 当前版本: V2.2 + * 创建日期: 2020-09-23 + * + * 2020-09-23: V2.2.8 增加文件说明 + * 2020-10-10: V2.2.8 增加与Double互转 +******************************************************************************/ + +using System; + +namespace Sunny.UI +{ + /// + /// 日期与长整形和浮点型互转 + /// Value:长整形,为1970年1月1日0时起的毫秒数 + /// DoubleValue:双精度浮点数,1970年1月1日0时起的天数 + /// + public struct DateTimeInt64 : IComparable, IEquatable, IEquatable, IEquatable + { + public long Value { get; set; } + + public const long Jan1st1970Ticks = 621355968000000000; //Jan1st1970.Ticks; + public const long Dec31th9999Ticks = 3155378975999990000; //DateTime.MaxValue.Ticks; + public const string DefaultFormatString = DateTimeEx.DateTimeFormatEx; + public const double MillisecondsPerDay = 86400000.0; + + /// + /// 返回当前时间的毫秒数, 这个毫秒其实就是自1970年1月1日0时起的毫秒数 + /// + public static long CurrentDateTimeToTicks() + { + return (DateTime.UtcNow.Ticks - Jan1st1970Ticks) / 10000; + } + + public double DoubleValue + { + get { return Value * 1.0 / MillisecondsPerDay; } + set { Value = (long)(value * MillisecondsPerDay); } + } + + /// + /// 返回指定时间的毫秒数, 这个毫秒其实就是自1970年1月1日0时起的毫秒数 + /// + public static long DateTimeToTicks(DateTime datetime) + { + return (datetime.ToUniversalTime().Ticks - Jan1st1970Ticks) / 10000; + } + + /// + /// 从一个代表自1970年1月1日0时起的毫秒数,转换为DateTime (北京时间) + /// + public static DateTime TicksToDateTime(long ticks) + { +#pragma warning disable CS0618 // 类型或成员已过时 + return TimeZone.CurrentTimeZone.ToLocalTime(TicksToUTCDateTime(ticks)); +#pragma warning restore CS0618 // 类型或成员已过时 + } + + /// + /// 从一个代表自1970年1月1日0时起的毫秒数,转换为DateTime (UTC时间) + /// + public static DateTime TicksToUTCDateTime(long ticks) + { + return new DateTime(ticks * 10000 + Jan1st1970Ticks); + } + + public DateTimeInt64(long ticks) + { + ticks = MakeValidDate(ticks); + Value = ticks; + } + + public DateTimeInt64(double doubleTicks) + { + doubleTicks = MakeValidDate((long)(doubleTicks * MillisecondsPerDay)); + Value = (long)doubleTicks; + } + + public DateTimeInt64(DateTime dateTime) + { + Value = DateTimeToTicks(dateTime); + } + + public DateTimeInt64(int year, int month, int day) + { + Value = DateTimeToTicks(new DateTime(year, month, day)); + } + + public DateTimeInt64(int year, int month, int day, int hour, int minute, int second) + { + Value = DateTimeToTicks(new DateTime(year, month, day, hour, minute, second)); + } + + public DateTimeInt64(int year, int month, int day, int hour, int minute, int second, int millisecond) + { + Value = DateTimeToTicks(new DateTime(year, month, day, hour, minute, second, millisecond)); + } + + public DateTimeInt64(DateTimeInt64 dtValue) + { + Value = dtValue.Value; + } + + public bool IsValidDate + { + get { return Value >= 0 && Value <= Dec31th9999Ticks - Jan1st1970Ticks; } + } + + public DateTime DateTime + { + get { return TicksToDateTime(Value); } + set { Value = DateTimeToTicks(value); } + } + + public static bool CheckValidDate(long ticks) + { + return ticks >= 0 && ticks <= Dec31th9999Ticks - Jan1st1970Ticks; + } + + public static long MakeValidDate(long ticks) + { + if (ticks < 0) + ticks = 0; + if (ticks > Dec31th9999Ticks - Jan1st1970Ticks) + ticks = Dec31th9999Ticks - Jan1st1970Ticks; + + return ticks; + } + + public void AddMilliseconds(double milliseconds) + { + Value = DateTimeToTicks(DateTime.AddMilliseconds(milliseconds)); + } + + public void AddSeconds(double seconds) + { + Value = DateTimeToTicks(DateTime.AddSeconds(seconds)); + } + + public void AddMinutes(double minutes) + { + Value = DateTimeToTicks(DateTime.AddMinutes(minutes)); + } + + public void AddHours(double hours) + { + Value = DateTimeToTicks(DateTime.AddHours(hours)); + } + + public void AddDays(double days) + { + Value = DateTimeToTicks(DateTime.AddDays(days)); + } + + public void AddMonths(int months) + { + Value = DateTimeToTicks(DateTime.AddMonths(months)); + } + + public void AddYears(int years) + { + Value = DateTimeToTicks(DateTime.AddYears(years)); + } + + public static long operator -(DateTimeInt64 dtValue1, DateTimeInt64 dtValue2) + { + return dtValue1.Value - dtValue2.Value; + } + + public static long operator +(DateTimeInt64 dtValue1, DateTimeInt64 dtValue2) + { + return dtValue1.Value + dtValue2.Value; + } + + public static DateTimeInt64 operator -(DateTimeInt64 dtValue1, long dtValue2) + { + dtValue1.Value -= dtValue2; + return dtValue1; + } + + public static DateTimeInt64 operator +(DateTimeInt64 dtValue1, long dtValue2) + { + dtValue1.Value += dtValue2; + return dtValue1; + } + + public static DateTimeInt64 operator ++(DateTimeInt64 dtValue) + { + dtValue.AddDays(1); + return dtValue; + } + + public static DateTimeInt64 operator --(DateTimeInt64 dtValue) + { + dtValue.AddDays(-1); + return dtValue; + } + + public static implicit operator long(DateTimeInt64 dtValue) + { + return dtValue.Value; + } + + public static implicit operator DateTimeInt64(long ticks) + { + return new DateTimeInt64(ticks); + } + + public static implicit operator DateTimeInt64(DateTime dt) + { + return new DateTimeInt64(dt); + } + + public static implicit operator DateTime(DateTimeInt64 dt) + { + return dt.DateTime; + } + + public static implicit operator double(DateTimeInt64 dtValue) + { + return dtValue.DoubleValue; + } + + public static implicit operator DateTimeInt64(double ticks) + { + return new DateTimeInt64(ticks); + } + + public static bool operator ==(DateTimeInt64 dtValue1, DateTimeInt64 dtValue2) + { + return dtValue1.Value == dtValue2.Value; + } + + public static bool operator !=(DateTimeInt64 dtValue1, DateTimeInt64 dtValue2) + { + return dtValue1.Value != dtValue2.Value; + } + + public static bool operator ==(DateTimeInt64 dtValue, long ticks) + { + return dtValue.Value == ticks; + } + + public static bool operator !=(DateTimeInt64 dtValue, long ticks) + { + return dtValue.Value != ticks; + } + + public static bool operator <(DateTimeInt64 dtValue1, DateTimeInt64 dtValue2) + { + return dtValue1.Value < dtValue2.Value; + } + + public static bool operator >(DateTimeInt64 dtValue1, DateTimeInt64 dtValue2) + { + return dtValue1.Value > dtValue2.Value; + } + + public static bool operator <=(DateTimeInt64 dtValue1, DateTimeInt64 dtValue2) + { + return dtValue1.Value <= dtValue2.Value; + } + + public static bool operator >=(DateTimeInt64 dtValue1, DateTimeInt64 dtValue2) + { + return dtValue1.Value >= dtValue2.Value; + } + + public static bool operator <(DateTimeInt64 dtValue, long ticks) + { + return dtValue.Value < ticks; + } + + public static bool operator >(DateTimeInt64 dtValue, long ticks) + { + return dtValue.Value > ticks; + } + + public static bool operator <=(DateTimeInt64 dtValue, long ticks) + { + return dtValue.Value <= ticks; + } + + public static bool operator >=(DateTimeInt64 dtValue, long ticks) + { + return dtValue.Value >= ticks; + } + + public override bool Equals(object obj) + { + if (obj is DateTimeInt64 dtValue) + { + return dtValue.Value == Value; + } + else if (obj is long longValue) + { + return longValue == Value; + } + else + { + return false; + } + } + + public override int GetHashCode() + { + return Value.GetHashCode(); + } + + int IComparable.CompareTo(object obj) + { + if (!(obj is DateTimeInt64)) throw new ArgumentException(); + return (Value).CompareTo(((DateTimeInt64)obj).Value); + } + + public string ToString(long ticks) + { + return ToString(ticks, DefaultFormatString); + } + + public override string ToString() + { + return ToString(Value, DefaultFormatString); + } + + public string ToString(string fmtStr) + { + return ToString(Value, fmtStr); + } + + public static string ToString(long dtValue, string fmtStr) + { + DateTime dt = TicksToDateTime(dtValue); + return dt.ToString(fmtStr); + } + + public bool Equals(DateTimeInt64 dtValue) + { + return Value == dtValue.Value; + } + + public bool Equals(long ticks) + { + return Value == ticks; + } + + public bool Equals(DateTime datetime) + { + return Value == (new DateTimeInt64(datetime)).Value; + } + + public string DateTimeString => DateTime.DateTimeString(); + + public string DateString => DateTime.DateString(); + + public string TimeString => DateTime.TimeString(); + + public string HourMinuteString => DateTime.ToString("HH:mm"); + + public int Year => DateTime.Year; + public int Month => DateTime.Month; + public int Day => DateTime.Day; + public int Hour => DateTime.Hour; + public int Minute => DateTime.Minute; + public int Second => DateTime.Second; + public int Millisecond => DateTime.Millisecond; + } +} \ No newline at end of file diff --git a/SunnyUI/Common/UIniFile.cs b/SunnyUI/Common/UIniFile.cs index 29641df8..365e0e4a 100644 --- a/SunnyUI/Common/UIniFile.cs +++ b/SunnyUI/Common/UIniFile.cs @@ -22,7 +22,6 @@ * 2023-08-11: v3.4.1 增加了文件绝对路径判断和文件夹是否存在判断 ******************************************************************************/ -using Sunny.UI.Win32; using System; using System.Collections.Specialized; using System.ComponentModel; @@ -31,6 +30,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Text; +using Sunny.UI.Win32; namespace Sunny.UI { @@ -299,29 +299,6 @@ namespace Sunny.UI /// public class IniFile : IniBase { - /// - /// 写Byte数组 - /// - /// section - /// key - /// value - public void Write(string section, string key, byte[] value) - { - Write(section, key, value.ToHexString()); - } - - /// - /// 读Byte数组 - /// - /// section - /// key - /// Normal - /// 结果 - public byte[] ReadBytes(string section, string key, byte[] Default) - { - return Read(section, key, Default.ToHexString()).ToHexBytes(); - } - /// /// 写Char /// diff --git a/SunnyUI/Common/UIniFileEx.cs b/SunnyUI/Common/UIniFileEx.cs new file mode 100644 index 00000000..a9227a0b --- /dev/null +++ b/SunnyUI/Common/UIniFileEx.cs @@ -0,0 +1,790 @@ +/****************************************************************************** + * SunnyUI 开源控件库、工具类库、扩展类库、多页面开发框架。 + * CopyRight (C) 2012-2023 ShenYongHua(沈永华). + * QQ群:56829229 QQ:17612584 EMail:SunnyUI@QQ.Com + * + * Blog: https://www.cnblogs.com/yhuse + * Gitee: https://gitee.com/yhuse/SunnyUI + * GitHub: https://github.com/yhuse/SunnyUI + * + * SunnyUI.dll can be used for free under the GPL-3.0 license. + * If you use this code, please keep this note. + * 如果您使用此代码,请保留此说明。 + ****************************************************************************** + * 文件名称: UIniFileEx.cs + * 文件说明: INI 文件读取类(不用WinAPI) + * 当前版本: V3.1 + * 创建日期: 2021-10-27 + * + * 2021-10-27: V2.2.0 增加文件说明 +******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Drawing; +using System.Globalization; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; + +namespace Sunny.UI +{ + public class IniFileEx + { + private readonly Dictionary data = new Dictionary(); + + private static readonly Regex regRemoveEmptyLines = + new Regex + ( + @"(\s*;[\d\D]*?\r?\n)+|\r?\n(\s*\r?\n)*", + RegexOptions.Multiline | RegexOptions.Compiled + ); + + private static readonly Regex regParseIniData = + new Regex + ( + @" + (? + ^\s*\[(?[^\]]+)?\]\s*$ + ) + | + (? + ^\s*(?[^(\s*\=\s*)]+)?\s*\=\s*(?[\d\D]*)$ + )", + RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace + ); + + public IniFileEx(string fileName) : this(fileName, Encoding.Default) { } + + public IniFileEx(string fileName, Encoding encoding) + { + FileName = fileName; + Encoding = encoding; + using FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); + ReadIniData(fs, encoding); + } + + /// + /// 文件名 + /// + [Description("文件名")] + public string FileName { get; set; } //INI文件名 + + public Encoding Encoding { get; set; } + + private void ReadIniData(Stream stream, Encoding encoding) + { + string lastSection = string.Empty; + data.Add(lastSection, new NameValueCollection()); + if (stream != null && encoding != null) + { + using StreamReader reader = new StreamReader(stream, encoding); + string iniData = reader.ReadToEnd(); + + iniData = regRemoveEmptyLines.Replace(iniData, "\n"); + string[] lines = iniData.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); + + foreach (string s in lines) + { + Match m = regParseIniData.Match(s); + if (m.Success) + { + if (m.Groups["IsSection"].Length > 0) + { + string sName = m.Groups["SectionName"].Value.ToLowerInvariant(); + if (lastSection != sName) + { + lastSection = sName; + if (!data.ContainsKey(sName)) + { + data.Add(sName, new NameValueCollection()); + } + } + } + else if (m.Groups["IsKeyValue"].Length > 0) + { + data[lastSection].Add(m.Groups["Key"].Value, m.Groups["Value"].Value); + } + } + } + } + } + + public NameValueCollection this[string section] + { + get + { + section = section.ToLowerInvariant(); + if (!data.ContainsKey(section)) + data.Add(section, new NameValueCollection()); + return data[section]; + } + } + + public string this[string section, string key] + { + get => this[section][key]; + set => this[section][key] = value; + } + + public object this[string section, string key, Type t] + { + get + { + if (t == null || t == (Type)Type.Missing) + return this[section][key]; + return GetValue(section, key, null, t); + } + set + { + if (t == null || t == (Type)Type.Missing) + this[section][key] = string.Empty; + else + SetValue(section, key, value); + } + } + + public string[] KeyNames(string section) + { + return this[section].AllKeys; + } + + public string[] SectionValues(string section) + { + return this[section].GetValues(0); + } + + private object GetValue(string section, string key, object defaultValue, Type t) + { + section = section.ToLowerInvariant(); + key = key.ToLowerInvariant(); + if (!data.ContainsKey(section)) return defaultValue; + string v = data[section][key]; + if (string.IsNullOrEmpty(v)) return defaultValue; + TypeConverter conv = TypeDescriptor.GetConverter(t); + if (!conv.CanConvertFrom(typeof(string))) return defaultValue; + + try + { + return conv.ConvertFrom(v); + } + catch + { + return defaultValue; + } + } + + private T GetValue(string section, string key, T defaultValue) + { + return (T)GetValue(section, key, defaultValue, typeof(T)); + } + + private void SetValue(string section, string key, object value) + { + if (value == null) + { + this[section][key] = string.Empty; + } + else + { + TypeConverter conv = TypeDescriptor.GetConverter(value); + if (!conv.CanConvertTo(typeof(string))) + { + this[section][key] = value.ToString(); + } + else + { + this[section][key] = (string)conv.ConvertTo(value, typeof(string)); + } + } + + UpdateFile(); + } + + public void Write(string section, string key, string value) + { + SetValue(section, key, value); + } + + public string Read(string section, string key, string Default) + { + return GetValue(section, key, Default); + } + + /// + /// 读取指定的Section的所有Value到列表中 + /// + /// section + public NameValueCollection GetSectionValues(string section) + { + return this[section]; + } + + public void UpdateFile() + { + Save(); + } + + public void Save() + { + Save(FileName, Encoding); + } + + public void Save(string fileName, Encoding encoding) + { + using FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); + Save(fs, encoding); + } + + private void Save(Stream stream, Encoding encoding) + { + using StreamWriter sw = new StreamWriter(stream, encoding); + foreach (var cur in data) + { + if (!string.IsNullOrEmpty(cur.Key)) + { + sw.WriteLine("[{0}]", cur.Key); + } + + NameValueCollection col = cur.Value; + foreach (string key in col.Keys) + { + if (!string.IsNullOrEmpty(key)) + { + string value = col[key]; + if (!string.IsNullOrEmpty(value)) + sw.WriteLine("{0}={1}", key, value); + } + } + } + + sw.Flush(); + } + + public bool HasSection(string section) + { + return data.ContainsKey(section.ToLowerInvariant()); + } + + public bool HasKey(string section, string key) + { + return + data.ContainsKey(section) && + !string.IsNullOrEmpty(data[section][key]); + } + + /// + /// 写结构 + /// + /// section + /// key + /// value + /// T + public void WriteStruct(string section, string key, T value) where T : struct + { + Write(section, key, value.ToBytes()); + } + + /// + /// 读结构 + /// + /// T + /// section + /// key + /// Normal + /// 结果 + public T ReadStruct(string section, string key, T Default) where T : struct + { + //得到结构体的大小 + int size = StructEx.Size(Default); + byte[] bytes = Read(section, key, "").ToHexBytes(); + return size > bytes.Length ? Default : bytes.ToStruct(); + } + + /// + /// 写Byte数组 + /// + /// section + /// key + /// value + public void Write(string section, string key, byte[] value) + { + Write(section, key, value.ToHexString()); + } + + /// + /// 读Byte数组 + /// + /// section + /// key + /// Normal + /// 结果 + public byte[] ReadBytes(string section, string key, byte[] Default) + { + return Read(section, key, Default.ToHexString()).ToHexBytes(); + } + + /// + /// 写Char + /// + /// section + /// key + /// value + public void Write(string section, string key, char value) + { + Write(section, key, value.ToString()); + } + + /// + /// 读Char + /// + /// section + /// key + /// Normal + /// 结果 + public char ReadChar(string section, string key, char Default = ' ') + { + return Read(section, key, Default.ToString()).ToChar(Default); + } + + /// + /// 写Decimal + /// + /// section + /// key + /// value + public void Write(string section, string key, decimal value) + { + Write(section, key, value.ToString(CultureInfo.InvariantCulture)); + } + + /// + /// 读Decimal + /// + /// section + /// key + /// Normal + /// 结果 + public decimal ReadDecimal(string section, string key, decimal Default = 0) + { + return Read(section, key, Default.ToString(CultureInfo.InvariantCulture)).ToDecimal(Default); + } + + /// + /// 写整数 + /// + /// section + /// key + /// value + public void Write(string section, string key, short value) + { + Write(section, key, value.ToString()); + } + + /// + /// 读整数 + /// + /// section + /// key + /// Normal + /// 结果 + public short ReadShort(string section, string key, short Default = 0) + { + return Read(section, key, Default.ToString()).ToShort(Default); + } + + /// + /// 写整数 + /// + /// section + /// key + /// value + public void Write(string section, string key, ushort value) + { + Write(section, key, value.ToString()); + } + + /// + /// 读整数 + /// + /// section + /// key + /// Normal + /// 结果 + public ushort ReadUShort(string section, string key, ushort Default = 0) + { + return Read(section, key, Default.ToString()).ToUShort(Default); + } + + /// + /// 写整数 + /// + /// section + /// key + /// value + public void Write(string section, string key, int value) + { + Write(section, key, value.ToString()); + } + + /// + /// 读整数 + /// + /// section + /// key + /// Normal + /// 结果 + public int ReadInt(string section, string key, int Default = 0) + { + return Read(section, key, Default.ToString()).ToInt(Default); + } + + /// + /// 写整数 + /// + /// section + /// key + /// value + public void Write(string section, string key, uint value) + { + Write(section, key, value.ToString()); + } + + /// + /// 读整数 + /// + /// section + /// key + /// Normal + /// 结果 + public uint ReadUInt(string section, string key, uint Default = 0) + { + return Read(section, key, Default.ToString()).ToUInt(Default); + } + + /// + /// 写整数 + /// + /// section + /// key + /// value + public void Write(string section, string key, ulong value) + { + Write(section, key, value.ToString()); + } + + /// + /// 读整数 + /// + /// section + /// key + /// Normal + /// 结果 + public ulong ReadULong(string section, string key, ulong Default = 0) + { + return Read(section, key, Default.ToString()).ToULong(Default); + } + + /// + /// 写整数 + /// + /// section + /// key + /// value + public void Write(string section, string key, long value) + { + Write(section, key, value.ToString()); + } + + /// + /// 读整数 + /// + /// section + /// key + /// Normal + /// 结果 + public long ReadLong(string section, string key, long Default = 0) + { + return Read(section, key, Default.ToString()).ToLong(Default); + } + + /// + /// 写布尔 + /// + /// section + /// key + /// value + public void Write(string section, string key, bool value) + { + Write(section, key, value ? bool.TrueString : bool.FalseString); + } + + /// + /// 读布尔 + /// + /// section + /// key + /// Normal + /// 结果 + public bool ReadBool(string section, string key, bool Default = false) + { + string str = Read(section, key, Default.ToString()); + if (string.Equals(str, bool.TrueString, StringComparison.CurrentCultureIgnoreCase)) + { + return true; + } + + if (string.Equals(str, bool.FalseString, StringComparison.CurrentCultureIgnoreCase)) + { + return false; + } + + return Default; + } + + /// + /// 写Double + /// + /// section + /// key + /// value + public void Write(string section, string key, double value) + { + Write(section, key, value.ToString(CultureInfo.InvariantCulture)); + } + + /// + /// 读Double + /// + /// section + /// key + /// Normal + /// 结果 + public double ReadDouble(string section, string key, double Default = 0) + { + return Read(section, key, Default.ToString(CultureInfo.InvariantCulture)).ToDouble(Default); + } + + /// + /// 写Float + /// + /// section + /// key + /// value + public void Write(string section, string key, float value) + { + Write(section, key, value.ToString(CultureInfo.InvariantCulture)); + } + + /// + /// 读Float + /// + /// section + /// key + /// Normal + /// 结果 + public float ReadFloat(string section, string key, float Default = 0) + { + return Read(section, key, Default.ToString(CultureInfo.InvariantCulture)).ToFloat(Default); + } + + /// + /// 写Byte + /// + /// section + /// key + /// value + public void Write(string section, string key, byte value) + { + Write(section, key, value.ToString()); + } + + /// + /// 读Byte + /// + /// section + /// key + /// Normal + /// 结果 + public byte ReadByte(string section, string key, byte Default = 0) + { + return Read(section, key, Default.ToString()).ToByte(Default); + } + + /// + /// 写SByte + /// + /// section + /// key + /// value + public void Write(string section, string key, sbyte value) + { + Write(section, key, value.ToString()); + } + + /// + /// 读Byte + /// + /// section + /// key + /// Normal + /// 结果 + public sbyte ReadSByte(string section, string key, sbyte Default = 0) + { + return Read(section, key, Default.ToString()).ToSByte(Default); + } + + /// + /// 写DateTime + /// + /// section + /// key + /// value + public void Write(string section, string key, DateTime value) + { + Write(section, key, value.ToString(DateTimeEx.DateTimeFormat)); + } + + /// + /// 读DateTime + /// + /// section + /// key + /// Normal + /// 结果 + public DateTime ReadDateTime(string section, string key, DateTime Default) + { + string str = Read(section, key, Default.ToString(CultureInfo.InvariantCulture)); + try + { + return str.ToDateTime(DateTimeEx.DateTimeFormat); + } + catch (Exception) + { + return Default; + } + } + + /// + /// 写Point + /// + /// section + /// key + /// value + public void Write(string section, string key, Point value) + { + Write(section, key, ConvertEx.ObjectToString(value, typeof(Point))); + } + + /// + /// 读Point + /// + /// section + /// key + /// Normal + /// 结果 + public Point ReadPoint(string section, string key, Point Default) + { + string str = Read(section, key, ""); + return (Point)ConvertEx.StringToObject(str, typeof(Point), Default); + } + + /// + /// 写PointF + /// + /// section + /// key + /// value + public void Write(string section, string key, PointF value) + { + Write(section, key, ConvertEx.ObjectToString(value, typeof(PointF))); + } + + /// + /// 读PointF + /// + /// section + /// key + /// Normal + /// 结果 + public PointF ReadPointF(string section, string key, PointF Default) + { + string str = Read(section, key, ""); + return (PointF)ConvertEx.StringToObject(str, typeof(PointF), Default); + } + + /// + /// 写Size + /// + /// section + /// key + /// value + public void Write(string section, string key, Size value) + { + Write(section, key, ConvertEx.ObjectToString(value, typeof(Size))); + } + + /// + /// 读Size + /// + /// section + /// key + /// Normal + /// 结果 + public Size ReadSize(string section, string key, Size Default) + { + string str = Read(section, key, ""); + return (Size)ConvertEx.StringToObject(str, typeof(Size), Default); + } + + /// + /// 写SizeF + /// + /// section + /// key + /// value + public void Write(string section, string key, SizeF value) + { + Write(section, key, ConvertEx.ObjectToString(value, typeof(SizeF))); + } + + /// + /// 读SizeF + /// + /// section + /// key + /// Normal + /// 结果 + public SizeF ReadSizeF(string section, string key, SizeF Default) + { + string str = Read(section, key, ""); + return (SizeF)ConvertEx.StringToObject(str, typeof(SizeF), Default); + } + + /// + /// 写Color + /// + /// section + /// key + /// value + public void Write(string section, string key, Color value) + { + Write(section, key, ConvertEx.ObjectToString(value, typeof(Color))); + } + + /// + /// 读Color + /// + /// section + /// key + /// Normal + /// 结果 + public Color ReadColor(string section, string key, Color Default) + { + string str = Read(section, key, ""); + return (Color)ConvertEx.StringToObject(str, typeof(Color), Default); + } + } +} diff --git a/SunnyUI/Common/UMapper.cs b/SunnyUI/Common/UMapper.cs new file mode 100644 index 00000000..38fcf21c --- /dev/null +++ b/SunnyUI/Common/UMapper.cs @@ -0,0 +1,203 @@ +/****************************************************************************** + * SunnyUI 开源控件库、工具类库、扩展类库、多页面开发框架。 + * CopyRight (C) 2012-2023 ShenYongHua(沈永华). + * QQ群:56829229 QQ:17612584 EMail:SunnyUI@QQ.Com + * + * Blog: https://www.cnblogs.com/yhuse + * Gitee: https://gitee.com/yhuse/SunnyUI + * GitHub: https://github.com/yhuse/SunnyUI + * + * SunnyUI.dll can be used for free under the GPL-3.0 license. + * If you use this code, please keep this note. + * 如果您使用此代码,请保留此说明。 + ****************************************************************************** + * 文件名称: UMapper.cs + * 文件说明: 轻量级的对象映射框架,可以映射值类型(包括Struct),和以值类型构成的List和数组。 + * 当前版本: V3.1 + * 创建日期: 2021-09-30 + * + * 2021-09-30: V3.0.7 增加文件说明 +******************************************************************************/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace Sunny.UI +{ + /// + /// 轻量级的对象映射框架 + /// + public static class Mapper + { + private static void Execute(T1 source, T2 dest) + where T1 : class, new() + where T2 : class, new() + { + if (source == null || dest == null) + { + return; + } + + var listSource = source.GetType().GetNeedProperties().ToDictionary(prop => prop.Name); + var listDest = dest.GetType().GetNeedProperties().ToDictionary(prop => prop.Name); + + foreach (var item in listDest) + { + if (listSource.NotContainsKey(item.Key)) continue; + + var sourceInfo = listSource[item.Key]; + Type sourceType = sourceInfo.PropertyType; + object sourceValue = sourceInfo.GetValue(source, null); + + var destInfo = item.Value; + Type destType = item.Value.PropertyType; + + if (!sourceType.Equals(destType)) continue; + if (sourceType.IsValueType) + { + //Console.WriteLine("ValueType: " + item.Key + ", " + sourceType.FullName); + destInfo.SetValue(dest, sourceValue, null); + } + else + { + if (sourceType == typeof(string)) + { + //Console.WriteLine("String: " + item.Key + ", " + sourceType.FullName); + destInfo.SetValue(dest, sourceValue, null); + continue; + } + + if (sourceType.IsList()) + { + //Console.WriteLine("List: " + item.Key + ", " + sourceType.FullName); + Type[] sourceTypes = sourceType.GetGenericArguments(); + Type[] destTypes = destType.GetGenericArguments(); + if (sourceTypes.Length != 1) continue; + if (destTypes.Length != 1) continue; + if (!sourceTypes[0].Equals(destTypes[0])) continue; + + if (sourceValue == null) + { + destInfo.SetValue(dest, null, null); + } + else + { + Type typeDataList = typeof(List<>).MakeGenericType(destTypes[0]); + MethodInfo AddInfo = typeDataList.GetMethod("Add", BindingFlags.Public | BindingFlags.Instance); + if (AddInfo == null) continue; + + if (sourceTypes[0].IsValueType || sourceTypes[0] == typeof(string)) + { + object listvalue = typeDataList.InvokeMember(null, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance, null, null, new object[] { }); + IEnumerable sourceList = sourceValue as IEnumerable; + foreach (var listItem in sourceList) + { + AddInfo.Invoke(listvalue, new[] { listItem }); + } + + destInfo.SetValue(dest, listvalue, null); + } + else + { + //暂时不考虑 + } + } + + continue; + } + + if (sourceType.IsArray) + { + //Console.WriteLine("Array: " + item.Key + ", " + sourceType.FullName); + if (sourceValue == null) + { + destInfo.SetValue(dest, null, null); + } + else + { + ICollection sourceList = sourceValue as ICollection; + Type type = sourceType.GetElementType(); + var array = Array.CreateInstance(type, sourceList.Count); + + int index = 0; + foreach (var listItem in sourceList) + { + array.SetValue(listItem, index++); + } + + destInfo.SetValue(dest, array, null); + } + + continue; + } + + if (sourceType.IsDictionary()) + { + + continue; + } + + //类没有无参构造函数的话,创建有问题 + //if (sourceType.IsClass) + //{ + // if (sourceValue == null) + // { + // destInfo.SetValue(dest, null, null); + // } + // else + // { + // object obj = Activator.CreateInstance(sourceType, null); + // obj.MapperFrom(sourceValue); + // destInfo.SetValue(dest, obj, null); + // } + // + // continue; + //} + } + } + } + + /// + /// T1映射到T2 + /// + /// T1 + /// T2 + /// 源 + /// 目标 + public static void MapperTo(this T1 source, T2 dest) + where T1 : class, new() + where T2 : class, new() + { + Execute(source, dest); + } + + /// + /// T1从T2映射 + /// + /// T1 + /// T2 + /// 源 + /// 目标 + public static void MapperFrom(this T1 dest, T2 source) + where T1 : class, new() + where T2 : class, new() + { + Execute(source, dest); + } + + /// + /// 获取数组的类类型 + /// + /// 类型 + /// 类类型 + public static Type GetArrayElementType(this Type t) + { + if (!t.IsArray) return null; + string name = t.FullName.Replace("[]", string.Empty); + return t.Assembly.GetType(name); + } + } +} diff --git a/SunnyUI/Common/UThunder.cs b/SunnyUI/Common/UThunder.cs index a9b2720d..956cb1d7 100644 --- a/SunnyUI/Common/UThunder.cs +++ b/SunnyUI/Common/UThunder.cs @@ -22,9 +22,9 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.ComponentModel; using System.IO; using System.Runtime.InteropServices; -using System.Windows.Forms; #pragma warning disable 1591 @@ -32,7 +32,7 @@ namespace Sunny.UI { public class Thunder : IDisposable { - private readonly Timer timer; + private readonly System.Windows.Forms.Timer timer; private bool Exit; public delegate void OnTaskInfoChange(object sender, ThunderTask task); @@ -52,7 +52,7 @@ namespace Sunny.UI public Thunder() { InitSuccess = ThunderDll.Init(); - timer = new Timer(); + timer = new System.Windows.Forms.Timer(); timer.Interval = 1000; timer.Tick += Timer_Tick; timer.Start(); @@ -512,7 +512,7 @@ namespace Sunny.UI public override string ToString() { - return Status.DisplayText() + ",已完成:" + (Percent * 100.0f).ToString("F2") + "%,速度:" + Speed + "KB/s"; + return Status.Description() + ",已完成:" + (Percent * 100.0f).ToString("F2") + "%,速度:" + Speed + "KB/s"; } } @@ -524,43 +524,43 @@ namespace Sunny.UI /// /// 无 /// - [DisplayText("无")] + [Description("无")] NOITEM = 0, /// /// 错误 /// - [DisplayText("错误")] + [Description("错误")] TSC_ERROR, /// /// 暂停 /// - [DisplayText("暂停")] + [Description("暂停")] TSC_PAUSE, /// /// 下载 /// - [DisplayText("下载中")] + [Description("下载中")] TSC_DOWNLOAD, /// /// 完成 /// - [DisplayText("完成")] + [Description("完成")] TSC_COMPLETE, /// /// 停止开始 /// - [DisplayText("已开始")] + [Description("已开始")] TSC_STARTENDING, /// /// 停止完成 /// - [DisplayText("已停止")] + [Description("已停止")] TSC_STOPENDING } diff --git a/SunnyUI/Common/UXmlConfig.cs b/SunnyUI/Common/UXmlConfig.cs new file mode 100644 index 00000000..d74176e5 --- /dev/null +++ b/SunnyUI/Common/UXmlConfig.cs @@ -0,0 +1,163 @@ +/****************************************************************************** + * SunnyUI 开源控件库、工具类库、扩展类库、多页面开发框架。 + * CopyRight (C) 2012-2023 ShenYongHua(沈永华). + * QQ群:56829229 QQ:17612584 EMail:SunnyUI@QQ.Com + * + * Blog: https://www.cnblogs.com/yhuse + * Gitee: https://gitee.com/yhuse/SunnyUI + * GitHub: https://github.com/yhuse/SunnyUI + * + * SunnyUI.Common.dll can be used for free under the MIT license. + * If you use this code, please keep this note. + * 如果您使用此代码,请保留此说明。 + ****************************************************************************** + * 文件名称: UXmlConfig.cs + * 文件说明: XML 配置文件类 + * 当前版本: V3.1 + * 创建日期: 2020-01-01 + * + * 2020-01-01: V2.2.0 增加文件说明 +******************************************************************************/ + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Xml; + +namespace Sunny.UI +{ + /// + /// XML 配置文件类 + /// + /// 类型 + public class XmlConfig : BaseConfig where TConfig : XmlConfig, new() + { + #region 加载 + /// + /// 当前可执行文件路径,末尾包括\ + /// + /// 结果 + private static string CurrentDir() + { + return Environment.CurrentDirectory.DealPath(); + } + + /// 加载指定配置文件 + /// 文件名 + /// 结果 + public override bool Load(string filename) + { + if (filename.IsNullOrWhiteSpace()) + { + filename = CurrentDir() + ConfigFile; + } + + if (filename.IsNullOrWhiteSpace()) + { + throw new ApplicationException($"未指定{typeof(TConfig).Name}的配置文件路径!"); + } + + if (!File.Exists(filename)) + { + return false; + } + + try + { + ConcurrentDictionary idents = ConfigHelper.InitIdents(current); + + XmlDocument doc = new XmlDocument(); + doc.Load(filename); + XmlElement root = doc.DocumentElement; //获取根节点 + foreach (Ident ident in idents.Values) + { + if (root != null) + { + var elements = root.GetElementsByTagName(ident.Key); + if (elements.Count == 1) + { + if (ident.IsList) + { + ident.Values.Clear(); + foreach (XmlNode node in elements[0].ChildNodes) + { + ident.Values.Add(node.InnerText); + } + } + else + { + ident.Value = elements[0].InnerText; + } + } + } + } + + ConfigHelper.LoadConfigValue(current, idents); + return true; + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + return false; + } + } + + /// 保存到配置文件中去 + /// 文件名 + public override void Save(string filename) + { + if (filename.IsNullOrWhiteSpace()) + { + filename = CurrentDir() + ConfigFile; + } + + if (filename.IsNullOrWhiteSpace()) + { + throw new ApplicationException($"未指定{typeof(TConfig).Name}的配置文件路径!"); + } + + ConcurrentDictionary idents = ConfigHelper.InitIdents(current); + ConfigHelper.SaveConfigValue(Current, idents); + + List strs = new List { " ", " " }; + + strs.Add("<" + GetType().Name + ">"); + + SortedList slist = new SortedList(); + foreach (var ident in idents.Values) + { + slist.Add(ident.Index, ident); + } + + foreach (var ident in slist.Values) + { + if (!ident.Description.IsNullOrEmpty()) + { + strs.Add(" "); + } + + if (!ident.IsList) + { + strs.Add(" <" + ident.Key + ">" + ident.Value + ""); + } + else + { + strs.Add(" <" + ident.Key + ">"); + foreach (string value in ident.Values) + { + strs.Add(" " + value + ""); + } + + strs.Add(" "); + } + } + + strs.Add(""); + File.WriteAllLines(filename, strs.ToArray(), Encoding.UTF8); + } + + #endregion 加载 + } +} \ No newline at end of file diff --git a/SunnyUI/Controls/UIRoundMeter.cs b/SunnyUI/Controls/UIRoundMeter.cs index 87cc45b6..7fb758af 100644 --- a/SunnyUI/Controls/UIRoundMeter.cs +++ b/SunnyUI/Controls/UIRoundMeter.cs @@ -22,7 +22,6 @@ using System.ComponentModel; using System.Drawing; using System.Windows.Forms; -using Sunny.UI.Properties; namespace Sunny.UI { @@ -45,7 +44,7 @@ namespace Sunny.UI Custom, /// - /// The GPS + /// The Gps /// Gps, @@ -133,14 +132,14 @@ namespace Sunny.UI if (value == TMeterType.Gps) { - BackgroundImage = Resources.gps1; - AngleImage = Resources.gps_postion; + BackgroundImage = Sunny.UI.Properties.Resources.gps1; + AngleImage = Sunny.UI.Properties.Resources.gps_postion; } if (value == TMeterType.Wind) { - BackgroundImage = Resources.wind; - AngleImage = Resources.wind_postion; + BackgroundImage = Sunny.UI.Properties.Resources.wind; + AngleImage = Sunny.UI.Properties.Resources.wind_postion; } Invalidate(); diff --git a/SunnyUI/Controls/UIVerificationCode.cs b/SunnyUI/Controls/UIVerificationCode.cs index 94183d30..f5968fcb 100644 --- a/SunnyUI/Controls/UIVerificationCode.cs +++ b/SunnyUI/Controls/UIVerificationCode.cs @@ -97,10 +97,39 @@ namespace Sunny.UI { base.OnPaintFill(g, path); - using var bmp = CreateImage(RandomEx.RandomChars(CodeLength)); + using var bmp = CreateImage(RandomChars(CodeLength)); g.DrawImage(bmp, Width / 2 - bmp.Width / 2, 1); } + private const string CHARS_62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + + /// + /// 生成字母和数字的随机字符串 + /// + /// 长度 + /// 结果 + private static string RandomChars(int length = 10) + { + return RandomBase(CHARS_62.ToCharArray(), length); + } + + private static string RandomBase(char[] pattern, int length) + { + if (pattern.IsNullOrEmpty()) + { + throw new ArgumentNullException(); + } + + string result = ""; + for (int i = 0; i < length; i++) + { + Random random = new Random(DateTime.Now.Millisecond); + result += pattern[random.Next(0, pattern.Length)]; + } + + return result; + } + /// /// 绘制前景颜色 /// diff --git a/SunnyUI/Forms/UILoginForm.cs b/SunnyUI/Forms/UILoginForm.cs index 0ee362db..722e0aaa 100644 --- a/SunnyUI/Forms/UILoginForm.cs +++ b/SunnyUI/Forms/UILoginForm.cs @@ -20,7 +20,6 @@ * 2023-04-19: V3.3.5 增加可选择显示时激活的控件 ******************************************************************************/ -using Sunny.UI.Properties; using System; using System.ComponentModel; @@ -96,12 +95,12 @@ namespace Sunny.UI { loginImage = value; - if (loginImage == UILoginImage.Login1) BackgroundImage = Resources.Login1; - if (loginImage == UILoginImage.Login2) BackgroundImage = Resources.Login2; - if (loginImage == UILoginImage.Login3) BackgroundImage = Resources.Login3; - if (loginImage == UILoginImage.Login4) BackgroundImage = Resources.Login4; - if (loginImage == UILoginImage.Login5) BackgroundImage = Resources.Login5; - if (loginImage == UILoginImage.Login6) BackgroundImage = Resources.Login6; + if (loginImage == UILoginImage.Login1) BackgroundImage = Sunny.UI.Properties.Resources.Login1; + if (loginImage == UILoginImage.Login2) BackgroundImage = Sunny.UI.Properties.Resources.Login2; + if (loginImage == UILoginImage.Login3) BackgroundImage = Sunny.UI.Properties.Resources.Login3; + if (loginImage == UILoginImage.Login4) BackgroundImage = Sunny.UI.Properties.Resources.Login4; + if (loginImage == UILoginImage.Login5) BackgroundImage = Sunny.UI.Properties.Resources.Login5; + if (loginImage == UILoginImage.Login6) BackgroundImage = Sunny.UI.Properties.Resources.Login6; } } } diff --git a/SunnyUI/Style/UIMenuStyle.cs b/SunnyUI/Style/UIMenuStyle.cs index 44e7baa8..386f4fca 100644 --- a/SunnyUI/Style/UIMenuStyle.cs +++ b/SunnyUI/Style/UIMenuStyle.cs @@ -19,6 +19,7 @@ * 2020-01-01: V2.2.0 增加文件说明 ******************************************************************************/ +using System.ComponentModel; using System.Drawing; namespace Sunny.UI @@ -31,19 +32,19 @@ namespace Sunny.UI /// /// 自定义 /// - [DisplayText("Custom")] + [Description("Custom")] Custom, /// /// 黑 /// - [DisplayText("Black")] + [Description("Black")] Black, /// /// 白 /// - [DisplayText("White")] + [Description("White")] White } @@ -59,7 +60,7 @@ namespace Sunny.UI public override string ToString() { - return Style.DisplayText(); + return Style.Description(); } } diff --git a/SunnyUI/Style/UIStyle.cs b/SunnyUI/Style/UIStyle.cs index bcf8b8a3..57d14f74 100644 --- a/SunnyUI/Style/UIStyle.cs +++ b/SunnyUI/Style/UIStyle.cs @@ -25,6 +25,7 @@ ******************************************************************************/ using System.Collections.Generic; +using System.ComponentModel; using System.Drawing; using System.Reflection; using System.Windows.Forms; @@ -55,85 +56,85 @@ namespace Sunny.UI /// /// 继承的全局主题 /// - [DisplayText("继承的全局主题")] + [Description("继承的全局主题")] Inherited = -1, /// /// 自定义 /// - [DisplayText("Custom")] + [Description("Custom")] Custom = 0, /// /// 蓝 /// - [DisplayText("Blue")] + [Description("Blue")] Blue = 1, /// /// 绿 /// - [DisplayText("Green")] + [Description("Green")] Green = 2, /// /// 橙 /// - [DisplayText("Orange")] + [Description("Orange")] Orange = 3, /// /// 红 /// - [DisplayText("Red")] + [Description("Red")] Red = 4, /// /// 灰 /// - [DisplayText("Gray")] + [Description("Gray")] Gray = 5, /// /// 紫 /// - [DisplayText("Purple")] + [Description("Purple")] Purple = 6, /// /// LayuiGreen /// - [DisplayText("LayuiGreen")] + [Description("LayuiGreen")] LayuiGreen = 7, /// /// LayuiRed /// - [DisplayText("LayuiRed")] + [Description("LayuiRed")] LayuiRed = 8, /// /// LayuiOrange /// - [DisplayText("LayuiOrange")] + [Description("LayuiOrange")] LayuiOrange = 9, /// /// 深蓝 /// - [DisplayText("DarkBlue")] + [Description("DarkBlue")] DarkBlue = 101, /// /// 黑 /// - [DisplayText("Black")] + [Description("Black")] Black = 102, /// /// 多彩的 /// - [DisplayText("Colorful")] + [Description("Colorful")] Colorful = 999 } diff --git a/SunnyUI/Style/UIStyleColor.cs b/SunnyUI/Style/UIStyleColor.cs index 50ae6006..63bcbff6 100644 --- a/SunnyUI/Style/UIStyleColor.cs +++ b/SunnyUI/Style/UIStyleColor.cs @@ -419,7 +419,7 @@ namespace Sunny.UI public override string ToString() { - return Name.DisplayText(); + return Name.Description(); } public virtual bool BuiltIn => true; diff --git a/SunnyUI/Style/UTranslate.cs b/SunnyUI/Style/UTranslate.cs index 54f39b45..cad4c42e 100644 --- a/SunnyUI/Style/UTranslate.cs +++ b/SunnyUI/Style/UTranslate.cs @@ -210,10 +210,11 @@ namespace Sunny.UI string thisFullName = form.GetType().FullName; string section = "Info"; - string inifile = Dir.CurrentDir() + "Language\\" + thisFullName + ".ini"; - if (!File.Exists(inifile)) return; + string fullName = Dir.CurrentDir() + "Language\\" + thisFullName + ".ini"; + if (!File.Exists(fullName)) return; IniFile ini = new IniFile(Dir.CurrentDir() + "Language\\" + thisFullName + ".ini", System.Text.Encoding.UTF8); - int count = ini.ReadInt("Controls", "Count", 0); + string readString = ini.ReadString("Controls", "Count", ""); + if (!int.TryParse(readString, out int count)) return; if (count == 0) return; string key = UIStyles.CultureInfo.LCID.ToString() + ".Name"; diff --git a/SunnyUI/SunnyUI.csproj b/SunnyUI/SunnyUI.csproj index 76470461..5ebdf9d4 100644 --- a/SunnyUI/SunnyUI.csproj +++ b/SunnyUI/SunnyUI.csproj @@ -72,7 +72,7 @@ - +