Imports System.IO.Ports
Imports System.Text

Public Class Form1

    '声明一个委派类，并声明符合函数参数有一个，而其类型是字符串
    Delegate Sub SetTextCallback(ByVal InputString As String)

    '**************************************************************
    '窗体的Load事件中先将所有的通信端口先列出来
    '将通信端口排序，并将第一个通信端口设为默认值
    '**************************************************************

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        For Each sp As String In SerialPort.GetPortNames()
            cmbCOM.Items.Add(sp)
        Next
        cmbCOM.Sorted = True   '排序
        cmbCOM.SelectedIndex = 0 '第一个默认排序
    End Sub
    '**************************************************************
    '『打开通信端口』按钮的Click事件
    '此事件将设定通信端口参数，并打开通信端口
    '**************************************************************
    Private Sub btnOpenPort_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpenPort.Click
        Dim mPortName As String
        mPortName = cmbCOM.SelectedItem.ToString   '欲打开的通信端口  
        RS232.PortName = mPortName
        RS232.Encoding = Encoding.ASCII
        If Not RS232.IsOpen Then  '还未打开
            RS232.Open()  '打开通信端口
            btnSend.Enabled = True  '致能传送按钮
            
        Else
            MsgBox("~~通信端口打开错误(通信端口已被打开)~~", MsgBoxStyle.Critical Or MsgBoxStyle.OkCancel)
            End
        End If
        picCOM.Image = picON.Image '变更为绿色图示
    End Sub
    '**************************************************************
    '『关闭通信端口』按钮的Click事件
    '以Cｌose方法关闭通信端口，并释放对象所占用的资源
    '**************************************************************
    Private Sub btnClosePort_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClosePort.Click
        If RS232 Is Nothing OrElse Not RS232.IsOpen Then  '还未打开
            MsgBox("~~通信端口还未打开~~", MsgBoxStyle.Critical Or MsgBoxStyle.OkCancel)
        Else
            RS232.Close()
        End If
        picCOM.Image = picOFF.Image '变更为白色图示
    End Sub
    '**************************************************************
    '『结束程序』按钮的Click事件
    '此事件将设定通信端口参数，并打开通信端口
    '**************************************************************
    Private Sub btnClose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClose.Click
        If Not RS232 Is Nothing Then  '判断是否已创建通信对象
            If RS232.IsOpen Then RS232.Close() '若已打开，就将其关闭
        End If
        End
    End Sub

    '**************************************************************
    '通信端口的KeyPress事件，在此不让用户输入数据
    '**************************************************************
    Private Sub cmbCOM_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles cmbCOM.KeyPress
        e.KeyChar = ChrW(0)  '禁止用户在其中输入任何的文字
    End Sub

    '**************************************************************
    '通信端口对象的DataReceived事件程序
    '当有数据超过ReceivedBytesThreshold属性设定值会引发此事件
    '接收的程序可以写在此事件程序中
    '由于此事件的引发是在另一个线程，因此必须使用委派来处理
    '**************************************************************
   Private Sub RS232_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles RS232.DataReceived
        If e.EventType <> SerialData.Chars Then Exit Sub '判断接收的数据是否为字符
        Dim InString As String
        If rbRAsc.Checked Then   '字符 
            InString = RS232.ReadExisting '取得字符串
            DisplayText(InString)  '显示数据
        Else   '16进制 
            Dim iReceivedbytes As Integer, i As Integer
            Dim strReceiveBytes As String
            Dim bReadByte() As Byte
            iReceivedbytes = RS232.BytesToRead   'buffer中所有字节数 
            ReDim bReadByte(iReceivedbytes - 1)
            RS232.Read(bReadByte, 0, iReceivedbytes)
            For i = 0 To iReceivedbytes - 1
                strReceiveBytes = Hex(bReadByte(i))

            Next
            DisplayText(strReceiveBytes)  '显示数据
            End If

    End Sub

    '**************************************************************
    '委派子程序
    '处理上述通信端口的接收事件
    '由于欲将数据显示到接收文字框中，因此必须检查是否由另外的Thread
    '所调用的，若是，则必须先创建委派对象
    'Invoke用于在拥有控件基础窗口控制代码的线程上执行委派
    '**************************************************************
    Private Sub DisplayText(ByVal comData As String)
        '如果调用txtReceive的是另外的线程，返回True
        If Me.txtReceive.InvokeRequired Then
            '利用委派型别创建委派对象，并指定委派的函数
            Dim d As New SetTextCallback(AddressOf DisplayText)
            '用大括号{} 括住初始值，藉以初始化数组的值。
            Me.Invoke(d, New Object() {comData})  '以指定的自变量清单调用函数
        Else  '相同的线程
            txtReceive.Text += comData   '将收到的数据入接收文字框中
        End If
    End Sub

    '**************************************************************
    '传送按钮的Click事件
    '以Write方法送出文字框内的数据
    '**************************************************************

    Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click


        Dim buffer As Byte() = {1, 2, 3, 4}
        Dim offset As Integer = 1
        Dim count As Integer = 4

        RS232.Write(buffer, offset, count) '这样就能传输4 个字节的十六进制数了

        'Dim sendData1 As Byte
        'Dim sendData2 As Byte
        'Dim sendData3 As Byte

        'If radFormat1.Checked Then
        'sendData1 = (txtSend1.Text)
        'sendData2 = (txtSend2.Text)
        'sendData3 = (txtSend3.Text)
        'Else
        'sendData1 = (txtSend1.Text - 48)
        'sendData2 = (txtSend2.Text - 48)
        'sendData3 = (txtSend3.Text - 48)
        'End If
        'RS232.Write(txtSend1.Text)
        'RS232.Write(txtSend2.Text)
        'RS232.Write(txtSend3.Text & vbCr)
        'RS232.Write(sendData1)
        'RS232.Write(sendData2)
        'RS232.Write(sendData3)
    End Sub

   

    Private Sub CheckBox1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox1.CheckedChanged
        If CheckBox1.CheckState = CheckState.Checked Then
            CheckBox1.Text = "加 1"
        ElseIf CheckBox1.CheckState = CheckState.Unchecked Then
            CheckBox1.Text = "不加 1"
        End If
    End Sub

   
    Private Sub btnClear_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClear.Click

        txtReceive.Text = Nothing
    End Sub
End Class
