VS开发C#窗体实现串口通信功能RS232、RS485

先看效果图,字符串收发

  • COM3、4为虚拟串口
    在这里插入图片描述

程序源码

  • 新建C#窗体程序,布局如图:
    在这里插入图片描述
  • 程序源码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Com_zhx
{
    public partial class Form1 : Form
    {
        #region**参数设置**
        private static SerialPort sp = null;
        private static Boolean isSetProperty = false;
        private static String[] rates = { "2400", "4800", "9600", "19200", "38400", "43000", "56000", "57600", "115200"};
        private static String[] paritys = { "None", "奇校验", "偶校验" };
        private static String[] dataBits = { "5", "6", "7", "8" };
        private static String[] stopBits = { "0","1", "1.5","2" };
        #endregion
        #region**初始化**
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //加载所有
            //Com_zhx.Profile.SaveProfile();
            Com_zhx.Profile.LoadProfile();
            DTR.Enabled = false;
            RTS.Enabled = false;
            //加载可用串口,波特率,校验位,数据位,停止位
            SearchPort();
            Load_Rate();
            Load_Parity();
            Load_DataBits();
            Load_StopBits();
            Auto_SenT_Initialize();
        }
        #endregion

        #region**搜索串口按钮**
        private void Search_ComPort_Click(object sender, EventArgs e)
        {
            SearchPort();
        }
        #endregion
        #region**开关串口**
        private void Open_Port_Click(object sender, EventArgs e)
        {
            if (RS485.Checked)
            {
                Open_Port_485();
            }
            else
            {
                Open_Port_Simple();
            }
        }
        public void Open_Port_485()
        {
            if (Open_Port.Text == "打开串口")
            {
                //Console.WriteLine(CheckPortSetting());

                if (!CheckPortSetting())
                {
                    MessageBox.Show("串口未设置!", "错误提示");
                    return;
                }
                if (!isSetProperty)
                {
                    SetPortProperty();
                }
                try
                {
                    sp.Open();
                    // ColorTranslator.FromHtml("Red");
                    Open_Port.Text = "关闭串口";
                    Open_Port.BackColor = Color.GreenYellow;
                    //串口打开后相关设置不可用
                    Enable_Para(false);
                }
                catch (Exception)
                {
                    //打开串口失败,相应标志位取消
                    isSetProperty = false;
                    Open_Port.Text = "打开串口";
                    MessageBox.Show("串口无效或已被占用!", "错误提示");
                    return;
                }
            }
            else
            {
                try
                {
                    sp.Close();
                    isSetProperty = false;
                    Open_Port.Text = "打开串口";
                    Open_Port.BackColor = SystemColors.Control;
                    Enable_Para(true);
                }
                catch (Exception)
                {
                    MessageBox.Show("关闭串口时发生错误");
                }

            }
        }
        public void Open_Port_Simple()
        {
            if (Open_Port.Text == "打开串口")
            {
                //Console.WriteLine(CheckPortSetting());
                if (!CheckPortSetting())
                {
                    MessageBox.Show("串口未设置!", "错误提示");
                    return;
                }
                if (!isSetProperty)
                {
                    SetPortProperty();
                }
                try
                {
                    sp.Open();
                    Open_Port.Text = "关闭串口";
                    Open_Port.BackColor = Color.DarkSeaGreen;
                    //串口打开后相关设置不可用
                    Enable_Para(false);
                }
                catch (Exception)
                {
                    //打开串口失败,相应标志位取消
                    isSetProperty = false;
                    Open_Port.Text = "打开串口";
                    MessageBox.Show("串口无效或已被占用!", "错误提示");
                    return;
                }
            }
            else
            {
                try
                {
                    sp.Close();
                    isSetProperty = false;
                    Open_Port.Text = "打开串口";
                    Open_Port.BackColor = SystemColors.Control;
                    Enable_Para(true);
                }
                catch (Exception)
                {
                    MessageBox.Show("关闭串口时发生错误");
                }

            }
        }
        #endregion
        #region**启停RS485**
        private void RS485_CheckedChanged(object sender, EventArgs e)
        {
            if (RS485.Checked)
            {
                DTR.Checked = RTS.Checked = true;
            }
            else
            {
                DTR.Checked = RTS.Checked = false;
            }
        }
        #endregion
        #region**使能参数设置**
        public void Enable_Para(Boolean ifEnable)
        {
            Cbx_ComPort.Enabled = ifEnable;
            Cbx_BaudRate.Enabled = ifEnable;
            Cbx_DataBits.Enabled = ifEnable;
            Cbx_Parity.Enabled = ifEnable;
            Cbx_StopBits.Enabled = ifEnable;
            Hex_Rec.Enabled = ifEnable;
            RS485.Enabled = ifEnable;

        }
        #endregion


        #region**加载可用串口**
        //****************************加载可用串口****************************************************************
        public void SearchPort()
        {
            bool comExistence = false;//有可用串口标志位
            Cbx_ComPort.Items.Clear(); //清除当前串口号中的所有串口名称
            for (int i = 0; i < 20; i++)
            {
                try
                {
                    SerialPort sp = new SerialPort("COM" + (i + 1).ToString());
                    sp.Open();
                    sp.Close();
                    Cbx_ComPort.Items.Add("COM" + (i + 1).ToString());
                    comExistence = true;
                }
                catch (Exception)
                {
                    continue;
                }
            }
            if (comExistence)
            {
                Cbx_ComPort.SelectedIndex = 0;//使 comBox 显示第 1 个添加的索引
            }
            else
            {
                MessageBox.Show("没有找到可用串口!", "错误提示");
            }
        }
        #endregion
        #region**加载波特率**
        public void Load_Rate()
        {
            foreach(String rate in rates)
            {
                Cbx_BaudRate.Items.Add(rate);
            }
            // 预置波特率
            switch (Profile.G_BAUDRATE)
            {
                case "2400":
                    Cbx_BaudRate.SelectedIndex = 0;
                    break;
                case "4800":
                    Cbx_BaudRate.SelectedIndex = 1;
                    break;
                case "9600":
                    Cbx_BaudRate.SelectedIndex = 2;
                    break;
                case "19200":
                    Cbx_BaudRate.SelectedIndex = 3;
                    break;
                case "38400":
                    Cbx_BaudRate.SelectedIndex = 4;
                    break;
                case "43000":
                    Cbx_BaudRate.SelectedIndex = 5;
                    break;
                case "56000":
                    Cbx_BaudRate.SelectedIndex = 6;
                    break;
                case "57600":
                    Cbx_BaudRate.SelectedIndex = 7;
                    break;
                case "115200":
                    Cbx_BaudRate.SelectedIndex = 8;
                    break;
                default:
                    {
                        MessageBox.Show("波特率预置参数错误。");
                        return;
                    }
            }
        }
        #endregion
        #region**加载校验位**
        public void Load_Parity()
        {
            foreach(String parity in paritys)
            {
                Cbx_Parity.Items.Add(parity);
            }
            switch (Profile.G_PARITY)
            {
                case "None":
                    Cbx_Parity.SelectedIndex = 0;
                    break;
                case "ODD":
                    Cbx_Parity.SelectedIndex = 1;
                    break;
                case "EVEN":
                    Cbx_Parity.SelectedIndex = 2;
                    break;
                default:
                    {
                        MessageBox.Show("停止位预置参数错误。");
                        return;
                    }
            }
        }
        #endregion
        #region**加载数据位**
        public void Load_DataBits()
        {
            foreach(String dataBit in dataBits)
            {
                Cbx_DataBits.Items.Add(dataBit);
            }
            switch (Profile.G_DATABITS)
            {
                case "5":
                    Cbx_DataBits.SelectedIndex = 0;
                    break;
                case "6":
                    Cbx_DataBits.SelectedIndex = 1;
                    break;
                case "7":
                    Cbx_DataBits.SelectedIndex = 2;
                    break;
                case "8":
                    Cbx_DataBits.SelectedIndex = 3;
                    break;
                default:
                    {
                        MessageBox.Show("数据位预置参数错误。");
                        return;
                    }
            }
        }
        #endregion
        #region**加载停止位**
        public void Load_StopBits()
        {
            foreach(String stopbit in stopBits)
            {
                Cbx_StopBits.Items.Add(stopbit);
            }
            switch (Profile.G_STOP)
            {
                case "0":
                    Cbx_StopBits.SelectedIndex = 0;
                    break;
                case "1":
                    Cbx_StopBits.SelectedIndex = 1;
                    break;
                case "1.5":
                    Cbx_StopBits.SelectedIndex = 2;
                    break;
                case "2":
                    Cbx_StopBits.SelectedIndex = 3;
                    break;
                default:
                    {
                        MessageBox.Show("停止位预置参数错误。");
                        return;
                    }
            }
        }

        #endregion
        #region**参数设置检查**
        private bool CheckPortSetting()
        {   /*
            Console.WriteLine(CbxCOMPort.Text.Trim());
            Console.WriteLine(CbxBaudRate.Text.Trim());
            Console.WriteLine(CbxDataBits.Text.Trim());
            Console.WriteLine(CbxParity.Text.Trim());
            Console.WriteLine(CbxStopBits.Text.Trim());
            */
            if (Cbx_ComPort.Text.Trim() == "") return false;
            if (Cbx_BaudRate.Text.Trim() == "") return false;
            if (Cbx_DataBits.Text.Trim() == "") return false;
            if (Cbx_Parity.Text.Trim() == "") return false;
            if (Cbx_StopBits.Text.Trim() == "") return false;
            return true;
        }
        #endregion
        #region**设置串口**
        private void SetPortProperty()//设置串口
        {
            sp = new SerialPort();
            //串口号
            sp.PortName = Cbx_ComPort.Text.Trim();
            //波特率
            sp.BaudRate = Convert.ToInt32(Cbx_BaudRate.Text.Trim());
            //停止位
            float f = Convert.ToSingle(Cbx_StopBits.Text.Trim());
            if (f == 0)
            {
                sp.StopBits = StopBits.None;
            }
            else if (f == 1.5)
            {
                sp.StopBits = StopBits.OnePointFive;
            }
            else if (f == 1)
            {
                sp.StopBits = StopBits.One;
            }
            else if (f == 2)
            {
                sp.StopBits = StopBits.Two;
            }
            //数据位
            sp.DataBits = Convert.ToInt16(Cbx_DataBits.Text.Trim());
            //校验位
            string s = Cbx_Parity.Text.Trim();
            if (s.CompareTo("None") == 0)
            {
                sp.Parity = Parity.None;
            }
            else if (s.CompareTo("奇校验") == 0)
            {
                sp.Parity = Parity.Odd;
            }
            if (s.CompareTo("偶校验") == 0)
            {
                sp.Parity = Parity.Even;
            }
            else
            {
                sp.Parity = Parity.None;
            }

            //****************设置DTR、RTS有效******************
            if (RS485.Checked)
            {
                sp.DtrEnable = true;
                sp.RtsEnable = true;
            }
            else
            {
                sp.DtrEnable = false;
                sp.RtsEnable = false;
            }
            //超时读取
            sp.ReadTimeout = -1;
            sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
            //串口配置完成
            isSetProperty = true;
        }
        #endregion

        #region**定时发送**
        private void Auto_Sen_CheckedChanged(object sender, EventArgs e)
        {
            if (Auto_Sen.Checked)
            {
                //设置Timer控件可用
                this.timer1.Enabled = true;
                //设置时间间隔(毫秒为单位)
                try
                {
                    this.timer1.Interval = int.Parse(Auto_SenT.Text);
                }
                catch (Exception)
                {
                    this.timer1.Interval = 1000;
                }
                
                
            }
            else
            {
                //设置Timer控件可用
                this.timer1.Enabled = false;
            }
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            Send.PerformClick();
        }
        #endregion
        #region**发送数据**
        private void Send_Click(object sender, EventArgs e)
        {
            if (Open_Port.Text == "关闭串口")//写串口数据
            {
                if (TextBox_Sen.Text == "" || TextBox_Sen.Text == null)//检测要发送的数据
                {
                    MessageBox.Show("请输入要发送的数据!", "错误提示");
                    Auto_Sen.Checked = false;
                    return;
                }
                else
                {
                    if (RS485.Checked)
                    {
                        Send_485();
                    }
                    else
                    {
                        Send_Simple();
                    }
                }
            }
            else
            {
                MessageBox.Show("串口未打开!", "错误提示");
                Auto_Sen.Checked = false;
                return;
            }
        }
        public void Send_485()
        {
            byte[] sendbuf = new byte[TextBox_Sen.Text.Length / 2]; ;//tbxSendData.Text.ToCharArray();
            for (int i = 0; i < sendbuf.Length; i++)
            {
                try
                {
                    // 每两个字符是一个 byte。 
                    sendbuf[i] = byte.Parse(TextBox_Sen.Text.Substring(i * 2, 2),
                    System.Globalization.NumberStyles.HexNumber);
                }
                catch
                {
                    // Rethrow an exception with custom message. 
                    throw new ArgumentException("hex is not a valid hex number!", "hex");
                }
            }

            //Console.WriteLine(TbxSendData.Text.Length);
            //Console.WriteLine(sendbuf.Length);
            /*for(int j=0;j< sendbuf.Length; j++)
            {
                Console.WriteLine(sendbuf[j]);
            }
            */
            SendModbusData(ref sendbuf);
        }
        public void Send_Simple()
        {
            try
            {
                sp.WriteLine(TextBox_Sen.Text);
            }
            catch (Exception)
            {
                MessageBox.Show("发送数据时发生错误!", "错误提示");
                return;
            }
        }




        #endregion
        #region**接收数据**
        public void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {

            System.Threading.Thread.Sleep(100);//延时100ms完全接收数据
            //this.Invoke跨线程访问,辅助线程访问主线程控件
            this.Invoke((EventHandler)(delegate
            {
                if (RS485.Checked)
                {
                    DataReceived_485();
                }
                else
                {
                    DataReceived_Simple();
                }
            }));
        }

        public void DataReceived_485()
        {
            //Console.WriteLine("kkk");
            DateTime dt = DateTime.Now;
            if (sp.IsOpen)
            {
                try
                {
                    //string str = readBuffer.ToString();
                    int count = sp.BytesToRead;//读取缓冲区数据字节(8位)数
                    if (count > 0)
                    {
                        Byte[] readBuffer = new Byte[sp.BytesToRead];//创建接收字节数组
                        sp.Read(readBuffer, 0, readBuffer.Length);//读取接收的数据
                        String RecvDataText = null;
                        String RescDataCRC = null;
                        
                        TextBox_Rec.Text += dt.GetDateTimeFormats('f')[0].ToString() + "\r\n";
                        //GetResponse(ref readBuffer);//readBuffer[0]一个字节                   
                        // CRC 验证
                        if (CheckResponse(readBuffer))
                        {
                            //显示输入数据
                            for (int i = 0; i < readBuffer.Length; i++)
                            {
                                RecvDataText += ("0x" + readBuffer[i].ToString("X2") + " ");
                                
                                //RecvDataText += (ReceivedData[i].ToString("X2") + " ");
                            }
                            byte[] CRC = new byte[2];
                            GetCRC(readBuffer, ref CRC);
                            //未进行CRC校验
                            for (int j = 0; j < 2; j++)
                            {
                                RescDataCRC += ("0x" + CRC[j].ToString("X2") + " ");
                            }
                            TextBox_Rec.Text += RecvDataText + "\r\n";
                            sp.DiscardInBuffer();//清除串行驱动程序的接收缓冲区的数据;  
                        }
                        else
                        {
                            //modbusStatus = "CRC校验 error";
                            sp.DiscardInBuffer();
                        }
                    }
                    else
                    {
                        //**************************************************************************************************
                        TextBox_Rec.Text += "读取缓冲区数据失败,请重启系统" + "\r\n";
                    }
                }
                catch (Exception)
                {
                    sp.DiscardInBuffer();//读取缓冲区数据字节(8位)数   失败                           
                }


            }
            else
            {
                // modbusStatus = "Serial port not open";                    
            }
            //Console.WriteLine(weightdate);
        }
        public void DataReceived_Simple()
        {
            DateTime dt = DateTime.Now;
            if (!Hex_Rec.Checked)
            {
               TextBox_Rec.Text += dt.GetDateTimeFormats('f')[0].ToString() + "\r\n";
                //TextBox_Rec.Text += sp.Read() + "\r\n";
                /*
                 * sp.ReadLine()是线程阻塞的,机器向串口发送数据然后 串口有数据接收时,sp.ReadLine()才会继续向下执行。
                 * 因为下位机没有发回车换行来,默认是\n结束,相当于执行ReadTo('\n')因为下位机没发\n,所以一直卡在这里等待。
                */
                //TextBox_Rec.Text += sp.ReadLine() + "\r\n";
                try{
                    Byte[] receivedData = new Byte[sp.BytesToRead];        //创建接收字节数组
                    sp.Read(receivedData, 0, receivedData.Length);         //读取数据
                    TextBox_Rec.Text += new UTF8Encoding().GetString(receivedData) + "\r\n";//用万能的UTF8可以传输中文不会乱码
                }catch (System.Exception ex){
                    MessageBox.Show(ex.Message, ":出错提示!!!!!");
                }
            }
            else
            {
                int i_InNum;//输入缓冲区中字节数
                i_InNum = sp.BytesToRead;

                Byte[] ReceivedData = new Byte[sp.BytesToRead];//创建接收字节数组
                sp.Read(ReceivedData, 0, ReceivedData.Length);//读取接收的数据
                String RecvDataText = null;

                for (int i = 0; i < ReceivedData.Length; i++)
                {
                    RecvDataText += ("0x" + ReceivedData[i].ToString("X2") + " ");
                }
                TextBox_Rec.Text += dt.GetDateTimeFormats('f')[0].ToString() + "\r\n";
                TextBox_Rec.Text += RecvDataText + "\r\n";
            }
            //丢弃接收缓冲区数据
            sp.DiscardInBuffer();
        }

        #endregion
        #region**Check Response**
        private bool CheckResponse(byte[] response)
        {
            //Perform a basic CRC check:
            byte[] CRC = new byte[2];
            GetCRC(response, ref CRC);
            if (CRC[0] == response[response.Length - 2] && CRC[1] == response[response.Length - 1])
                return true;
            else
                return false;
        }
        #endregion
        #region**Get Response**
        private void GetResponse(ref byte[] response)
        {
            //There is a bug in .Net 2.0 DataReceived Event that prevents people from using this
            //event as an interrupt to handle data (it doesn't fire all of the time).  Therefore
            //we have to use the ReadByte command for a fixed length as it's been shown to be reliable.
            for (int i = 0; i < response.Length; i++)
            {
                response[i] = (byte)(sp.ReadByte());//从输入缓冲区同步读取一个字节
            }
            return;
        }
        #endregion
        #region**CRC Computation**
        public void GetCRC(byte[] message, ref byte[] CRC)
        {
            //Function expects a modbus message of any length as well as a 2 byte CRC array in which to 
            //return the CRC values:

            ushort CRCFull = 0xFFFF;
            byte CRCHigh = 0xFF, CRCLow = 0xFF;
            char CRCLSB;

            for (int i = 0; i < (message.Length) - 2; i++)
            {
                CRCFull = (ushort)(CRCFull ^ message[i]);

                for (int j = 0; j < 8; j++)
                {
                    CRCLSB = (char)(CRCFull & 0x0001);
                    CRCFull = (ushort)((CRCFull >> 1) & 0x7FFF);

                    if (CRCLSB == 1)
                        CRCFull = (ushort)(CRCFull ^ 0xA001);
                }
            }
            CRC[1] = CRCHigh = (byte)((CRCFull >> 8) & 0xFF);
            CRC[0] = CRCLow = (byte)(CRCFull & 0xFF);
        }
        #endregion
        #region**SendModbusData 打包发送数据**
        public bool SendModbusData(ref byte[] values)
        {
            //Ensure port is open:
            if (sp.IsOpen)
            {
                //Clear in/out buffers:
                sp.DiscardOutBuffer();//清空发送、接收缓冲区字节
                sp.DiscardInBuffer();
                //Function 3 response buffer:
                byte[] response = new byte[values.Length + 2];
                Array.Copy(values, response, values.Length);
                //BuildMessage(address, (byte)3, start, registers, ref message);
                //打包带有 CRC 验证的modbus 数据包:
                byte[] CRC = new byte[2];
                GetCRC(response, ref CRC);
                //Console.WriteLine(CRC[0]);
                //Console.WriteLine(CRC[1]);
                response[0] = Convert.ToByte(response[0]);//地址
                response[1] = Convert.ToByte(response[1]);//功能
                //values[2] = (byte)(Convert.ToByte(values[2])>>8);//寄存器地址
                response[2] = Convert.ToByte(response[2]);
                response[3] = Convert.ToByte(response[3]);
                //values[2] = (byte)(Convert.ToByte(values[]) >> 8);//寄存器个数
                response[4] = Convert.ToByte(response[4]);
                response[5] = Convert.ToByte(response[5]);

                response[response.Length - 2] = CRC[0];
                response[response.Length - 1] = CRC[1];
                values = response; //返回带有 CRC 验证的modbus 数据包
                /*
                Console.WriteLine(values.Length); 
                for (int i=0;i<values.Length;i++){
                     Console.WriteLine(values[i]);//控制台输出打包后的Modbus数据
                }
                */
                //Send modbus message to Serial Port:
                try
                {
                    sp.Write(values, 0, values.Length);

                    //GetResponse(ref response);
                    return true;
                }
                catch (Exception)
                {
                    return false;
                }
                //Evaluate message:
                //if (CheckResponse(response))
                //{
                //    //Return requested register values:
                //    for (int i = 0; i < (response.Length - 5) / 2; i++)
                //    {
                //        values[i] = response[2 * i + 3];
                //        values[i] <<= 8;
                //        values[i] += response[2 * i + 4];
                //    }
                //    modbusStatus = "Read successful";
                //    return true;
                //}
                //else
                //{
                //    modbusStatus = "CRC error";
                //    return false;
                //}
            }
            else
            {
                MessageBox.Show("串口未打开!");
                return false;
            }

        }
        #endregion

        #region**保存配置**
        private void Save_Cfg_Click(object sender, EventArgs e)
        {
            Profile.G_BAUDRATE = Cbx_BaudRate.Text;
            Profile.G_DATABITS = Cbx_DataBits.Text;
            Profile.G_STOP = Cbx_StopBits.Text;
            Profile.G_PARITY = Cbx_Parity.Text;
            Com_zhx.Profile.SaveProfile();
        }
        #endregion
        #region**周期样式**
        private void Auto_SenT_Enter(object sender, EventArgs e)
        {
            Auto_SenT.Text = "";
            Auto_SenT.ForeColor = Color.Black;
        }
        private void Auto_SenT_Leave(object sender, EventArgs e)
        {
            try
            {
                int b = int.Parse(Auto_SenT.Text);
            }
            catch (Exception)
            {
                Auto_SenT_Initialize();
            }
        }
        public void Auto_SenT_Initialize()
        {
            Auto_SenT.Text = "周期:1000ms";
            Auto_SenT.ForeColor = Color.LightGray;
        }
        #endregion
        #region**延时**
        public bool Wait(int ms)
        {
            DateTime t = DateTime.Now;
            for (int i = 0; i < ms; i++)
            {
                TimeSpan ts = DateTime.Now - t;
                if (ts.TotalSeconds >= ms)
                {
                    Console.WriteLine(ts.TotalMilliseconds);
                    i = ms + 2;
                }
                i--;
            }
            return true;
        }







        #endregion
        #region**清空接收发送区**
        private void Clear_Sen_Click(object sender, EventArgs e)
        {
            TextBox_Sen.Text = "";
        }

        private void Clear_Recive_Click(object sender, EventArgs e)
        {
            TextBox_Rec.Text = "";
        }
        #endregion
        #region**自动清空接收区**
        private void AutoClear_CheckedChanged(object sender, EventArgs e)
        {
            if (AutoClear.Checked)
            {
                //设置Timer控件可用
                this.timer2.Enabled = true;
                //设置时间间隔(毫秒为单位)
                this.timer2.Interval = 3000;
            }
            else
            {
                this.timer2.Enabled = false;
            }
        }
        private void timer2_Tick(object sender, EventArgs e)
        {
            this.Invoke(new EventHandler(delegate {
                TextBox_Rec.Text = "";
            }));
        }
        #endregion

    }
}

  • 添加类用于保存配置文件:IniFiles.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace Com_zhx
{
    public abstract class CustomIniFile
    {
        public CustomIniFile(string AFileName)
        {
            FFileName = AFileName;
        }
        private string FFileName;
        public string FileName
        {
            get { return FFileName; }
        }
        public virtual bool SectionExists(string Section)
        {
            List<string> vStrings = new List<string>();
            ReadSections(vStrings);
            return vStrings.Contains(Section);
        }
        public virtual bool ValueExists(string Section, string Ident)
        {
            List<string> vStrings = new List<string>();
            ReadSection(Section, vStrings);
            return vStrings.Contains(Ident);
        }
        public abstract string ReadString(string Section, string Ident, string Default);
        public abstract bool WriteString(string Section, string Ident, string Value);
        public abstract bool ReadSectionValues(string Section, List<string> Strings);
        public abstract bool ReadSection(string Section, List<string> Strings);
        public abstract bool ReadSections(List<string> Strings);
        public abstract bool EraseSection(string Section);
        public abstract bool DeleteKey(string Section, string Ident);
        public abstract bool UpdateFile();
    }
    /// <summary>
    /// 存储本地INI文件的类。
    /// </summary>
    public class IniFile : CustomIniFile
    {
        [DllImport("kernel32")]
        private static extern uint GetPrivateProfileString(
            string lpAppName,    // points to section name 
            string lpKeyName,    // points to key name 
            string lpDefault,    // points to default string 
            byte[] lpReturnedString,    // points to destination buffer 
            uint nSize,    // size of destination buffer 
            string lpFileName     // points to initialization filename 
        );

        [DllImport("kernel32")]
        private static extern bool WritePrivateProfileString(
            string lpAppName,    // pointer to section name 
            string lpKeyName,    // pointer to key name 
            string lpString,    // pointer to string to add 
            string lpFileName     // pointer to initialization filename 
        );

        /// <summary>
        /// 构造IniFile实例。
        /// <param name="AFileName">指定文件名</param>
        /// </summary>
        public IniFile(string AFileName)
            : base(AFileName)
        {

        }

        /// <summary>
        /// 析够IniFile实例。
        /// </summary>
        ~IniFile()
        {
            UpdateFile();
        }

        /// <summary>
        /// 读取字符串值。
        /// <param name="Ident">指定变量标识。</param>
        /// <param name="Section">指定所在区域。</param>
        /// <param name="Default">指定默认值。</param>
        /// <returns>返回读取的字符串。如果读取失败则返回该值。</returns>
        /// </summary>
        public override string ReadString(string Section, string Ident, string Default)
        {
            byte[] vBuffer = new byte[2048];
            uint vCount = GetPrivateProfileString(Section,
                Ident, Default, vBuffer, (uint)vBuffer.Length, FileName);
            return Encoding.Default.GetString(vBuffer, 0, (int)vCount);
        }
        /// <summary>
        /// 写入字符串值。
        /// </summary>
        /// <param name="Section">指定所在区域。</param>
        /// <param name="Ident">指定变量标识。</param>
        /// <param name="Value">所要写入的变量值。</param>
        /// <returns>返回写入是否成功。</returns>
        public override bool WriteString(string Section, string Ident, string Value)
        {
            return WritePrivateProfileString(Section, Ident, Value, FileName);
        }

        /// <summary>
        /// 获得区域的完整文本。(变量名=值格式)。
        /// </summary>
        /// <param name="Section">指定区域标识。</param>
        /// <param name="Strings">输出处理结果。</param>
        /// <returns>返回读取是否成功。</returns>
        public override bool ReadSectionValues(string Section, List<string> Strings)
        {
            List<string> vIdentList = new List<string>();
            if (!ReadSection(Section, vIdentList)) return false;
            foreach (string vIdent in vIdentList)
                Strings.Add(string.Format("{0}={1}", vIdent, ReadString(Section, vIdent, "")));
            return true;
        }

        /// <summary>
        /// 读取区域变量名列表。
        /// </summary>
        /// <param name="Section">指定区域名。</param>
        /// <param name="Strings">指定输出列表。</param>
        /// <returns>返回获取是否成功。</returns>
        public override bool ReadSection(string Section, List<string> Strings)
        {
            byte[] vBuffer = new byte[16384];
            uint vLength = GetPrivateProfileString(Section, null, null, vBuffer,
                (uint)vBuffer.Length, FileName);
            int j = 0;
            for (int i = 0; i < vLength; i++)
                if (vBuffer[i] == 0)
                {
                    Strings.Add(Encoding.Default.GetString(vBuffer, j, i - j));
                    j = i + 1;
                }
            return true;
        }

        /// <summary>
        /// 读取区域名列表。
        /// </summary>
        /// <param name="Strings">指定输出列表。</param>
        /// <returns></returns>
        public override bool ReadSections(List<string> Strings)
        {
            byte[] vBuffer = new byte[16384];
            uint vLength = GetPrivateProfileString(null, null, null, vBuffer,
                (uint)vBuffer.Length, FileName);
            int j = 0;
            for (int i = 0; i < vLength; i++)
                if (vBuffer[i] == 0)
                {
                    Strings.Add(Encoding.Default.GetString(vBuffer, j, i - j));
                    j = i + 1;
                }
            return true;
        }

        /// <summary>
        /// 删除指定区域。
        /// </summary>
        /// <param name="Section">指定区域名。</param>
        /// <returns>返回删除是否成功。</returns>
        public override bool EraseSection(string Section)
        {
            return WritePrivateProfileString(Section, null, null, FileName);
        }

        /// <summary>
        /// 删除指定变量。
        /// </summary>
        /// <param name="Section">变量所在区域。</param>
        /// <param name="Ident">变量标识。</param>
        /// <returns>返回删除是否成功。</returns>
        public override bool DeleteKey(string Section, string Ident)
        {
            return WritePrivateProfileString(Section, Ident, null, FileName);
        }

        /// <summary>
        /// 更新文件。
        /// </summary>
        /// <returns>返回更新是否成功。</returns>
        public override bool UpdateFile()
        {
            return WritePrivateProfileString(null, null, null, FileName);
        }
    }
}

  • 添加类用于保存配置文件:Profile.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Com_zhx
{
    class Profile
    {
        public static void LoadProfile()
        {
            string strPath = AppDomain.CurrentDomain.BaseDirectory;
            _file = new IniFile(strPath + "zhx_Cfg.ini");
            G_BAUDRATE = _file.ReadString("CONFIG", "BaudRate", "9600");    //读数据,下同
            G_DATABITS = _file.ReadString("CONFIG", "DataBits", "8");
            G_STOP = _file.ReadString("CONFIG", "StopBits", "1");
            G_PARITY = _file.ReadString("CONFIG", "Parity", "None");
            if(G_BAUDRATE==""|| G_BAUDRATE == null)
            {
                G_BAUDRATE = "9600";
            }
            if(G_DATABITS==""|| G_DATABITS == null)
            {
                G_DATABITS = "8";
            }
            if(G_STOP==""|| G_STOP == null)
            {
                G_STOP = "1";
            }
            if(G_PARITY==""|| G_PARITY == null)
            {
                G_PARITY = "None";
            }
        }

        public static void SaveProfile()
        {
            string strPath = AppDomain.CurrentDomain.BaseDirectory;
            _file = new IniFile(strPath + "zhx_Cfg.ini");
            _file.WriteString("CONFIG", "BaudRate", G_BAUDRATE);            //写数据,下同
            _file.WriteString("CONFIG", "DataBits", G_DATABITS);
            _file.WriteString("CONFIG", "StopBits", G_STOP);
            _file.WriteString("CONFIG", "G_PARITY", G_PARITY);
        }

        private static IniFile _file;//内置了一个对象

        public static string G_BAUDRATE = "9600";//给ini文件赋新值,并且影响界面下拉框的显示
        public static string G_DATABITS = "8";
        public static string G_STOP = "1";
        public static string G_PARITY = "None";
    }
}

结束

  • 51
    点赞
  • 337
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 31
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 31
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猪悟道

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值