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";
    }
}

結束

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章