C#学习小结
时间:2023-02-26 19:30:01
-)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);
这将创建与静态方法 Test.PrintTitle 相关的新委托对象。类似地,对象 totaller 非静态方法 AddBookToTotal 以下方式传递:
internal void AddBookToTotal(Book book)
{ countBooks = 1;
priceBooks = book.Price; }
bookDB.ProcessPaperbackBooks(totaller.AddBookToTotal);
在两个例子中,都向 ProcessPaperbackBooks 该方法传达了一个新的委托对象。委托一旦创建,其相关方法就不能改变;委托对象是不可改变的。
3、
调用委托。
创建委托对象后,委托对象通常传递给其他代码,以调用委托对象。通过委托对象的名称(后面将参数传递给委托参数,包括括括括括号内)调用委托对象。以下是委托调用的示例:
processBook(b);
就像这个例子一样,可以使用 BeginInvoke 和 EndInvoke 委托同步或异步调用方法。
2)全局变量
在许多情况下,一些变量会在几个窗口之间传递,这需要全局变量。C#里面没有定义全局变量的关键词,可以用下面的方法实现全局变量。
1.全程变量采用静态成员
2.建立一个类,然后在该类中添加静态成员变量或常量,然后在使用时直接访问该类。
class Static
{
public static SerialPort ComPort;
public static ushort usInstrumentID=0;
public static Timer tmrCommunicate; /div>
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;
}
}
}
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
{
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()
{
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);
}
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);
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 SerialPort.GetPortNames())
{
cmbPortName.Items.Add(s);
}
foreach (string s in Enum.GetNames(typeof(Parity)))
{
cmbParity.Items.Add(s);
}
{
cmbParity.Items.Add(s);
}
foreach (string s in Enum.GetNames(typeof(StopBits)))
{
cmbStopBits.Items.Add(s);
}
{
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.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 )发送数据
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 = " 发送区 :发送数据成功! ";
}
}
}
{
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();
}
}
{
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);
}
{
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;
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];
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));
}
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(); }));
}
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
控件
private void ToolStripMenuItemSystemParm_Click(object sender, EventArgs e)
{
if (tabControlMain.Visible == false)
{
tabControlMain.Visible = true;
panelMain.Visible = false;
}
tabControlMain.SelectedIndex = 1;//
选择第二个标签
}
相关文章
动力学技术KTU1121 USB Type-C 端口保护器的介绍、特性、及应用
Sensata PTE7300密封数字压力传感器的介绍、特性、及应用
PANJIT PBHV8110DA/PBHV9110DA低Vce(sat)晶体管的介绍、特性、及应用
ams OSRAM OSLON 黑色平板X LED器件的介绍、特性、及应用
Cree LED CLQ6A三合一贴片LED的介绍、特性、及应用
Cree LED CLQ6B 4-in-1 RGBW贴片LED的介绍、特性、及应用
NDK NX1210AB表面贴装晶体的介绍、特性、及应用
伊顿ACE2V3225共模芯片电感器的介绍、特性、及应用
意法半导体X040灵敏型栅可控硅和Z040可控硅的介绍、特性、及应用
ABLIC S-82Y1B电池保护芯片的介绍、特性、及应用