以下是學習筆記:
1,參數設置的子窗體設置
【1.1】大小要和主窗體嵌入的panel尺寸一致
【2.2】字體和大小要一致
【3.3】無邊框設置FormBorderStyle.None
2,批量參數設置思路
Ini:
Section 1個:參數
Key 2個:基礎參數,高級參數
JSON:對象和JSON字符串之間的互相轉換
反射:控件Name就是對象屬性的名稱
Tag: 參數修改記錄
3,代碼實現步驟
【3.1】幫助類,寫在DAL中
【3.1.1】INI幫助類
using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace AutomaticStoreMotionDal { public class IniConfigHelper { #region 方法說明 //WritePrivateProfileString方法說明: //功能:將信息寫入ini文件 // 返回值:long,如果為0則表示寫入失敗,反之成功。 //參數1(section) :寫入ini文件的某個小節名稱(不區分大小寫)。 //參數2(key) :上面section下某個項的鍵名(不區分大小寫)。 //參數3(val) :上面key對應的value //參數4(filePath):ini的文件名,包括其路徑(example: "c:/config.ini")。如果沒有指定路徑,僅有文件名,系統會自動在windows目錄中查找是否有對應的ini文件,如果沒有則會自動在當前應用程序運行的根目錄下創建ini文件。 //GetPrivateProfileString方法使用說明: //功能:從ini文件中讀取相應信息 // 返回值:返回所取信息字符串的字節長度 // 參數1(section):某個小節名(不區分大小寫),如果為空,則將在retVal內裝載這個ini文件的所有小節列表。 //參數2(key) :欲獲取信息的某個鍵名(不區分大小寫),如果為空,則將在retVal內裝載指定小節下的所有鍵列表。 //參數3(def) :當指定信息,未找到時,則返回def,可以為空。 //參數4(retVal) :一個字串緩沖區,所要獲取的字符串將被保存在其中,其緩沖區大小至少為size。 //參數5(size) :retVal的緩沖區大小(最大字符數量)。 //參數6(filePath) :指定的ini文件路徑,如果沒有路徑,則在windows目錄下查找,如果還是沒有則在應用程序目錄下查找,再沒有,就只能返回def了。 #endregion #region API函數說明 //[DllImport("kernel32")] //private static extern long WritePrivateProfileString(string section, string key, string val, string filePath); //[DllImport("kernel32",EntryPoint = "GetPrivateProfileString")] //private static extern long GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath); [DllImport("kernel32", EntryPoint = "GetPrivateProfileString")] private static extern uint GetPrivateProfileStringA(string section, string key, string def, byte[] retVal, int size, string filePath); #endregion #region 讀寫INI文件相關 [DllImport("kernel32.dll", EntryPoint = "WritePrivateProfileString", CharSet = CharSet.Ansi)] private static extern long WritePrivateProfileString(string section, string key, string val, string filePath); [DllImport("kernel32.dll", EntryPoint = "GetPrivateProfileString", CharSet = CharSet.Ansi)] private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath); [DllImport("kernel32")] private static extern int GetPrivateProfileInt(string lpApplicationName, string lpKeyName, int nDefault, string lpFileName); [DllImport("kernel32.dll", EntryPoint = "GetPrivateProfileSectionNames", CharSet = CharSet.Ansi)] private static extern int GetPrivateProfileSectionNames(IntPtr lpszReturnBuffer, int nSize, string filePath); [DllImport("KERNEL32.DLL ", EntryPoint = "GetPrivateProfileSection", CharSet = CharSet.Ansi)] private static extern int GetPrivateProfileSection(string lpAppName, byte[] lpReturnedString, int nSize, string filePath); #endregion #region 讀寫操作(字符串) //定義一個路徑 public static string filePath = string.Empty; public static string ReadIniData(string Section, string Key, string NoText) { return ReadIniData(Section, Key, NoText, filePath); } /// <summary> /// 讀取INI數據 /// </summary> /// <param name="Section">節點名</param> /// <param name="Key">鍵名</param> /// <param name="NoText"></param> /// <param name="iniFilePath"></param> /// <returns></returns> public static string ReadIniData(string Section, string Key, string NoText, string iniFilePath) { if (File.Exists(iniFilePath)) { StringBuilder temp = new StringBuilder(1024); GetPrivateProfileString(Section, Key, NoText, temp, 1024, iniFilePath); return temp.ToString(); } else { return string.Empty; } } public static bool WriteIniData(string Section, string Key, string Value) { return WriteIniData(Section, Key, Value, filePath); } /// <summary> /// 向INI寫入數據 /// </summary> /// <param name="Section"></param> /// <param name="Key"></param> /// <param name="Value"></param> /// <param name="iniFilePath"></param> /// <returns></returns> public static bool WriteIniData(string Section, string Key, string Value, string iniFilePath) { if (!File.Exists(iniFilePath)) File.Create(iniFilePath); StringBuilder temp = new StringBuilder(1024); long OpStation = WritePrivateProfileString(Section, Key, Value, iniFilePath); if (OpStation == 0) { return false; } else { return true; } } #endregion #region 配置節信息 /// <summary> /// 讀取一個ini里面所有的節 /// </summary> /// <param name="sections"></param> /// <param name="path"></param> /// <returns>-1:沒有節信息,0:正常</returns> public static int GetAllSectionNames(out string[] sections, string path) { int MAX_BUFFER = 32767; IntPtr pReturnedString = Marshal.AllocCoTaskMem(MAX_BUFFER); int bytesReturned = GetPrivateProfileSectionNames(pReturnedString, MAX_BUFFER, path); if (bytesReturned == 0) { sections = null; return -1; } string local = Marshal.PtrToStringAnsi(pReturnedString, (int) bytesReturned).ToString(); Marshal.FreeCoTaskMem(pReturnedString); //use of Substring below removes terminating null for split sections = local.Substring(0, local.Length - 1).Split('\0'); return 0; } /// <summary> /// 返回指定配置文件下的節名稱列表 /// </summary> /// <param name="path"></param> /// <returns></returns> public static List<string> GetAllSectionNames(string path) { List<string> sectionList = new List<string>(); int MAX_BUFFER = 32767; IntPtr pReturnedString = Marshal.AllocCoTaskMem(MAX_BUFFER); int bytesReturned = GetPrivateProfileSectionNames(pReturnedString, MAX_BUFFER, path); if (bytesReturned != 0) { string local = Marshal.PtrToStringAnsi(pReturnedString, (int) bytesReturned).ToString(); Marshal.FreeCoTaskMem(pReturnedString); sectionList.AddRange(local.Substring(0, local.Length - 1).Split('\0')); } return sectionList; } /// <summary> /// 獲取所有的Sections /// </summary> /// <param name="iniFilePath"></param> /// <returns></returns> public static List<string> ReadSections(string iniFilePath) { List<string> sectionList = new List<string>(); byte[] buf = new byte[65536]; uint len = GetPrivateProfileStringA(null, null, null, buf, buf.Length, iniFilePath); int j = 0; for (int i = 0; i < len; i++) { if (buf[i] == 0) { sectionList.Add(Encoding.Default.GetString(buf, j, i - j)); j = i + 1; } } return sectionList; } /// <summary> /// 獲取指定Section下的所有Keys /// </summary> /// <param name="SectionName"></param> /// <param name="iniFilePath"></param> /// <returns></returns> public static List<string> ReadKeys(string SectionName, string iniFilePath) { List<string> sectionList = new List<string>(); byte[] buf = new byte[65536]; uint len = GetPrivateProfileStringA(null, null, null, buf, buf.Length, iniFilePath); int j = 0; for (int i = 0; i < len; i++) { if (buf[i] == 0) { sectionList.Add(Encoding.Default.GetString(buf, j, i - j)); j = i + 1; } } return sectionList; } /// <summary> /// 得到某個節點下面所有的key和value組合 /// </summary> /// <param name="section">指定的節名稱</param> /// <param name="keys">Key數組</param> /// <param name="values">Value數組</param> /// <param name="path">INI文件路徑</param> /// <returns></returns> public static int GetAllKeyValues(string section, out string[] keys, out string[] values, string path) { byte[] b = new byte[65535]; //配置節下的所有信息 GetPrivateProfileSection(section, b, b.Length, path); string s = System.Text.Encoding.Default.GetString(b); //配置信息 string[] tmp = s.Split((char) 0); //Key\Value信息 List<string> result = new List<string>(); foreach (string r in tmp) { if (r != string.Empty) result.Add(r); } keys = new string[result.Count]; values = new string[result.Count]; for (int i = 0; i < result.Count; i++) { string[] item = result[i].Split(new char[] {'='}); //Key=Value格式的配置信息 //Value字符串中含有=的處理, //一、Value加"",先對""處理 //二、Key后續的都為Value if (item.Length > 2) { keys[i] = item[0].Trim(); values[i] = result[i].Substring(keys[i].Length + 1); } if (item.Length == 2) //Key=Value { keys[i] = item[0].Trim(); values[i] = item[1].Trim(); } else if (item.Length == 1) //Key= { keys[i] = item[0].Trim(); values[i] = ""; } else if (item.Length == 0) { keys[i] = ""; values[i] = ""; } } return 0; } /// <summary> /// 得到某個節點下面所有的key /// </summary> /// <param name="section">指定的節名稱</param> /// <param name="keys">Key數組</param> /// <param name="path">INI文件路徑</param> /// <returns></returns> public static int GetAllKeys(string section, out string[] keys, string path) { byte[] b = new byte[65535]; GetPrivateProfileSection(section, b, b.Length, path); string s = System.Text.Encoding.Default.GetString(b); string[] tmp = s.Split((char) 0); ArrayList result = new ArrayList(); foreach (string r in tmp) { if (r != string.Empty) result.Add(r); } keys = new string[result.Count]; for (int i = 0; i < result.Count; i++) { string[] item = result[i].ToString().Split(new char[] {'='}); if (item.Length == 2) { keys[i] = item[0].Trim(); } else if (item.Length == 1) { keys[i] = item[0].Trim(); } else if (item.Length == 0) { keys[i] = ""; } } return 0; } /// <summary> /// 獲取指定節下的Key列表 /// </summary> /// <param name="section">指定的節名稱</param> /// <param name="path">配置文件名稱</param> /// <returns>Key列表</returns> public static List<string> GetAllKeys(string section, string path) { List<string> keyList = new List<string>(); byte[] b = new byte[65535]; GetPrivateProfileSection(section, b, b.Length, path); string s = System.Text.Encoding.Default.GetString(b); string[] tmp = s.Split((char) 0); List<string> result = new List<string>(); foreach (string r in tmp) { if (r != string.Empty) result.Add(r); } for (int i = 0; i < result.Count; i++) { string[] item = result[i].Split(new char[] {'='}); if (item.Length == 2 || item.Length == 1) { keyList.Add(item[0].Trim()); } else if (item.Length == 0) { keyList.Add(string.Empty); } } return keyList; } /// <summary> /// 獲取值 /// </summary> /// <param name="section"></param> /// <param name="path"></param> /// <returns></returns> public static List<string> GetAllValues(string section, string path) { List<string> keyList = new List<string>(); byte[] b = new byte[65535]; GetPrivateProfileSection(section, b, b.Length, path); string s = System.Text.Encoding.Default.GetString(b); string[] tmp = s.Split((char) 0); List<string> result = new List<string>(); foreach (string r in tmp) { if (r != string.Empty) result.Add(r); } for (int i = 0; i < result.Count; i++) { string[] item = result[i].Split(new char[] {'='}); if (item.Length == 2 || item.Length == 1) { keyList.Add(item[1].Trim()); } else if (item.Length == 0) { keyList.Add(string.Empty); } } return keyList; } #endregion #region 通過值查找鍵(一個節中的鍵唯一,可能存在多個鍵值相同,因此反查的結果可能為多個) /// <summary> /// 第一個鍵 /// </summary> /// <param name="section"></param> /// <param name="path"></param> /// <param name="value"></param> /// <returns></returns> public static string GetFirstKeyByValue(string section, string path, string value) { foreach (string key in GetAllKeys(section, path)) { if (ReadString(section, key, "", path) == value) { return key; } } return string.Empty; } /// <summary> /// 所有鍵 /// </summary> /// <param name="section"></param> /// <param name="path"></param> /// <param name="value"></param> /// <returns></returns> public static List<string> GetKeysByValue(string section, string path, string value) { List<string> keys = new List<string>(); foreach (string key in GetAllKeys(section, path)) { if (ReadString(section, key, "", path) == value) { keys.Add(key); } } return keys; } #endregion #region 具體類型的讀寫 #region string /// <summary> /// /// </summary> /// <param name="sectionName"></param> /// <param name="keyName"></param> /// <param name="defaultValue" /> /// <param name="path"></param> /// <returns></returns> public static string ReadString(string sectionName, string keyName, string defaultValue, string path) { const int MAXSIZE = 255; StringBuilder temp = new StringBuilder(MAXSIZE); GetPrivateProfileString(sectionName, keyName, defaultValue, temp, 255, path); return temp.ToString(); } /// <summary> /// /// </summary> /// <param name="sectionName"></param> /// <param name="keyName"></param> /// <param name="value"></param> /// <param name="path"></param> public static void WriteString(string sectionName, string keyName, string value, string path) { WritePrivateProfileString(sectionName, keyName, value, path); } #endregion #region Int /// <summary> /// /// </summary> /// <param name="sectionName"></param> /// <param name="keyName"></param> /// <param name="defaultValue"></param> /// <param name="path"></param> /// <returns></returns> public static int ReadInteger(string sectionName, string keyName, int defaultValue, string path) { return GetPrivateProfileInt(sectionName, keyName, defaultValue, path); } /// <summary> /// /// </summary> /// <param name="sectionName"></param> /// <param name="keyName"></param> /// <param name="value"></param> /// <param name="path"></param> public static void WriteInteger(string sectionName, string keyName, int value, string path) { WritePrivateProfileString(sectionName, keyName, value.ToString(), path); } #endregion #region bool /// <summary> /// 讀取布爾值 /// </summary> /// <param name="sectionName"></param> /// <param name="keyName"></param> /// <param name="defaultValue"></param> /// <param name="path"></param> /// <returns></returns> public static bool ReadBoolean(string sectionName, string keyName, bool defaultValue, string path) { int temp = defaultValue ? 1 : 0; int result = GetPrivateProfileInt(sectionName, keyName, temp, path); return (result == 0 ? false : true); } /// <summary> /// 寫入布爾值 /// </summary> /// <param name="sectionName"></param> /// <param name="keyName"></param> /// <param name="value"></param> /// <param name="path"></param> public static void WriteBoolean(string sectionName, string keyName, bool value, string path) { string temp = value ? "1 " : "0 "; WritePrivateProfileString(sectionName, keyName, temp, path); } #endregion #endregion #region 刪除操作 /// <summary> /// 刪除指定項 /// </summary> /// <param name="sectionName"></param> /// <param name="keyName"></param> /// <param name="path"></param> public static void DeleteKey(string sectionName, string keyName, string path) { WritePrivateProfileString(sectionName, keyName, null, path); } /// <summary> /// 刪除指定節下的所有項 /// </summary> /// <param name="sectionName"></param> /// <param name="path"></param> public static void EraseSection(string sectionName, string path) { WritePrivateProfileString(sectionName, null, null, path); } #endregion #region 判斷節、鍵是否存在 /// <summary> /// 指定節知否存在 /// </summary> /// <param name="section"></param> /// <param name="fileName"></param> /// <returns></returns> public static bool ExistSection(string section, string fileName) { string[] sections = null; GetAllSectionNames(out sections, fileName); if (sections != null) { foreach (var s in sections) { if (s == section) { return true; } } } return false; } /// <summary> /// 指定節下的鍵是否存在 /// </summary> /// <param name="section"></param> /// <param name="key"></param> /// <param name="fileName"></param> /// <returns></returns> public static bool ExistKey(string section, string key, string fileName) { string[] keys = null; GetAllKeys(section, out keys, fileName); if (keys != null) { foreach (var s in keys) { if (s == key) { return true; } } } return false; } #endregion #region 同一Section下添加多個Key\Value /// <summary> /// /// </summary> /// <param name="section"></param> /// <param name="keyList"></param> /// <param name="valueList"></param> /// <param name="path"></param> /// <returns></returns> public static bool AddSectionWithKeyValues(string section, List<string> keyList, List<string> valueList, string path) { bool bRst = true; //判斷Section是否已經存在,如果存在,返回false //已經存在,則更新 //if (GetAllSectionNames(path).Contains(section)) //{ // return false; //} //判斷keyList中是否有相同的Key,如果有,返回false //添加配置信息 for (int i = 0; i < keyList.Count; i++) { WriteString(section, keyList[i], valueList[i], path); } return bRst; } #endregion } }
【3.2.2】JSON幫助類
using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; /* * 需要添加引用Newtonsoft.Json.dll */ namespace AutomaticStoreMotionDal { public class JSONHelper { /// <summary> /// 實體對象轉JSON字符串 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="x"></param> /// <returns></returns> public static string EntityToJSON<T>(T x) { string result = string.Empty; try { result = JsonConvert.SerializeObject(x); } catch (Exception e) { result = string.Empty; } return result; } /// <summary> /// JSON字符串轉實體類 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="json"></param> /// <returns></returns> public static T JSONToEntity<T>(string json) { T t = default(T); try { t = (T) JsonConvert.DeserializeObject(json, typeof(T)); } catch (Exception e) { t = default(T); } return t; } } }
【3.2】實體類
【3.2.1】基礎參數類
namespace AutomaticStoreMotionModels { /// <summary> /// 基礎參數類 /// </summary> public class BasicParameter { //X軸稱重坐標值 public double Weight_X { get; set; } //Y軸稱重坐標值 public double Weight_Y { get; set; } //Z軸稱重坐標值 public double Weight_Z { get; set; } //X軸回收坐標值 public double Recycle_X { get; set; } //Y軸回收坐標值 public double Recycle_Y { get; set; } //Z軸回收坐標值 public double Recycle_Z { get; set; } //X軸待機坐標值 public double Standby_X { get; set; } //Y軸待機坐標值 public double Standby_Y { get; set; } //Z軸待機坐標值 public double Standby_Z { get; set; } //X軸初始坐標值 public double Initial_X { get; set; } //Y軸初始坐標值 public double Initial_Y { get; set; } //Z軸庫位坐標值 public double Initial_Z { get; set; } //X軸偏移坐標值 public double Offset_X { get; set; } //Y軸偏移坐標值 public double Offset_Y { get; set; } //Z軸安全坐標值 public double Offset_Z { get; set; } //X軸自動運行速度 public double SpeedAuto_X { get; set; } //Y軸自動運行速度 public double SpeedAuto_Y { get; set; } //Z軸自動運行速度 public double SpeedAuto_Z { get; set; } //X軸手動運行速度 public double SpeedHand_X { get; set; } = 15; //Y軸手動運行速度 public double SpeedHand_Y { get; set; } = 2; //Z軸手動運行速度 public double SpeedHand_Z { get; set; } = 1; //系統參數 //稱重端口 public string WeightPort { get; set; } = "COM1"; //掃碼槍端口 public string ScannerPort { get; set; } = "COM2"; //稱重波特率 public int WeightBaud { get; set; } = 9600; //掃碼槍波特率 public int ScannerBaud { get; set; } = 9600; //稱重參數 public string WeightParmeter { get; set; } = "N81"; //掃碼槍參數 public string ScannerParmeter { get; set; } = "N81"; //空瓶重量 public double EmptyWeight { get; set; } = 12.0f; //冗余重量 public double RedundancyWeight { get; set; } = 1.0f; //允許入庫數量 public int AllowInCount { get; set; } = 100; //允許出庫數量 public int AllowOutCount { get; set; } = 3; //自動鎖定間隔 單位秒 public int AtuoLock { get; set; } = 100; } }
【3.2.2】高級參數類
namespace AutomaticStoreMotionModels { /// <summary> /// 高級參數類 /// </summary> public class AdvancedParameter { //卡號 public short CardNo { get; set; } = 1; //軸數量 public short AxisCount { get; set; } = 4; //X軸 public short Axis_X { get; set; } = 1; //Y軸 public short Axis_Y { get; set; } = 2; //Z軸 public short Axis_Z { get; set; } = 3; //U軸 public short Axis_U { get; set; } = 4; //輸入輸出 //存料按鈕 public short StoreButton { get; set; } = 1; //取料按鈕 public short ReclaimButton { get; set; } = 2; //急停按鈕 public short EmergencyButton { get; set; } = 3; //夾子打開到位 public short ClipOpen { get; set; } = 4; //夾子關閉到位 public short ClipClose { get; set; } =5; //存料指示 public short StoreState { get; set; } = 1; //取料指示 public short ReclaimState { get; set; } = 2; //模式指示 public short ModeState { get; set; } = 3; //夾子控制 public short ClipCtrl { get; set; } = 4; //上左門控制 public short TopLeftDoor { get; set; } = 5; //上后門控制 public short TopBehindDoor { get; set; } = 6; //上右門控制 public short TopRightDoor { get; set; } = 7; //下前門控制 public short BottomBehindDoor { get; set; } = 8; //照明控制 public short LightCtrl { get; set; } = 9; //總行數 public short RowCount { get; set; } = 10; //總列數 public short ColumnCount { get; set; } = 9; //運動控制卡配置文件 public string Cfg { get; set; } = "thinger"; //脈沖當量(1個毫米對應多少個脈沖) //X軸縮放系數 public double Scale_X { get; set; } = 4000; //Y軸縮放系數 public double Scale_Y { get; set; } = 4000; //Z軸縮放系數 public double Scale_Z { get; set; } = 4000; //加速度 //X軸運動加速度 public double Acc_X { get; set; } = 0.01; //Y軸運動加速度 public double Acc_Y { get; set; } = 0.01; //Z軸運動加速度 public double Acc_Z { get; set; } = 0.01; //復位方向 } }
【3.2.3】操作結果的類
namespace AutomaticStoreMotionModels { /// <summary> /// 操作結果的類 /// </summary> public class OperationResult { /// <summary> /// 是否成功 /// </summary> public bool IsSuccess { get; set; } /// <summary> /// 錯誤信息 /// </summary> public string ErrorMsg { get; set; } /// <summary> /// 返回成功的操作結果 /// </summary> /// <returns></returns> public static OperationResult CreateSuccessResult() { return new OperationResult() { IsSuccess = true, ErrorMsg = "OK" }; } /// <summary> /// 返回失敗的操作結果 /// </summary> /// <returns></returns> public static OperationResult CreateFailResult() { return new OperationResult() { IsSuccess = false, ErrorMsg = "NG" }; } } }
4,新建一個公共方法,參數對象和參數保存和加載方法
namespace AutomaticStoreMotionDal { /// <summary> /// 公共方法 /// </summary> public class CommonMethods { #region 參數配置 /// <summary> /// 基礎參數 /// </summary> public static BasicParameter basicParameter = new BasicParameter(); /// <summary> /// 高級參數 /// </summary> public static AdvancedParameter advancedParameter = new AdvancedParameter(); /// <summary> /// 配置文件路徑 /// </summary> public static string configFile = Application.StartupPath + "\\Config\\Config.ini"; /// <summary> /// 保存基礎參數【把對象轉字符串保存在配置文件,保存修改參數時調用的方法】 /// </summary> /// <returns>操作結果</returns> public static OperationResult SaveBasicParmetmer() { //先將對象轉JSON字符串 string json = JSONHelper.EntityToJSON(basicParameter); //把json字符寫入INI if (IniConfigHelper.WriteIniData("參數", "基礎參數", json, configFile)) { return OperationResult.CreateSuccessResult(); } else { return OperationResult.CreateFailResult(); } } /// <summary> /// 保存高級參數【把對象轉字符串保存在配置文件,保存修改參數時調用的方法】 /// </summary> /// <returns>操作結果</returns> public static OperationResult SaveAdvancedParmetmer() { //先將對象轉JSON字符串 string json = JSONHelper.EntityToJSON(advancedParameter); //把json字符寫入INI if (IniConfigHelper.WriteIniData("參數", "高級參數", json, configFile)) { return OperationResult.CreateSuccessResult(); } else { return OperationResult.CreateFailResult(); } } /// <summary> /// 參數加載【主窗體加載的時候調用,配置文件轉對象】 /// </summary> /// <returns></returns> public static OperationResult LoadParameter() { try { //獲取INI文件中的基礎參數json字符串 string jsonBasic = IniConfigHelper.ReadIniData("參數", "基礎參數", JSONHelper.EntityToJSON(basicParameter), configFile); //json轉對象 if (!string.IsNullOrEmpty(jsonBasic)) //防止第一用的時候配置文件不存,basicParameter=null,導致參數加載都是空 basicParameter = JSONHelper.JSONToEntity<BasicParameter>(jsonBasic); //獲取INI文件中的高級參數json字符串 string jsonAdvanced = IniConfigHelper.ReadIniData("參數", "高級參數", JSONHelper.EntityToJSON(advancedParameter), configFile); //json轉對象 if (!string.IsNullOrEmpty(jsonAdvanced)) //防止第一用的時候配置文件不存,basicParameter=null,導致參數加載都是空 advancedParameter = JSONHelper.JSONToEntity<AdvancedParameter>(jsonAdvanced); } catch (Exception e) { return new OperationResult() { IsSuccess = false, ErrorMsg = e.Message //從這里獲取錯誤的信息 }; } return OperationResult.CreateSuccessResult(); } #endregion } }
5,參數設置界面
【5.1】界面UI
注意:控件的Name要跟對象屬性名稱保持一致
【5.2】 參數設置代碼:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.IO.Ports; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using AutomaticStoreMotionDal; using AutomaticStoreMotionModels; namespace AutomaticStoreMotionPro { public partial class FrmparameterSet : Form { public enum SerialParameter { N81, N71, E81, O81, O71 } public FrmparameterSet() { InitializeComponent(); //端口號 this.WeightPort.DataSource = SerialPort.GetPortNames(); this.ScannerPort.DataSource = SerialPort.GetPortNames(); //波特率 this.WeightBaud.DataSource=new string[]{"4800","9600","19200","38400"}; this.WeightBaud.DataSource=new string[]{"4800","9600","19200","38400"}; //參數 this.WeightParmeter.DataSource = Enum.GetNames(typeof(SerialParameter)); this.ScannerParmeter.DataSource = Enum.GetNames(typeof(SerialParameter)); //方向 //配置 DirectoryInfo directoryInfo = new DirectoryInfo(Application.StartupPath + "\\Config"); foreach (FileInfo file in directoryInfo.GetFiles("*.cfg")) { this.Cfg.Items.Add(file.Name); } //讀取配置文件給控件顯示 InitialParameter(this.tabPage1, CommonMethods.basicParameter); InitialParameter(this.tabPage2, CommonMethods.advancedParameter); } /// <summary> /// 加載參數【把對象屬性的值賦值給控件顯示】 /// </summary> /// <typeparam name="T">對象類型</typeparam> /// <param name="tabPage">容器</param> /// <param name="obj">對象</param> private void InitialParameter<T>(TabPage tabPage,T obj) { foreach (var item in tabPage.Controls) { if (item is NumericUpDown numeric) { //獲取控件的名稱 string propertyName = numeric.Name; //通過控件的名稱,拿到對象屬性的值 string value = GetObjectPropertyVaule(obj, propertyName); if (value != null && value.Length > 0) { if (decimal.TryParse(value, out decimal val)) { //把對象屬性的值賦值給控件顯示 numeric.Value = val; } } } else if(item is ComboBox cmb) { //獲取控件的名稱 string propertyName = cmb.Name; //通過控件的名稱,拿到對象屬性的值 string value = GetObjectPropertyVaule(obj, propertyName); //把對象的值賦值給控件顯示 if (value != null) cmb.Text = value; } } } /// <summary> /// 修改參數【根據控件名稱給對象的屬性賦值】 /// </summary> /// <typeparam name="T">對象類型</typeparam> /// <param name="parameterType">參數類型</param> /// <param name="obj">對象</param> private void ModifyParameter<T>(string parameterType,T obj) { StringBuilder sb=new StringBuilder(); foreach (var item in this.tab_main.SelectedTab.Controls) { if (item is NumericUpDown numeric) { //獲取控件的名稱(控件的名稱對應的是對象屬性的名稱) string propertyName = numeric.Name; //通過對象屬性名稱拿到屬性的值 string value = GetObjectPropertyVaule(obj, propertyName); //如果控制的值和對象屬性的值不一致,表示有修改動作 if (value.Length>0&& numeric.Value.ToString() != value) { //添加修改記錄 sb.Append(numeric.Tag.ToString() + "修改為:" + numeric.Value.ToString() + "; "); //通過屬性名稱給對象的屬性賦值 SetObjectPropertyVaule(obj, propertyName, numeric.Value.ToString()); } } else if(item is ComboBox cmb) { //獲取控件的名稱(控件的名稱對應的是對象屬性的名稱) string propertyName = cmb.Name; //通過對象屬性名稱拿到屬性的值 string value = GetObjectPropertyVaule(obj, propertyName); //如果控制的值和對象屬性的值不一致,表示有修改動作 if (value.Length > 0 && cmb.Text != value) { //添加修改記錄 sb.Append(cmb.Tag.ToString() + "修改為:" + cmb.Text.ToString() + "; "); //通過屬性名稱給對象的屬性賦值 SetObjectPropertyVaule(obj, propertyName, cmb.Text.ToString()); } } } if (sb.ToString().Length > 0) { OperationResult result = parameterType == "基礎參數" ? CommonMethods.SaveBasicParmetmer() : CommonMethods.SaveAdvancedParmetmer(); if (result.IsSuccess) { //寫入數據庫 if (!SysLogService.AddSysLog(new SysLog(sb.ToString(), "觸發", LogTye.操作記錄, GlobalVariable.SysAdmin.LoginName))) { NLogHelper.Error("參數修改記錄寫入數據庫出錯"); }; MessageBox.Show(parameterType+"修改成功", "參數修改"); } else { MessageBox.Show(parameterType + "修改失敗", "參數修改"); } } else { MessageBox.Show("參數未做任何修改", "參數修改"); } } /// <summary> /// 通過屬性名稱獲對象屬性的值 /// </summary> /// <typeparam name="T">對象類型</typeparam> /// <param name="obj">對象</param> /// <param name="propertyName">屬性名稱</param> /// <returns>返回值</returns> private string GetObjectPropertyVaule<T>(T obj, string propertyName) { try { Type type = typeof(T); PropertyInfo property = type.GetProperty(propertyName); if (property == null) { return string.Empty; } object val = property.GetValue(obj, null); return val?.ToString(); } catch (Exception e) { NLogHelper.Info("通過屬性名獲取值",e.Message); return null; } } /// <summary> /// 通過屬性名稱給對象的屬性賦值 /// </summary> /// <typeparam name="T">對象類型</typeparam> /// <param name="obj">對象</param> /// <param name="propertyName">屬性名稱</param> /// <param name="value">值</param> /// <returns></returns> private bool SetObjectPropertyVaule<T>(T obj, string propertyName,string value) { try { Type type = typeof(T); object t = Convert.ChangeType(value, type.GetProperty(propertyName).PropertyType); type.GetProperty(propertyName).SetValue(obj,t,null); return true; } catch (Exception e) { return false; } } //保存修改 private void btn_modifyBasic_Click(object sender, EventArgs e) { ModifyParameter("基礎參數", CommonMethods.basicParameter); } //取消修改 private void btn_cancelBasic_Click(object sender, EventArgs e) { InitialParameter(this.tab_main.SelectedTab, CommonMethods.basicParameter); } //保存修改 private void btn_modifyAdvanced_Click(object sender, EventArgs e) { ModifyParameter("高級參數", CommonMethods.advancedParameter); } //取消修改 private void btn_cancelAdvanced_Click(object sender, EventArgs e) { InitialParameter(this.tab_main.SelectedTab, CommonMethods.advancedParameter); } } }
6,配置文件結果:
E:\VS workspace\學習C sharp運動控制\AutomaticStoreMotionPro\AutomaticStoreMotionPro\bin\Debug\Config
[參數]
基礎參數={"Weight_X":1.0,"Weight_Y":2.0,"Weight_Z":3.0,"Recycle_X":0.0,"Recycle_Y":0.0,"Recycle_Z":0.0,"Standby_X":0.0,"Standby_Y":0.0,"Standby_Z":0.0,"Initial_X":0.0,"Initial_Y":0.0,"Initial_Z":0.0,"Offset_X":0.0,"Offset_Y":0.0,"Offset_Z":0.0,"SpeedAuto_X":0.0,"SpeedAuto_Y":0.0,"SpeedAuto_Z":0.0,"SpeedHand_X":17.0,"SpeedHand_Y":2.0,"SpeedHand_Z":2.0,"WeightPort":"COM1","ScannerPort":"COM2","WeightBaud":9600,"ScannerBaud":9600,"WeightParmeter":"N81","ScannerParmeter":"N81","EmptyWeight":12.0,"RedundancyWeight":1.0,"AllowInCount":100,"AllowOutCount":3,"AutoLock":0}
高級參數={"CardNo":1,"AxisCount":4,"Axis_X":1,"Axis_Y":2,"Axis_Z":3,"Axis_U":4,"StoreButton":3,"ReclaimButton":2,"EmergencyButton":1,"ClipOpen":4,"ClipClose":5,"StoreState":1,"ReclaimState":2,"ModeState":3,"ClipCtrl":4,"TopLeftDoor":5,"TopBehindDoor":6,"TopRightDoor":7,"BottomBehindDoor":8,"LightCtrl":9,"RowCount":10,"ColumnCount":9,"Cfg":"thinger","Scale_X":4000.0,"Scale_Y":4000.0,"Scale_Z":4000.0,"Acc_X":0.01,"Acc_Y":0.01,"Acc_Z":0.01,"HomeDir_X":null,"HomePos_X":0,"HomeNeg_X":0,"HomeOffset_X":0}