// // Copyright (c) PlaceholderCompany. All rights reserved. // using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; using System.Xml.Serialization; namespace GeoSigma.SigmaDrawerUtil { public class ConfigItem { public ConfigItem() { } /// /// Initializes a new instance of the class. /// /// The item caption. /// The item name. /// The item value. /// The item order. public ConfigItem(string itemName, string itemCaption, object itemValue, int itemOrder = -1) { ItemCaption = itemCaption; ItemName = itemName; ItemValue = itemValue; ItemOrder = itemOrder; } /// /// 配置名称显示 /// [XmlAttribute] public string ItemCaption { get; set; } /// /// 配置名称 /// [XmlAttribute] public string ItemName { get; set; } /// /// 配置值 /// public object ItemValue { get; set; } [XmlAttribute] public int ItemOrder { get; set; } = -1; } /// /// The config item. /// public class ConfigNode { /// /// 配置分类 /// [XmlAttribute] public string Name { get; set; } /// /// 配置分类显示 /// [XmlAttribute] public string Caption { get; set; } //[XmlElement] //public List ConfigNodes { get; set; } [XmlAttribute] public int DisplayOrder { get; set; } = 0; [XmlElement] public CustomProperties ConfigItems { get; set; } = new CustomProperties(); /// /// Initializes a new instance of the class. /// public ConfigNode() { //ConfigNodes = new List(); } [XmlAttribute] public bool Display { get; set; } = true; /// /// Initializes a new instance of the class. /// /// The config type. /// The config name. /// 是否显示 public ConfigNode(string name, string caption, bool display) : base() { Name = name; Caption = caption; this.Display = display; } public ConfigNode Clone() { ConfigNode node = new ConfigNode(this.Name, this.Caption, this.Display); foreach (CustomProperty property in this.ConfigItems) { node.AddItem(property.Clone()); } return node; } /// /// Adds the item. /// /// The item. public void AddItem(CustomProperty item) { ConfigItems.Add(item); if (item.ItemOrder <= 0) { item.ItemOrder = ConfigItems.Count - 1; } } } public delegate void ConfigChangedEventHandler(CustomProperty property, string nodeName); public class DrawerConfig { public ConfigChangedEventHandler ConfigChangedEvent; [XmlIgnore] public string FileName; //INI文件名 private string configFile; [XmlElement("ConfigNodes")] public List ConfigNodes { get; set; } = new List(); //string path = System.IO.Path.Combine(Application.StartupPath,"pos.ini"); /// /// 添加新节点. /// /// The new node. public void AddNode(ConfigNode newNode) { ConfigNodes.Add(newNode); } /// /// Finds the config value. /// /// The config name. /// An object. public CustomProperty FindConfigValue(string configName) { IEnumerable propFind = ConfigNodes.Select(node => { CustomProperty prop = node.ConfigItems.FirstOrDefault(it => it.Name.Equals(configName)); return prop; }) .Where(it => it != null); if (propFind != null) { CustomProperty prop = propFind.ElementAt(0); return prop; } return null; } /// /// Finds the config value. /// /// The node name. /// The config name. /// The default value. /// A T. public T FindConfigValue(string nodeName, string configName, T defaultValue) { ConfigNode node = ConfigNodes.FirstOrDefault(it => it.Name.Equals(nodeName)); if (node == null) { return defaultValue; } CustomProperty prop = node.ConfigItems.FirstOrDefault(it => it.Name.Equals(configName)); if (prop == null) { return defaultValue; } return (T)prop.Value; } public bool SetConfigValue(string nodeName, string configName, T value) { CustomProperty prop = ConfigNodes.FirstOrDefault(it => it.Name == nodeName) ?.ConfigItems .FirstOrDefault(it => it.Name == configName); if (prop == null) { Console.WriteLine($"未找到配置项: {nodeName}/{configName}"); return false; } prop.Value = value; return true; } //声明读写INI文件的API函数 [DllImport("kernel32")] private static extern bool WritePrivateProfileString(string section, string key, string val, string filePath); [DllImport("kernel32")] private static extern int GetPrivateProfileString(string section, string key, string def, byte[] retVal, int size, string filePath); //public string GetValue(string key) //{ // if (configData.Count <= 0) // return null; // else if (configData.ContainsKey(key)) // return configData[key].ToString(); // else // return null; //} //public void SetValue(string key, string value) //{ // if (configData.ContainsKey(key)) // configData[key] = value; // else // configData.Add(key, value); //} //public void Save() //{ // StreamWriter writer = new StreamWriter(fullFileName, false, Encoding.Default); // IDictionaryEnumerator enu = configData.GetEnumerator(); // while (enu.MoveNext()) // { // if (enu.Key.ToString().StartsWith(";")) // writer.WriteLine(enu.Value); // else // writer.WriteLine(enu.Key + "=" + enu.Value); // } // writer.Close(); //} //类的构造函数,传递INI文件名 /// /// Prevents a default instance of the class from being created. /// private DrawerConfig() { var path = StartupPath; if (string.IsNullOrEmpty(path)) { path = System.AppDomain.CurrentDomain.BaseDirectory; } var strFileName = path + "\\Sigma.config"; FileInfo fileInfo = new FileInfo(strFileName); // 必须是完全路径,不能是相对路径 FileName = fileInfo.FullName; configFile = Path.Combine(path, "KevConfig.xml"); ConfigFile = configFile; } private static DrawerConfig instance; private static string s_startupPath = string.Empty; /// /// Gets or sets 程序启动目录. /// public static string StartupPath { get => s_startupPath; set { s_startupPath = value; } } public static string ConfigFile { get; set; } /// /// Gets or sets the instance. /// public static DrawerConfig Instance { get { if (instance == null) { instance = new DrawerConfig(); if (instance.Open() == false) { ConfigNode node = new ConfigNode("RecentFiles", "最近打开的文件", false); node.ConfigItems.Add(new CustomProperty("FileNumbers", null, "记录数量", 8, typeof(int), "记录数量", false)); node.ConfigItems.Add(new CustomProperty("FileName", null, "上次打开的文件", @"c:\temp\某地区射层层深度构造图.dfd", typeof(string), null, false)); ConfigNode nodeTheme = new ConfigNode("Theme", "界面主题", false); nodeTheme.ConfigItems.Add(new CustomProperty("Version", null, "主题名称", "WeifenLuo.WinFormsUI.Docking.VS2013LightTheme", typeof(string))); ConfigNode nodeDisplay = new ConfigNode("Display", "显示", true); nodeDisplay.ConfigItems.Add(new CustomProperty("ZoomMode", null, "缩放模式", 1, typeof(int))); nodeDisplay.ConfigItems.Add(new CustomProperty("Precision", null, "保留小数", -1, typeof(int))); ConfigNode nodeGridSet = new ConfigNode("GridSet", "绘图网格", true); nodeGridSet.ConfigItems.Add(new CustomProperty("ShowGrid", null, "显示网格", false, typeof(bool), "是否显示网格", true, false, 0)); nodeGridSet.ConfigItems.Add(new CustomProperty("X", null, "X", 0.5d, typeof(double), "X方向间距", true, false, 1)); nodeGridSet.ConfigItems.Add(new CustomProperty("Y", null, "Y", 0.5d, typeof(double), "Y方向间距", true, false, 2)); ConfigNode nodeIntersection = new ConfigNode("Extension", "区域充填", true); nodeIntersection.ConfigItems.Add(new CustomProperty("Length", null, "延伸长度", 100d, typeof(double))); ConfigNode nodeMesh = new ConfigNode("MeshDisplay", "曲面网格", true); nodeMesh.ConfigItems.Add(new CustomProperty("SmoothTeeth", null, "消除锯齿", false, typeof(bool))); nodeMesh.ConfigItems.Add(new CustomProperty("LoopColor", null, "循环颜色", false, typeof(bool))); ConfigNode nodeSelectRange = new ConfigNode("SelectRange", "选择范围", true); nodeSelectRange.ConfigItems.Add(new CustomProperty("Extension", null, "相交面积百分比", 100d, typeof(double))); ConfigNode nodeAreaTrade = new ConfigNode("AreaTrade", "面积计算", true); nodeAreaTrade.ConfigItems.Add(new CustomProperty("CaculateMethod", null, "面积权衡方式", 0, typeof(int))); ConfigNode debugNode = new ConfigNode("Debug", "调试", true); debugNode.ConfigItems.Add(new CustomProperty("Enable", null, "启用", false, typeof(bool))); instance.ConfigNodes.AddRange(new ConfigNode[] { node , nodeTheme , nodeDisplay , nodeGridSet , nodeIntersection , nodeMesh , nodeSelectRange , nodeAreaTrade , debugNode, }); instance.Save(); instance.SetDefaultEditor(instance.ConfigNodes); } } return instance; } set { instance = value; } } /// /// 写出统计结果 /// public void Save() { string strFile = this.configFile; if (!File.Exists(strFile)) { File.Create(strFile).Close(); } using (StreamWriter writer = new StreamWriter(strFile)) { XmlSerializer xmlSerializer = new XmlSerializer(typeof(List)); XmlSerializerNamespaces nameSpace = new XmlSerializerNamespaces(); nameSpace.Add(string.Empty, string.Empty); xmlSerializer.Serialize(writer, this.ConfigNodes, nameSpace); } } /// /// 打开配置文件. /// /// 是否成功 public bool Open() { string strFile = this.configFile; Trace.WriteLine(strFile); if (string.IsNullOrEmpty(strFile) || !File.Exists(strFile)) { return false; } try { using (StreamReader reader = new StreamReader(strFile)) { XmlSerializer xmlSerializer = new XmlSerializer(typeof(List)); this.ConfigNodes = xmlSerializer.Deserialize(reader) as List; SetDefaultEditor(this.ConfigNodes); } } catch (Exception ex) { return false; } return true; } public DrawerConfig Clone() { DrawerConfig config = new DrawerConfig(); foreach (ConfigNode node in this.ConfigNodes) { config.ConfigNodes.Add(node.Clone()); } return config; } private void SetDefaultEditor(List nodes) { for (int i = 0; i < nodes.Count; i++) { for (int j = 0; j < nodes[i].ConfigItems.Count; j++) { CustomProperty prop = nodes[i].ConfigItems[j]; prop.PropertyType = prop.Value.GetType(); if (prop.Name.Equals("ZoomMode")) { prop.Converter = new StringComboItemConvert("左上,居中"); } else if (prop.Name.Equals("CaculateMethod")) { prop.Converter = new StringComboItemConvert("积分方式,等值线区域"); } else if (prop.PropertyType == typeof(bool)) { prop.Converter = new CustomBooleanConverter(); } else { prop.Converter = null; } prop.ParentName = nodes[i].Name; prop.PropertyChanged -= Prop_PropertyChanged; prop.PropertyChanged += Prop_PropertyChanged; //if (prop.PropertyChanged == null) //{ // prop.PropertyChanged += (object sender, System.ComponentModel.PropertyChangedEventArgs e) => // { // ConfigChangedEvent?.Invoke(prop, nodes[i].Name); // }; //} } } } private void Prop_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { PropertyChangedEventArgsEx ex = e as PropertyChangedEventArgsEx; if (ex != null) { ConfigChangedEvent?.Invoke(sender as CustomProperty, ex.ParentName); } } //写INI文件 public void WriteString(string section, string ident, string value) { if (!WritePrivateProfileString(section, ident, value, FileName)) { throw (new ApplicationException("写Ini文件出错")); } } //读取INI文件指定 public string ReadString(string section, string ident, string @default) { byte[] buffer = new byte[65535]; int bufLen = GetPrivateProfileString(section, ident, @default, buffer, buffer.GetUpperBound(0), FileName); //必须设定0(系统默认的代码页)的编码方式,否则无法支持中文 string s = Encoding.GetEncoding(0).GetString(buffer); s = s.Substring(0, bufLen); return s.Trim(); } ////读整数 //public int ReadInteger(string section, string ident, int @default) //{ // string intStr = ReadString(section, ident, Convert.ToString(@default)); // try // { // return Convert.ToInt32(intStr); // } // catch (Exception ex) // { // Console.WriteLine(ex.Message); // return @default; // } //} //写整数 public void WriteInteger(string section, string ident, int value) { WriteString(section, ident, value.ToString()); } ////读布尔 //public bool ReadBool(string section, string ident, bool @default) //{ // try // { // return Convert.ToBoolean(ReadString(section, ident, Convert.ToString(@default))); // } // catch (Exception ex) // { // Console.WriteLine(ex.Message); // return @default; // } //} //写Bool public void WriteBool(string section, string ident, bool value) { WriteString(section, ident, Convert.ToString(value)); } //从Ini文件中,将指定的Section名称中的所有Ident添加到列表中 public void ReadSection(string section, StringCollection idents) { Byte[] Buffer = new Byte[16384]; //Idents.Clear(); int bufLen = GetPrivateProfileString(section, null, null, Buffer, Buffer.GetUpperBound(0), FileName); //对Section进行解析 GetStringsFromBuffer(Buffer, bufLen, idents); } private void GetStringsFromBuffer(Byte[] buffer, int bufLen, StringCollection strings) { strings.Clear(); if (bufLen != 0) { int start = 0; for (int i = 0; i < bufLen; i++) { if ((buffer[i] == 0) && ((i - start) > 0)) { String s = Encoding.GetEncoding(0).GetString(buffer, start, i - start); strings.Add(s); start = i + 1; } } } } //从Ini文件中,读取所有的Sections的名称 public void ReadSections(StringCollection sectionList) { //Note:必须得用Bytes来实现,StringBuilder只能取到第一个Section byte[] Buffer = new byte[65535]; int bufLen = 0; bufLen = GetPrivateProfileString(null, null, null, Buffer, Buffer.GetUpperBound(0), FileName); GetStringsFromBuffer(Buffer, bufLen, sectionList); } ////读取指定的Section的所有Value到列表中 //public void ReadSectionValues(string section, NameValueCollection values) //{ // StringCollection KeyList = new StringCollection(); // ReadSection(section, KeyList); // values.Clear(); // foreach (string key in KeyList) // { // values.Add(key, ReadString(section, key, string.Empty)); // } //} //清除某个Section public void EraseSection(string section) { if (!WritePrivateProfileString(section, null, null, FileName)) { throw (new ApplicationException("无法清除Ini文件中的Section")); } } //删除某个Section下的键 public void DeleteKey(string section, string ident) { WritePrivateProfileString(section, ident, null, FileName); } //Note:对于Win9X,来说需要实现UpdateFile方法将缓冲中的数据写入文件 //在Win NT, 2000和XP上,都是直接写文件,没有缓冲,所以,无须实现UpdateFile //执行完对Ini文件的修改之后,应该调用本方法更新缓冲区。 public void UpdateFile() { WritePrivateProfileString(null, null, null, FileName); } //检查某个Section下的某个键值是否存在 public bool ValueExists(string section, string ident) { StringCollection Idents = new StringCollection(); ReadSection(section, Idents); return Idents.IndexOf(ident) > -1; } //确保资源的释放 ~DrawerConfig() { //UpdateFile(); } } }