VB的MSCOMM控件雖然很好用,但是在沒有裝VB的機器上用該控件總覺得有些累贅,網上的VB API代碼大部分都基于是同步方式,處理複雜的通信模式不是太理想,是以用了一些時間,把VC項目中的異步序列槽讀寫代碼翻譯為VB格式。
在VB建立一個類,把下面的代碼複制後即可使用
'*************************************************************************
'**模 塊 名:SerialPort
'**說 明:YFsoft 版權所有2006 - 2007(C)
'**創 建 人:葉帆
'**日 期:2006-08-17 14:32:29
'**修 改 人:
'**日 期:
'**描 述:序列槽異步讀寫(API)
'**版 本:V1.0.0
Option Explicit
Private Type ComStat
fCtsHold As Long
fDsrHold As Long
fRlsdHold As Long
fXoffHold As Long
fXoffSent As Long
fEof As Long
fTxim As Long
fReserved As Long
cbInQue As Long
cbOutQue As Long
End Type
Private Type COMMTIMEOUTS
ReadIntervalTimeout As Long
ReadTotalTimeoutMultiplier As Long
ReadTotalTimeoutConstant As Long
WriteTotalTimeoutMultiplier As Long
WriteTotalTimeoutConstant As Long
Private Type DCB
DCBlength As Long
BaudRate As Long
'DWORD DCBlength; /* sizeof(DCB) */
'DWORD BaudRate; /* Baudrate at which running */
'DWORD fBinary: 1; /* Binary Mode (skip EOF check) */
'DWORD fParity: 1; /* Enable parity checking */
'DWORD fOutxCtsFlow:1; /* CTS handshaking on output */
'DWORD fOutxDsrFlow:1; /* DSR handshaking on output */
'DWORD fDtrControl:2; /* DTR Flow control */
'DWORD fDsrSensitivity:1; /* DSR Sensitivity */
'DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */
'DWORD fOutX: 1; /* Enable output X-ON/X-OFF */
'DWORD fInX: 1; /* Enable input X-ON/X-OFF */
'DWORD fErrorChar: 1; /* Enable Err Replacement */
'DWORD fNull: 1; /* Enable Null stripping */
'DWORD fRtsControl:2; /* Rts Flow control */
'DWORD fAbortOnError:1; /* Abort all reads and writes on Error */
'DWORD fDummy2:17; /* Reserved */
fBitFields As Long 'See Comments in Win32API.Txt
wReserved As Integer
XonLim As Integer
XoffLim As Integer
ByteSize As Byte
Parity As Byte
StopBits As Byte
XonChar As Byte
XoffChar As Byte
ErrorChar As Byte
EofChar As Byte
EvtChar As Byte
wReserved1 As Integer 'Reserved; Do Not Use
Private Type OVERLAPPED
Internal As Long
InternalHigh As Long
offset As Long
OffsetHigh As Long
hEvent As Long
Private Type SECURITY_ATTRIBUTES
nLength As Long
lpSecurityDescriptor As Long
bInheritHandle As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function GetLastError Lib "kernel32" () As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As OVERLAPPED) As Long
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As OVERLAPPED) As Long 'OVERLAPPED
Private Declare Function SetCommTimeouts Lib "kernel32" (ByVal hFile As Long, lpCommTimeouts As COMMTIMEOUTS) As Long
Private Declare Function GetCommTimeouts Lib "kernel32" (ByVal hFile As Long, lpCommTimeouts As COMMTIMEOUTS) As Long
Private Declare Function BuildCommDCB Lib "kernel32" Alias "BuildCommDCBA" (ByVal lpDef As String, lpDCB As DCB) As Long
Private Declare Function SetCommState Lib "kernel32" (ByVal hCommDev As Long, lpDCB As DCB) As Long
Private Declare Function GetCommState Lib "kernel32" (ByVal nCid As Long, lpDCB As DCB) As Long
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function FlushFileBuffers Lib "kernel32" (ByVal hFile As Long) As Long
Private Declare Function CreateEvent Lib "kernel32" Alias "CreateEventA" (lpEventAttributes As SECURITY_ATTRIBUTES, ByVal bManualReset As Long, ByVal bInitialState As Long, ByVal lpName As String) As Long
Private Declare Function SetCommMask Lib "kernel32" (ByVal hFile As Long, ByVal dwEvtMask As Long) As Long
Private Declare Function SetEvent Lib "kernel32" (ByVal hEvent As Long) As Long
Private Declare Function PurgeComm Lib "kernel32" (ByVal hFile As Long, ByVal dwFlags As Long) As Long
Private Declare Function ClearCommError Lib "kernel32" (ByVal hFile As Long, lpErrors As Long, lpStat As ComStat) As Long
Private Declare Function GetOverlappedResult Lib "kernel32" (ByVal hFile As Long, lpOverlapped As OVERLAPPED, lpNumberOfBytesTransferred As Long, ByVal bWait As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function SetupComm Lib "kernel32" (ByVal hFile As Long, ByVal dwInQueue As Long, ByVal dwOutQueue As Long) As Long
Private Const GENERIC_WRITE = &H40000000
Private Const GENERIC_READ = &H80000000
Private Const OPEN_EXISTING = 3
Private Const FILE_ATTRIBUTE_NORMAL = &H80
Private Const FILE_FLAG_OVERLAPPED = &H40000000
Private Const DTR_CONTROL_DISABLE = &H0
Private Const RTS_CONTROL_ENABLE = &H1
Private Const PURGE_RXABORT = &H2
Private Const PURGE_RXCLEAR = &H8
Private Const PURGE_TXABORT = &H1
Private Const PURGE_TXCLEAR = &H4
Private Const ERROR_IO_PENDING = 997
Private Const STATUS_WAIT_0 = &H0
Private Const WAIT_OBJECT_0 = (STATUS_WAIT_0 + 0)
Private Const WAIT_TIMEOUT = 258&
Private m_Handle As Long
Private m_OverlappedRead As OVERLAPPED
Private m_OverlappedWrite As OVERLAPPED
'**函 數 名:OpenPort
'**輸 入:ComNumber(Long) - 序列槽号
'** :Comsettings(String) - 配置資訊
'**輸 出:(Long) - 0 成功 非 0 失敗
'**功能描述:打開序列槽
'**全局變量:
'**調用子產品:
'**作 者:葉帆
'**日 期:2006-08-17 14:40:14
Public Function OpenPort(ComNumber As Long, Comsettings As String, Optional lngInSize As Long = 1024, Optional lngOutSize As Long = 512) As Long
On Error GoTo handelinitcom
Dim retval As Long
Dim CtimeOut As COMMTIMEOUTS, dcbs As DCB
Dim strCOM As String, strConfig As String
strCOM = "/.COM" & Format(ComNumber, "0")
m_Handle = CreateFile(strCOM, GENERIC_READ Or GENERIC_WRITE, 0, 0&, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL Or FILE_FLAG_OVERLAPPED, 0)
If m_Handle = -1 Then
OpenPort = -1
Exit Function
End If
'設定dcb塊
dcbs.DCBlength = Len(dcbs) '長度
Call GetCommState(m_Handle, dcbs)
'波特率,奇偶校驗,資料位,停止位 如:9600,n,8,1
strConfig = "COM" & Format(ComNumber, "0") & ":" & Comsettings
Call BuildCommDCB(strConfig, dcbs)
'------------------------------
' dcbs.fBinary = 1 '二進制方式
' dcbs.fOutxCtsFlow = 0 '不用CTS檢測發送流控制
' dcbs.fOutxDsrFlow = 0 '不用DSR檢測發送流控制
' dcbs.fDtrControl = DTR_CONTROL_DISABLE '禁止DTR流量控制
' dcbs.fDsrSensitivity = 0 '對DTR信号線不敏感
' dcbs.fTXContinueOnXoff = 1 '檢測接收緩沖區
' dcbs.fOutX = 0 '不做發送字元控制
' dcbs.fInX = 0 '不做接收控制
' dcbs.fErrorChar = 0 '是否用指定字元替換校驗錯的字元
' dcbs.fNull = 0 '保留NULL字元
' dcbs.fRtsControl = RTS_CONTROL_ENABLE '允許RTS流量控制
' dcbs.fAbortOnError = 0 '發送錯誤後,繼續進行下面的讀寫操作
' dcbs.fDummy2 = 0 '保留
dcbs.fBitFields = 1 * 2 ^ 0 Or DTR_CONTROL_DISABLE * 2 ^ 4 Or 1 * 2 ^ 7 Or RTS_CONTROL_ENABLE * 2 ^ 12
dcbs.wReserved = 0 '沒有使用,必須為0
dcbs.XonLim = 0 '指定在XOFF字元發送之前接收到緩沖區中可允許的最小位元組數
dcbs.XoffLim = 0 '指定在XOFF字元發送之前緩沖區中可允許的最小可用位元組數
dcbs.XonChar = 0 '發送和接收的XON字元
dcbs.XoffChar = 0 '發送和接收的XOFF字元
dcbs.ErrorChar = 0 '代替接收到奇偶校驗錯誤的字元
dcbs.EofChar = 0 '用來表示資料的結束
dcbs.EvtChar = 0 '事件字元,接收到此字元時,會産生一個事件
'dcbs.wReserved1 = 0 '沒有使用
'dcbs.BaudRate =9600 '波特率
'dcbs.Parity=0 '奇偶校驗
'dcbs.ByteSize=8 '資料位
'dcbs.StopBits=0 '停止位
If dcbs.Parity = 0 Then ' 0-4=None,Odd,Even,Mark,Space
dcbs.fBitFields = dcbs.fBitFields And &HFFFD 'dcbs.fParity = 0 '奇偶校驗無效
Else
dcbs.fBitFields = dcbs.fBitFields Or &H2 'dcbs.fParity = 1 '奇偶校驗有效
'逾時設定
CtimeOut.ReadIntervalTimeout = 20 '0
CtimeOut.ReadTotalTimeoutConstant = 1 '2500
CtimeOut.ReadTotalTimeoutMultiplier = 1 '0
CtimeOut.WriteTotalTimeoutConstant = 10 '2500
CtimeOut.WriteTotalTimeoutMultiplier = 1 '0
retval = SetCommTimeouts(m_Handle, CtimeOut)
If retval = -1 Then
retval = GetLastError()
OpenPort = retval
retval = CloseHandle(m_Handle)
'擷取信号句柄
Dim lpEventAttributes1 As SECURITY_ATTRIBUTES
Dim lpEventAttributes2 As SECURITY_ATTRIBUTES
m_OverlappedRead.hEvent = CreateEvent(lpEventAttributes1, 1, 0, 0)
m_OverlappedWrite.hEvent = CreateEvent(lpEventAttributes2, 1, 0, 0)
'判斷設定參數是否成功 設定輸入和輸出緩沖區是否成功
If SetCommState(m_Handle, dcbs) = -1 Or SetupComm(m_Handle, lngInSize, lngOutSize) = -1 Or m_OverlappedRead.hEvent = 0 Or m_OverlappedWrite.hEvent = 0 Then
If (m_OverlappedRead.hEvent <> 0) Then CloseHandle (m_OverlappedRead.hEvent)
If (m_OverlappedWrite.hEvent <> 0) Then CloseHandle (m_OverlappedWrite.hEvent)
Call CloseHandle(m_Handle)
m_Handle = 0
OpenPort = 0
Exit Function
handelinitcom:
Call CloseHandle(m_Handle)
m_Handle = 0
OpenPort = -2
End Function
'**函 數 名:ClosePort
'**輸 入:無
'**輸 出:(Long) - 0 成功 -1 失敗
'**功能描述:關閉序列槽
'**日 期:2006-08-17 14:56:13
Public Function ClosePort() As Long
If (m_Handle = 0) Then
ClosePort = 1
Call SetCommMask(m_Handle, 0)
Call SetEvent(m_OverlappedRead.hEvent)
Call SetEvent(m_OverlappedWrite.hEvent)
If (m_OverlappedRead.hEvent <> 0) Then CloseHandle (m_OverlappedRead.hEvent)
If (m_OverlappedWrite.hEvent <> 0) Then CloseHandle (m_OverlappedWrite.hEvent)
If CloseHandle(m_Handle) <> 0 Then
ClosePort = 0
ClosePort = -1
'**函 數 名:ClearInBuf
'**輸 出:無
'**功能描述:清空輸入緩沖區
'**日 期:2006-08-17 14:57:26
Public Function ClearInBuf() As Long
ClearInBuf = 1
Call PurgeComm(m_Handle, PURGE_RXABORT Or PURGE_RXCLEAR)
ClearInBuf = 0
'**函 數 名:ClearOutBuf
'**輸 出:(Long) -
'**功能描述:清空輸出緩沖區
'**日 期:2006-08-17 15:40:38
Public Function ClearOutBuf() As Long
ClearOutBuf = 1
Call PurgeComm(m_Handle, PURGE_TXABORT Or PURGE_TXCLEAR)
ClearOutBuf = 0
'**函 數 名:SendData
'**輸 入:bytBuffer()(Byte) - 資料
'** :lngSize(Long) - 資料長度
'**功能描述:發送資料
'**日 期:2006-08-17 15:43:42
Public Function SendData(bytBuffer() As Byte, lngSize As Long) As Long
On Error GoTo ToExit '打開錯誤陷阱
'------------------------------------------------
SendData = 1
Dim dwBytesWritten As Long
Dim bWriteStat As Long
Dim ComStats As ComStat
Dim dwErrorFlags As Long
dwBytesWritten = lngSize
Call ClearCommError(m_Handle, dwErrorFlags, ComStats)
bWriteStat = WriteFile(m_Handle, bytBuffer(0), lngSize, dwBytesWritten, m_OverlappedWrite)
If bWriteStat = 0 Then
If GetLastError() = ERROR_IO_PENDING Then
Call GetOverlappedResult(m_Handle, m_OverlappedWrite, dwBytesWritten, 1) '等待直到發送完畢
End If
dwBytesWritten = 0
SendData = dwBytesWritten
'----------------
ToExit:
SendData = -1
'**函 數 名:ReadData
'**功能描述:讀取資料
'**日 期:2006-08-17 16:04:38
Public Function ReadData(bytBuffer() As Byte, lngSize As Long, Optional Overtime As Long = 3000) As Long
ReadData = 1
Dim lngBytesRead As Long
Dim fReadStat As Long
Dim dwRes As Long
lngBytesRead = lngSize
'讀資料
fReadStat = ReadFile(m_Handle, bytBuffer(0), lngSize, lngBytesRead, m_OverlappedRead)
If fReadStat = 0 Then
If GetLastError() = ERROR_IO_PENDING Then '重疊 I/O 操作在進行中
dwRes = WaitForSingleObject(m_OverlappedRead.hEvent, Overtime) '等待,直到逾時
Select Case dwRes
Case WAIT_OBJECT_0: '讀完成
If GetOverlappedResult(m_Handle, m_OverlappedRead, lngBytesRead, 0) = 0 Then
'錯誤
ReadData = -2
Exit Function
End If
Case WAIT_TIMEOUT: '逾時
ReadData = -1
Exit Function
Case Else: 'WaitForSingleObject 錯誤
End Select
ReadData = lngBytesRead
ReadData = -1
'**函 數 名:Class_Terminate
'**功能描述:
'**日 期:2006-08-17 16:36:21
Private Sub Class_Terminate()
Call ClosePort
End Sub