跟具外部文件动态创建控件或加载文件的方式提高了代码的复用性减少了冗余代码。
以下演示一个自动化设备开发中通过INI文件将IO点位生成Button按钮,通过点击事件控制IO状态。
INI文件内容:
读取INI文件的类:
class INI
{
/// <summary>
/// 获取某个指定节点(Section)中所有KEY和Value
/// </summary>
/// <param name="lpAppName">节点名称</param>
/// <param name="lpReturnedString">返回值的内存地址,每个之间用\0分隔</param>
/// <param name="nSize">内存大小(characters)</param>
/// <param name="lpFileName">Ini文件</param>
/// <returns>内容的实际长度,为0表示没有内容,为nSize-2表示内存大小不够</returns>
[System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern uint GetPrivateProfileSection(string lpAppName, IntPtr lpReturnedString, uint nSize, string lpFileName);
public static Dictionary<string, string> GetINISectionDic(string iniFile, string section)
{
uint MAX_BUFFER = 32767;
string[] items = null;
//分配内存
IntPtr pReturnedString = System.Runtime.InteropServices.Marshal.AllocCoTaskMem((int)MAX_BUFFER * sizeof(char));
uint bytesReturned = GetPrivateProfileSection(section, pReturnedString, MAX_BUFFER, iniFile);
if (!(bytesReturned == MAX_BUFFER - 2) || (bytesReturned == 0))
{
string returnedString = System.Runtime.InteropServices.Marshal.PtrToStringAuto(pReturnedString, (int)bytesReturned);
items = returnedString.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
}
System.Runtime.InteropServices.Marshal.FreeCoTaskMem(pReturnedString); //释放内存
//无结果返回空
if (items == null)
{
return null;
}
Dictionary<string, string> dic = new Dictionary<string, string>();
foreach (string item in items)
{
if (!item.Contains("="))
{
continue;
}
string[] part = item.Split('=');
dic.Add(part[0], part[1]);
}
return dic;
}
自动创建控件的代码:
#region 控件的动态创建相关
private void ClearCreatControl() {
this.tabPage1.Controls.Clear();
this.tabPage2.Controls.Clear();
butList.Clear();
}
//加载输入IO页
private void LoadInputPage(string iniPath, ref List<Button> butList) {
if (!File.Exists(iniPath))
{
return;
}
string section = "Input";
Dictionary<string,string> inputDic = INI.GetINISectionDic(iniPath,section);
TableLayoutPanel tlp = Creat_Table(inputDic, section, ref butList);
this.tabPage1.Controls.Add(tlp);
}
//加载输出IO页面
private void LoadOutputPage(string iniPath, ref List<Button> butList) {
if (!File.Exists(iniPath))
{
return;
}
string section = "Output";
Dictionary<string, string> ouputDic = INI.GetINISectionDic(iniPath, section);
TableLayoutPanel tlp = Creat_Table(ouputDic, section, ref butList);
this.tabPage2.Controls.Add(tlp);
}
//创建button控件的方法
private List<Button> Creat_Button(Dictionary<string, string> dic, string section, ref List<Button> butList)
{
List<Button> listBut = new List<Button>();
foreach (KeyValuePair<string, string> kv in dic)
{
Button but = new Button();
but.Name = kv.Key;
but.Text = kv.Value;
but.Size = new Size(200, 60);
but.Font = new Font("隶书", 16, FontStyle.Bold);
but.TextAlign = ContentAlignment.MiddleCenter;
//是否允许绑定按钮事件。由INI_IOItem类中的枚举决定,其中value = 1的被定义为具有点击事件
if (section == "Input")
{
//给button绑定出发事件
but.Click += btn_WriteDeviceRandom;
}
butList.Add(but);
listBut.Add(but);
}
return listBut;
}
//创建表格控件的方法
private TableLayoutPanel Creat_Table(Dictionary<string, string> dic, string section, ref List<Button> butList)
{
//创建一个动态TableLayoutPanel控件
TableLayoutPanel table = new TableLayoutPanel();
int dataCount = (dic.Count == 0) ? 1:dic.Count ;
//获取父节控件的大小
int tSize1 = tabControl1.Width - 5;
int tSize2 = dataCount * 60 / 5;
if (dataCount <= 5)
{
tSize2 = dataCount * 60;
}
//设置table大小
table.Size = new Size(tSize1, tSize2);
//显示table边框
//table.CellBorderStyle = TableLayoutPanelCellBorderStyle.OutsetPartial;
int c = 5, r = dic.Count % c == 0 ? dic.Count / c : dic.Count / c + 1;
//动态添加行列
table.RowCount = r;
//设置行
for (int i = 0; i < r; i++)
{
table.RowStyles.Add(new RowStyle(SizeType.Percent, tSize2 / dataCount));
}
table.ColumnCount = c;
//设置列
for (int i = 0; i < c; i++)
{
table.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, tSize1 / dataCount));
}
//将创建的button控件添加至表格
table.Controls.AddRange(Creat_Button(dic, section, ref butList).ToArray());
return table;
}
#endregion
效果: