You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

593 lines
22 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// <copyright file="Config.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
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()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ConfigItem"/> class.
/// </summary>
/// <param name="itemCaption">The item caption.</param>
/// <param name="itemName">The item name.</param>
/// <param name="itemValue">The item value.</param>
/// <param name="itemOrder">The item order.</param>
public ConfigItem(string itemName, string itemCaption, object itemValue, int itemOrder = -1)
{
ItemCaption = itemCaption;
ItemName = itemName;
ItemValue = itemValue;
ItemOrder = itemOrder;
}
/// <summary>
/// 配置名称显示
/// </summary>
[XmlAttribute]
public string ItemCaption { get; set; }
/// <summary>
/// 配置名称
/// </summary>
[XmlAttribute]
public string ItemName { get; set; }
/// <summary>
/// 配置值
/// </summary>
public object ItemValue { get; set; }
[XmlAttribute]
public int ItemOrder { get; set; } = -1;
}
/// <summary>
/// The config item.
/// </summary>
public class ConfigNode
{
/// <summary>
/// 配置分类
/// </summary>
[XmlAttribute]
public string Name { get; set; }
/// <summary>
/// 配置分类显示
/// </summary>
[XmlAttribute]
public string Caption { get; set; }
//[XmlElement]
//public List<ConfigNode> ConfigNodes { get; set; }
[XmlAttribute]
public int DisplayOrder { get; set; } = 0;
[XmlElement]
public CustomProperties ConfigItems { get; set; } = new CustomProperties();
/// <summary>
/// Initializes a new instance of the <see cref="ConfigNode"/> class.
/// </summary>
public ConfigNode()
{
//ConfigNodes = new List<ConfigNode>();
}
[XmlAttribute]
public bool Display { get; set; } = true;
/// <summary>
/// Initializes a new instance of the <see cref="ConfigNode"/> class.
/// </summary>
/// <param name="name">The config type.</param>
/// <param name="caption">The config name.</param>
/// <param name="display">是否显示</param>
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;
}
/// <summary>
/// Adds the item.
/// </summary>
/// <param name="item">The item.</param>
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<ConfigNode> ConfigNodes { get; set; } = new List<ConfigNode>();
//string path = System.IO.Path.Combine(Application.StartupPath,"pos.ini");
/// <summary>
/// 添加新节点.
/// </summary>
/// <param name="newNode">The new node.</param>
public void AddNode(ConfigNode newNode)
{
ConfigNodes.Add(newNode);
}
/// <summary>
/// Finds the config value.
/// </summary>
/// <param name="configName">The config name.</param>
/// <returns>An object.</returns>
public CustomProperty FindConfigValue(string configName)
{
IEnumerable<CustomProperty> 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;
}
/// <summary>
/// Finds the config value.
/// </summary>
/// <param name="nodeName">The node name.</param>
/// <param name="configName">The config name.</param>
/// <param name="defaultValue">The default value.</param>
/// <returns>A T.</returns>
public T FindConfigValue<T>(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<T>(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文件名
/// <summary>
/// Prevents a default instance of the <see cref="DrawerConfig"/> class from being created.
/// </summary>
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;
/// <summary>
/// Gets or sets 程序启动目录.
/// </summary>
public static string StartupPath
{
get => s_startupPath;
set { s_startupPath = value; }
}
public static string ConfigFile { get; set; }
/// <summary>
/// Gets or sets the instance.
/// </summary>
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;
}
}
/// <summary>
/// 写出统计结果
/// </summary>
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<ConfigNode>));
XmlSerializerNamespaces nameSpace = new XmlSerializerNamespaces();
nameSpace.Add(string.Empty, string.Empty);
xmlSerializer.Serialize(writer, this.ConfigNodes, nameSpace);
}
}
/// <summary>
/// 打开配置文件.
/// </summary>
/// <returns>是否成功</returns>
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<ConfigNode>));
this.ConfigNodes = xmlSerializer.Deserialize(reader) as List<ConfigNode>;
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<ConfigNode> 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();
}
}
}