代码地址:http://pan.baidu.com/share/link?shareid=3381776290&uk=588847378
新版本做了3个方面修改
1,修改了原有的打开关闭的链接图片,改到本地工程中
2,添加了定时发送机制
3,添加的帮助栏
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;
using System.Diagnostics;
namespace ComAssistant1
{
public partial class ComAssis : 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 ComAssis()
{
InitializeComponent();
}
Mutex m_Mutex = null;//锁
bool flag;
private void Form1_Load(object sender, EventArgs e)
{
//判断串口打开或关闭
if (serialPort1.IsOpen)
{
serialPort1.Close();
pictureBox1.Image = ComAssistant1.Properties.Resources.open;
}
else
{
pictureBox1.Image = ComAssistant1.Properties.Resources.close;
}
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)
{
this.serialPort1.DataReceived -= this.serialPort1_DataReceived;//先关掉对应的事件
DisconnectDeveice();
pictureBox1.Image = ComAssistant1.Properties.Resources.close;
}
else
{
this.serialPort1.DataReceived += this.serialPort1_DataReceived;
serialPort1.PortName = comboBox1.Text;
serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);
serialPort1.Open();
pictureBox1.Image = ComAssistant1.Properties.Resources.open;
}
RefrespictureBox1();
}
catch (Exception)
{
MessageBox.Show(this, e.ToString(), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void SendData_Click(object sender, EventArgs e)
{
if (AutoSend.Checked)
{
timer1.Enabled = true;
timer1.Interval = int.Parse(textEdit1.Text);
}
else
{
timer1.Enabled = false;
}
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);
}
else
{
s = txtSend.Text;
}
serialPort1.Write(s);
}
catch (Exception)
{
MessageBox.Show(this, e.ToString(), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
rtfTerminal.Text = "";
}
private void checkBox2_CheckedChanged(object sender, EventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
SendData_Click(sender, e);
}
private void textEdit1_TextChanged(object sender, EventArgs e)
{
timer1.Interval = int.Parse(textEdit1.Text);
}
private void ComAssis_HelpButtonClicked(object sender, CancelEventArgs e)
{
if (MessageBox.Show("是否需要自动跳转到开发者网\r\nhttp://blog.csdn.net/jonnyqian",
"Help Message", MessageBoxButtons.OKCancel) == DialogResult.OK)
{
Process.Start("http://blog.csdn.net/jonnyqian");
}
}
}
}