C#学习小结

  -)C#语言
1) 委托:
委托实现一般分三步骤:
1、 声明委托
声明一个新的委托类型。每个委托类型都描述参数的数目和类型,以及它可以封装的方法的返回值类型。每当需要一组新的参数类型或新的返回值类型时,都必须声明一个新的委托类型。
例如:
Public delegate void ProcessBookDelegate(Book book);
2、  实例化委托。
声明了委托类型后,必须创建委托对象并使之与特定方法关联。在上面的示例中,这是通过将 PrintTitle 方法传递给 ProcessPaperbackBooks 方法来完成的,如下所示:
     static void PrintTitle(Book b)
{ System.Console.WriteLine(" {0}", b.Title); }
bookDB.ProcessPaperbackBooks(PrintTitle);
internal void AddBookToTotal(Book book)
{ countBooks += 1;
priceBooks += book.Price; }
bookDB.ProcessPaperbackBooks(totaller.AddBookToTotal);
在两个示例中,都向 ProcessPaperbackBooks 方法传递了一个新的委托对象。委托一旦创建,它的关联方法就不能更改;委托对象是不可变的。
3、  调用委托。
创建委托对象后,通常将委托对象传递给将调用该委托的其他代码。通过委托对象的名称(后面跟着要传递给委托的参数,括在括号内)调用委托对象。下面是委托调用的示例:
processBook(b);
与本例一样,可以通过使用 BeginInvokeEndInvoke 方法同步或异步调用委托。
 
2) 全局变量
在很多时候,会有一些变量会在几个窗口之间传递,而这需要用到全局变量。而在C#里,没有定义全局变量的关键字,所以可以可以用下来方法来实现全局变量。
1、用静态成员来作全程变量
2、建立一个类,然后在该类中添加一个静态的成员变量,或者加一个常量也可以,然后用的时候直接对该类进行访问即可。 
class Static
    {
        public static SerialPort ComPort;
        public static ushort usInstrumentID=0;
        public static Timer tmrCommunicate;
        public static Boolean IsComing=false ;
        public static int TimeOutCount=0;
}
在窗口实例类中,可以用Static.TimeOutCount这种格式调用变量。
3、C#中没有全局变量,但可以使用命名空间和静态变实现类似功能,下面的例子定义了一个用户类,初始化用户名后,在filetobase命名空间的其它类都可以获得用户名  
namespace  FileToBase{  
public  class  user  
{   private  static  string  userName;  
   public  user(string  name)  
   { userName=name;  
   }  
         public  static  string  UserName  
       {  
           get  
           {  
                 return  userName;  
           }  
       }  
 }  
3)数组和枚举运用
1、一维数组
public byte[] ValueSJSOE;//事件SOE的个数(没有实例化,和定义其个数)
 public byte[] ValueSGSOE;//事故SOE的个数
 
 private int[] eachMessHasKeyNum ={ 8,8,5,8,3,8,8,8,5,4,4,4,4,4,4,4,2};//下面读取报文中的KEY个数(定义,实例化)
 
 //整定值写报文的KEY和Value
public byte[] LastKeyValueZDZ=new byte[11];
 
 //系统参数和继电器的写报文的KEY和Value
 public byte[] LastKeyValueSystemParm = new byte[6];
public byte[] LastKeyValueJDQ=new byte[6];
2、交错数组
定义:
public byte[][] KEYValueJKZ;//把读取监控值的KEY和Value存在数据里
实例化:
//初始化存储各个仪表数据的数组
            KEYValueJKZ=new byte[JKZNum][];//JKZNum 是一个常量
            for(int i=0 ;i<JKZNum ;i++)
            {
                KEYValueJKZ[i]=new byte[6]; //每个数组的头两位是KEY
            }
 
赋值:
            for (int i = 0; i < JKZNum; i++)
            {
                KEYValueJKZ[i][0] =Convert.ToByte (i + 8);
                KEYValueJKZ[i][1] = 0x41;
            }
注意:交错数组与二维数组的差别
若:public byte[,] KEYValueJKZ1
则KEYValueJKZ1[1,]这样用是错误的。
而可以用KEYValueJKZ[1],返回的是一个数组。
4、 枚举
Public enum DataQueueTypes {AllMess,JKKGSOE,SJSOE,SGSOE,wJDQ,
wSystemParm,wZDZ};
public DataQueueTypes SendDataQueueType;
 
4)线程
例子:
private Thread CheckSendDataType;
CheckSendDataType = new Thread(new ThreadStart (CheckSendData));创建一个线程,用于识别发送区的数据格式
//创建一个线程,用于识别发送区的数据格式
        private void CheckSendData()
        {
        ………….
      }
5)数值处理
1、输入一串字符,判断是否是16进制,并把字符串转化为对应的数值。
// 用于检测发送数据区的数据格式的过程。
        private Boolean CheckGetSendData(String strSendData)
        {
           if (strSendData != "")
     {
               foreach (char chrTemp in strSendData)  //
检测数据的合法性
                   {
                      if (chrTemp == 0x20)
                           continue;
                      else if (chrTemp >= 0x30 && chrTemp <= 0x39)
                           continue;
                      else if (chrTemp >= 0x41 && chrTemp <= 0x46)
                           continue;
                      else if (chrTemp >= 0x61 && chrTemp <= 0x66)
                            continue;
                      else
                            {
                             return (false);      
                             }
                   }
                   try
                   {
                       String[] strData = strSendData.Split(Convert.ToChar(0x20));
                        int index, intCount = strData.Length;
                        byte[] bytDataTemp = new byte[intCount];
                        for (index = 0; index < intCount; index++)  //16
进制数据的字符串长度不能超过 2
                        {
                            if (strData[index].Length > 2)
                            {
                            return(false );
                            }
                        }
                        for (index = 0; index < intCount; index++)
                        {
                            bytDataTemp[index] = Convert.ToByte(strData[index], 16);//
把字符串转化成对应的字节数组
                         }
                            bytSendData = bytDataTemp;
                            return (true);
                     }
                      catch (Exception ex)
                      {
                       Console.WriteLine(ex.Message);
                       return (false);
                       }
                       finally
                       {
                       }
              }
              return (false);
         }
2、把收到的16进制数据转化成字符串
        private string ByteArrayToHexString(byte[] data)
        {
            StringBuilder sb = new StringBuilder(data.Length * 3);
            foreach (byte b in data)
                sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' '));
            return sb.ToString().ToUpper();
        }
3、 双浮点数保留两位数
Double Temp;
String strTemp;
Temp=123.8956;
strTemp=Temp.ToString(“f2”);
4、 把长度为四的数组,转化为整数;整数转化为双浮点数的算术运算;
妙数转化为日期;以一定日期格式输出日期。
public static    string GetDateTime(byte[] Data)
        {
            long milSecond = 0;
            long Second = 0;
            double totalSecond = 0;
            DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0);//开始日期为1970-1-1 0:0:0
            for (int i = 3; i >= 0; i--)
            {
                milSecond <<= 8;
                milSecond = milSecond ^ Data[4 + i];//转化为整数
            }
            if (milSecond > 1000)
               milSecond = 0;
           for (int i = 3; i >= 0; i--)
           {
               Second <<= 8;
               Second =Second ^Data[i];
           }
            totalSecond = (double)Second + (double)(milSecond / 1000);//转化为double再除,才能保存小数后面的数。
            dt = dt.AddSeconds(totalSecond);//妙数转化为日期。
            return dt.ToString("yyyy年MM月dd日HH:mm:ss");//以特定的格式,输出日期
        }
6)用到的控件
1、 SerialPort串口控件
 
(1.1)以下是读取,电脑的串口特性,以供选择。
      using System.IO.Ports;
    private void LoadSerialPortConfiguration()
        {
            foreach (string s in SerialPort.GetPortNames())
            {
                cmbPortName.Items.Add(s);
            }
            foreach (string s in Enum.GetNames(typeof(Parity)))
            {
                cmbParity.Items.Add(s); 
            }
            foreach (string s in Enum.GetNames(typeof(StopBits)))
            {
                cmbStopBits.Items.Add(s); 
            }
// 波特率和数据位可以分别在 combobox 中的 items 手动输入。
        }
1 2 )设置串口控件
(波特率,奇偶校验,数据位,停止位)设置
// 设置 serialPort1 的串口属性
                    serialPort1.PortName = cmbPortName.Text;
                    serialPort1.BaudRate = int.Parse(cmbBaudRate.Text);
                    serialPort1.DataBits = int.Parse(cmbDataBits.Text);
                    serialPort1.StopBits = (StopBits)Enum.Parse(typeof(StopBits), cmbStopBits.Text);
                    serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), cmbParity.Text);
                    // 打开串口
                    serialPort1.Open();
1.3 )发送数据
private void btnSend_Click(object sender, EventArgs e)
        {
            if (bComOpen == true)
            {
                if (bSendHex == true)
                {
                    if (CheckGetSendData(txtSend.Text.Trim() ) == true)
                    {
                        byte[] data=bytSendData ;
                        //
以字节格式发送数据
                        intSendDataCount += data.Length;
                        serialPort1.Write(data, 0, data.Length);
                        groupBox2.Text = "
发送区    :发送数据成功! ";
                    }
                    else
                    {
                        groupBox2.Text = "
发送区    :发送数据有错! ";
                        if (chkAutoSend.Checked == true)  //
当定时发送时,如果数据格式错误的话,就停止定时器
                        {
                            tmrAutoSend.Enabled = false;
                            chkAutoSend.Checked = false;
                        }
                    }
                }
                else
                {
                    //
以文本格式发送数据
                    serialPort1.Write(txtSend.Text);
                    intSendDataCount += txtSend.Text.Length;
                    groupBox2.Text = "
发送区    :发送数据成功! ";
                }
            }
        }
1 4 )接收并显示数据
串口数据的接收是一个事件,可以通过设置其接收字节数阀值属性 ReceivedBytesThreshold N ),来确定当接收大于 N 个字节数时,产生一个接收事件。有一点很重要的是,接收事件是托管给 CLT 的事件池的,也就是说运行在另一个独立线程中。所以要把接收到的数据显示在串口控件上,不能直接赋值。要通过控件的触发函数( txtReceiveDataCount.Invoke(new EventHandler(delegate {      显示数据语句         }))
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
           
            if (bReceiveHex == true)
            {
                DataReceivedEventHandler DataReceive = new DataReceivedEventHandler(this.HexDataReceive);
                DataReceive();
            }
            else
            {
                DataReceivedEventHandler DataReceive = new DataReceivedEventHandler(this.TextDataReceive);
                DataReceive();
            }
          
        }
        private void chkReceiveHex_CheckedChanged(object sender, EventArgs e)// 事件
        {
            if (chkReceiveHex.Checked == true)
                bReceiveHex = true;
            else
                bReceiveHex = false;
        }
        //
以文本格式显示
        private void TextDataReceive()
        {
            String strReceiveData = serialPort1.ReadExisting();
            intReceiveDataCount += strReceiveData.Length;
            Log(strReceiveData);
        }
        // 16 进制数据显示
        private void HexDataReceive()
        {
            // Obtain the number of bytes waiting in the port's buffer
            int bytes = serialPort1.BytesToRead;
            // Create a byte array buffer to hold the incoming data
            byte[] buffer = new byte[bytes];
            intReceiveDataCount += bytes;
            // Read the data from the port and store it in our buffer
            serialPort1.Read(buffer, 0, bytes);
                // Show the user the incoming data in hex format
                Log ( ByteArrayToHexString(buffer));
        }
        // 在接收区显示数据
        private void Log(string msg)
        {
            if (bStopShow == false)
            {
                txtReceive.Invoke(new EventHandler(delegate
                {
                    txtReceive.AppendText(msg);
                    txtReceive.ScrollToCaret();
                }));
            }
            txtReceiveDataCount.Invoke(new EventHandler(delegate { txtReceiveDataCount.Text = intReceiveDataCount.ToString(); }));
            txtSendDataCount.Invoke(new EventHandler(delegate { txtSendDataCount.Text = intSendDataCount.ToString(); }));
        }
2、   Timer 控件
发送请求报文,要用到定时器定时发送,要注意的是:在发送数据时候,要先把定时器关闭,发送完数据后,再把定时器开启。以免正在发送数据时,定时器定时事件发生时去实行其他的函数,而导致没有把应该发送的数据发送出去。
Static.tmrCommunicate = new System.Timers.Timer();
Static.tmrCommunicate.Elapsed += new ElapsedEventHandler(SendData);
Static.tmrCommunicate.Interval = 200;
private void SendData(object source, ElapsedEventArgs e)
        {
            if (!Static.IsComing)
            {
                Static.tmrCommunicate.Enabled = false;   // 关定时器
                Static.IsComing = true;
                byte[] SendDataMess;
                SendDataMess = WorkMess.GetSendData();
                if (SendDataMess != null)
                    Static.ComPort.Write(SendDataMess, 0, SendDataMess.Length);
                Static.tmrCommunicate.Enabled = true;   // 定时器的调用函数一定要在实行过程中,先关后开
            }
            else
                TimeOutHandler(); // 检测是否超时,若是并做处理
       }
3、   ListView 控件
4、   TabControl 控件
用程序代码选择 TabControl 控件的标签,
private void ToolStripMenuItemSystemParm_Click(object sender, EventArgs e)
        {
            if (tabControlMain.Visible == false)
            {
                tabControlMain.Visible = true;
                panelMain.Visible = false;
 
            }
            tabControlMain.SelectedIndex = 1;// 选择第二个标签
        }
  
 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值