Класс для COM-порта с поддержкой событий - VB
Формулировка задачи:
Доброго. Мне нужен класс для работы с COM-портом с поддержкой событий.
У меня есть вариант: Serial Port Communication in Excel (VBA). Я его использую в Excel. Проблема в том, что нужно ручками регулировать время между командой и ответом, чтобы гарантировано принять данные во входной буфер. Хотелось бы иметь событие OnReceive(), которое основано на WaitCommEvent(). Без событийного решения трудно реализовать оптимальный по скорости алгоритм работы с устройствами. Мне нужно с определённой частотой читать данные и желательно получать их по мере заполнения входного буфера нужной посылкой.
Можно ли что-то такое сделать на vb6? Мне не нужны сторонние решения в готовом виде (ActiveX, dll и т.п.). Нужно всё реализовать на макросах в таблице.
Решение задачи: «Класс для COM-порта с поддержкой событий»
textual
Листинг программы
Public Function CommRead(intPortID As Integer, strData As String, _ lngSize As Long) As Long Dim lngStatus As Long Dim lngRdSize As Long, lngBytesRead As Long Dim lngRdStatus As Long, strRdBuffer As String * 1024 Dim lngErrorFlags As Long, udtCommStat As COMSTAT Dim osReader As OVERLAPPED osReader.hEvent = 0 osReader.Internal = 0 osReader.InternalHigh = 0 osReader.offset = 0 osReader.OffsetHigh = 0 On Error GoTo Routine_Error strData = "" lngBytesRead = 0 ' ' Clear any previous errors and get current status. ' lngStatus = ClearCommError(udtPorts(intPortID).lngHandle, lngErrorFlags, _ ' udtCommStat) ' ' If lngStatus = 0 Then ' ' lngBytesRead = -1 ' lngStatus = SetCommError("CommRead (ClearCommError)") ' GoTo Routine_Exit ' ' End If ' If udtCommStat.cbInQue > 0 Then ' ' If udtCommStat.cbInQue > lngSize Then ' ' lngRdSize = udtCommStat.cbInQue ' ' Else ' ' lngRdSize = lngSize ' ' End If ' ' Else ' ' lngRdSize = 0 ' ' End If lngRdSize = lngSize If lngRdSize Then osReader.hEvent = CreateEvent(0, True, False, 0) If osReader.hEvent = 0 Then lngBytesRead = -1 lngStatus = SetCommErrorEx("CommRead (CreateEvent)", _ udtPorts(intPortID).lngHandle) GoTo Routine_Exit End If lngRdStatus = ReadFile(udtPorts(intPortID).lngHandle, strRdBuffer, _ lngRdSize, 0, osReader) If lngRdStatus = 0 Then Dim dwRes As Long ' Wait for read to complete. dwRes = WaitForSingleObject(osReader.hEvent, READ_TIMEOUT) Select Case dwRes ' Read completed. Case WAIT_OBJECT_0 If GetOverlappedResult(udtPorts(intPortID).lngHandle, _ osReader, lngBytesRead, False) = 0 Then ' Error in communications; report it. lngBytesRead = -1 lngStatus = SetCommErrorEx("CommRead (GetOverlappedResult)", _ udtPorts(intPortID).lngHandle) GoTo Routine_Exit Else ' Read completed successfully. End If Case WAIT_TIMEOUT lngBytesRead = -1 lngStatus = SetCommErrorEx("CommRead (WaitForSingleObject)", _ udtPorts(intPortID).lngHandle) GoTo Routine_Exit Case Else lngBytesRead = -1 lngStatus = SetCommErrorEx("CommRead (WaitForSingleObject)", _ udtPorts(intPortID).lngHandle) GoTo Routine_Exit End Select End If strData = Left$(strRdBuffer, lngBytesRead) End If Routine_Exit: If Not osReader.hEvent = 0 Then CloseHandle osReader.hEvent CommRead = lngBytesRead Exit Function Routine_Error: lngBytesRead = -1 lngStatus = Err.Number With udtCommError .lngErrorCode = lngStatus .strFunction = "CommRead" .strErrorMessage = Err.Description End With Resume Routine_Exit End Function
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д