基于c#的工控软件版本v1.01_11.25

最近打算用c#做点实事,原来一直都在用串口调试,打算开发一种结合securt的串口保存机制及传统调试助手的便携串口配置模式的软件。今天发出第一个版本,这段时间慢慢积累打算把这个软件网上起来。

今天解决了串口关闭问题,及串口接收16进制显示的问题。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.IO.Ports;
using System.Threading;


namespace ComAssistant1
{
    public partial class Form1 : Form
    {
        public enum LogMsgType { Incoming, Outgoing, Normal, Warning, Error };
        public enum DataMode { Text, Hex }
        private Color[] LogMsgTypeColor = { Color.Orange, Color.Green, Color.Black, Color.Blue, Color.Red };
        /// 准备关闭串口=true
        /// </summary>
        private bool m_IsTryToClosePort = false;
        /// <summary>
        /// true表示正在接收数据
        /// </summary>
        private bool m_IsReceiving = false;
       
        public Form1()
        {
            InitializeComponent();


        }
        Mutex m_Mutex = null;//锁
        bool flag;
        private void Form1_Load(object sender, EventArgs e)
        {
            //判断串口打开或关闭
            if (serialPort1.IsOpen)
            {
                serialPort1.Close();
                pictureBox1.Image = Image.FromFile("E:\\C#\\图标\\PNG\\20091007130906335.png");
            }
            else
            {
                pictureBox1.Image = Image.FromFile("E:\\C#\\图标\\PNG\\20091007130902885.png");
            }
            RefrespictureBox1();


            int ii = 0;
            foreach (string s in SerialPort.GetPortNames())
            {
                if (ii >= 1)
                {
                    comboBox1.Items.Add(s);
                }
                ii++;
            }


            if (SerialPort.GetPortNames().Length != 0)
            {
                comboBox1.Text = (string)comboBox1.Items[0];
            }


            string[] ss = new string[] { "9600", "19200", "57600", "115200" };
            comboBox2.DataSource = ss;


            comboBox3.DataSource = Enum.GetNames(typeof(Parity));


            ss = new string[] { "5", "6", "7", "8" };
            comboBox4.DataSource = ss;
            comboBox4.Text = "8";


            comboBox5.DataSource = Enum.GetNames(typeof(StopBits));
            comboBox5.Text = Enum.Format(typeof(StopBits), StopBits.One, "G");


            m_Mutex = new Mutex();
            flag = false;
        }
        private void getData(string msg)
        {
            rtfTerminal.Invoke(new EventHandler(delegate
            {
                rtfTerminal.AppendText(msg);
                //滚动到控件光标处 
                this.rtfTerminal.ScrollToCaret();
            }));
        }


        private void getByteData(byte[] bb)
        {
            txtSend.Invoke(new EventHandler(delegate
            {
                string s = "";
                for (int i = 0; i < bb.Length; i++)
                {
                    s += bb[i].ToString() + " ";
                }
                //txtSend.Items.Add(s);
            }));
        }        
        //串口发送方式


        #region Local Properties


        private DataMode CurrentDataMode
        {
            get
            {
                if (tbHex.Checked)
                    return DataMode.Hex;
                else 
                    return DataMode.Text;


            }


            set
            {


                if (value == DataMode.Text) 
                    rbText.Checked = true;
                else 
                    tbHex.Checked = true;


            }


        }


        #endregion
        private void rbHex_CheckedChanged(object sender, EventArgs e)
        {
            if (rbHex.Checked) 
                CurrentDataMode = DataMode.Hex;
            else
                CurrentDataMode = DataMode.Text;
        }


        private void rbText_CheckedChanged(object sender, EventArgs e)
        {
            if (rbText.Checked) CurrentDataMode = DataMode.Text;
        }


        private void Log(LogMsgType msgtype, string msg)
        {
            /*
             * txt文件的换行是\r\n.
               textbox里的换行只有\n吧*/
            rtfTerminal.Invoke(new EventHandler(delegate
            {
                rtfTerminal.SelectedText = string.Empty;
                rtfTerminal.SelectionFont = new Font(rtfTerminal.SelectionFont, FontStyle.Bold);
                rtfTerminal.SelectionColor = LogMsgTypeColor[(int)msgtype];
                msg = msg.Replace("\n", "\r\n");
                rtfTerminal.AppendText(msg);
                rtfTerminal.ScrollToCaret();
            }));


        }
        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            if (m_IsTryToClosePort) // 关键!!!
            {
                return;
            }
            m_IsReceiving = true; // 关键!!!
            if (flag == true)
            {
                return;
            }
            m_Mutex.WaitOne();//这个地方加一个互斥
#if true
            try
            {
               // byte[] data = Convert.FromBase64String(serialPort1.ReadLine()); 
              //  string str = Encoding.Unicode.GetString(data); 
                  // 判断用户用的是字节模式还是字符模式
                if (CurrentDataMode == DataMode.Hex)
                {
                    // 读取缓冲区的数据
                 //   string data = serialPort1.ReadExisting();
                    // 显示读取的数据到数据窗口
                 //   Log(LogMsgType.Incoming, data/* + "\n"*/);
#if true
                    System.Threading.Thread.Sleep(300);
                    // 获取字节长度
                    int bytes = serialPort1.BytesToRead;
                    // 创建字节数组
                    byte[] readBuffer = new byte[bytes];
                    // 读取缓冲区的数据到数组
                    serialPort1.Read(readBuffer, 0, bytes);
                    this.getData(MyClass.ByteArrayToHexString(readBuffer));
#endif
                }
               else
                {
                  byte[] readBuffer = new byte[serialPort1.ReadBufferSize];
                  serialPort1.Read(readBuffer, 0, readBuffer.Length);
#if true
                  Log(LogMsgType.Incoming, Encoding.ASCII.GetString(readBuffer) + "\r\n");
                    /* ByteArrayToHexString(readBuffer) + "\n"/*/
#endif
#if false
                this.rtfTerminal.Invoke(
                    //在拥有此控件的基础窗口句柄的线程上执行委托Invoke(Delegate)  
                    //即在textBox_ReceiveDate控件的父窗口form中执行委托.  
                 new MethodInvoker(
                    /*表示一个委托,该委托可执行托管代码中声明为 void 且不接受任何参数的任何方法。
                     * 在对控件的 Invoke    方法进行调用时或需要一个简单委托又不想自己定义时可以使用该委托。*/
                 delegate
                 {
                     /*匿名方法,C#2.0的新功能,这是一种允许程序员将一段完整代码区块当成参数传递的程序代码编写技术,
                      * 通过此种方法可  以直接使用委托来设计事件响应程序以下就是你要在主线程上实现的功能但是有一点要注意,
                      * 这里不适宜处理过多的方法,因为C#消息机制是消息流水线响应机制,
                      * 如果这里在主线程上处理语句的时间过长会导致主UI线程阻塞,
                      * 停止响应或响应不顺畅,这时你的主form界面会延迟或卡死      */
                      this.rtfTerminal.Text += Encoding.ASCII.GetString(readBuffer); ;
                      this.rtfTerminal.Focus();
                      //设置光标的位置到文本尾 
                      this.rtfTerminal.Select(this.rtfTerminal.TextLength, 0);
                      //滚动到控件光标处 
                      this.rtfTerminal.ScrollToCaret();
                 }


                 )
                 );
#endif
                }
            }
            catch (Exception)
            { 
                MessageBox.Show(this, e.ToString(), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); 
            }
            finally // 放在finally里面比较好。
            {
                m_IsReceiving = false; // 关键!!!
            }
            m_Mutex.ReleaseMutex();
#else
            int SDateTemp = this.serialPort1.ReadByte();//读取串口中一个字节的数据
            this.rtfTerminal.Invoke(     //在拥有此控件的基础窗口句柄的线程上执行委托Invoke(Delegate)


                                                   //即在textBox_ReceiveDate控件的父窗口form中执行委托.


            new MethodInvoker( //表示一个委托,该委托可执行托管代码中声明为 void 且不接


                                                  //受任何参数的任何方法。在对控件的 Invoke 方法进行调用时


                                                  //或需要一个简单委托又不想自己定义时可以使用该委托。


            delegate
            {   //匿名方法,C#2.0的新功能,这是一种允许程序员将一段完整


                //代码区块当成参数传递的程序代码编写技术,通过此种方法可以直接使用委托来设计事件响应程序


                //以下就是你要在主线程上实现的功能,但是有一点要注意,这里不适宜处理过多的方法,因为C#消息机


                //制是消息流水线响应机制,如果这里在主线程上处理语句的时间过长会导致主UI线程阻塞,停止响应或响


                //应不顺畅,这时你的主form界面会延迟或卡死
                this.rtfTerminal.AppendText((Convert.ToChar(SDateTemp).ToString()));//输出到主窗口
                //     文本控件
                this.rtfTerminal.Text += "";
            }


                                        )


                                                    );
#endif


        }
        public void RefrespictureBox1()
        {
            if (serialPort1.IsOpen)
            {
                button1.BackColor = SystemColors.GradientActiveCaption;
                button1.Text = "断开";
            }
            else
            {
                button1.BackColor = SystemColors.Control;
                button1.Text = "连接";
            }
        }
        /// <summary>
        /// 结束工作
        /// </summary>
        public void DisconnectDeveice() // 关键和核心!!!
        {
            m_IsTryToClosePort = true;
            while (m_IsReceiving)
            {
                System.Windows.Forms.Application.DoEvents();
            }
            serialPort1.Close();
            m_IsTryToClosePort = false;


        }
        private void button1_Click(object sender, EventArgs e)
        {


           
            try
            {
                if (serialPort1.IsOpen)
                {
               //     m_Mutex.WaitOne();
                    {
                        this.serialPort1.DataReceived -= this.serialPort1_DataReceived;//先关掉对应的事件
                    }
                    DisconnectDeveice();
             //       flag = true;
               //     m_Mutex.ReleaseMutex();
                    pictureBox1.Image = Image.FromFile("E:\\C#\\图标\\PNG\\20091007130902885.png");


                }
                else
                {
                    this.serialPort1.DataReceived += this.serialPort1_DataReceived;
                    serialPort1.PortName = comboBox1.Text;
                    serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);
                    //  serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), comboBox3.Text);
                    // serialPort1.DataBits = Int32.Parse(comboBox4.Text);
                    // serialPort1.StopBits = (StopBits)Enum.Parse(typeof(StopBits), comboBox5.Text);
                    //   serialPort1.Encoding = Encoding.GetEncoding("Gb2312");
                    serialPort1.Open();
                    pictureBox1.Image = Image.FromFile("E:\\C#\\图标\\PNG\\20091007130906335.png");
                //    this.flag = false;
                }
                RefrespictureBox1();
            }
            catch (Exception)
            {
                MessageBox.Show(this, e.ToString(), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); 


            }
        }


        private void checkEdit1_CheckedChanged(object sender, EventArgs e)
        {


        }


        private void button2_Click(object sender, EventArgs e)
        {
          //  serialPort1.WriteLine(txtSend.Text);
            try
            {
                string s = "";
                if (rbHex.Checked)
                {
                    ArrayList al = MyClass.Str16ToArrayList(txtSend.Text);
                    byte[] by = new byte[al.Count];
                    int i = 0;
                    foreach (string stmp in al)
                    {
                        by[i] += Convert.ToByte(stmp, 16);
                        i++;
                    }
                    s = Encoding.GetEncoding("Gb2312").GetString(by);
                    //    Log(LogMsgType.Incoming, s); 
                }
                else
                {
                    s = txtSend.Text;
                }
                if (AutoSend.Checked)
                {
                    for (int i = 0; i < 5; i++)
                    {
                        System.Threading.Thread.Sleep(5000);
                        serialPort1.Write(s);
                    }
                }
                else
                {
                    serialPort1.Write(s);
                    //   Log(LogMsgType.Outgoing, s); 
                }


            }
            catch (Exception)
            {
                MessageBox.Show(this, e.ToString(), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); 


            }
        }


        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            rtfTerminal.Text = "";
        }

    }
}

基于c#的工控软件版本v1.01_11.25

上一篇:用delphi的THTTPRIO控件调用c#写的webservice。


下一篇:.net Thrift 之旅 (一) Windows 安装及 HelloWorld