📄 tcomm32.cpp
字号:
/***************************************************************************\
* *
* TComm32.h - 串行口通讯程序, 版本 1.3.3.5 *
* Bulid: 09-05-2004 *
* Copyright (C) 1997-2004, Victor Chen *
* Homepage: http://www.cppfans.com *
* Email: victor@cppfans.com *
* *
\***************************************************************************/
#pragma hdrstop
#include "TComm32.h"
#include "yb_base.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
char _TComm32_Copyright_YBCHEN[] = "\r\nTComm32.cpp Serial Port & Modem Library\r\n"
"Copyright (c) Victor Chen\r\n"
"http://www.cppfans.com\r\n"
"Email: victor@cppfans.com\r\n";
/***************************************************************************\
* TCommQueue *
\***************************************************************************/
TCommQueue::TCommQueue(long lSize)
{
_BufSize = lSize;
_Head = 0;
_Tail = 0;
_Buffer = NULL;
try
{
fSetBufSize(_BufSize);
}
catch(...)
{
fSetBufSize(0);
}
}
//---------------------------------------------------------------------------
TCommQueue::~TCommQueue()
{
fSetBufSize(0);
}
//---------------------------------------------------------------------------
void TCommQueue::fSetBufSize(long n)
{
Clear(); //clear buffer before resize
if(n<=0)
{
if(_Buffer)
{
free(_Buffer);
_Buffer = NULL;
}
}
else
{
char far *NewBuffer = (char far *)realloc(_Buffer, n);
if(NewBuffer)
{
_Buffer = NewBuffer;
_BufSize = n;
}
if(!NewBuffer)
{
throw EComm32Error(EComm32Error::COMM_NOMEMORY); //内存不够
}
}
}
//---------------------------------------------------------------------------
long TCommQueue::In(const char far *c)
{
if((_Buffer) && (c) && (fGetRemain()>0))
{
_Buffer[_Tail] = *c;
_Tail = (_Tail+1)%_BufSize;
return 1;
}
return 0;
}
//---------------------------------------------------------------------------
long TCommQueue::In(const char far *c, long n)
{
long BytesToIn = 0; // 0 1 2 3 4 5 6 7 8 9 <- address
// ~~~ <- data
if((_Buffer) && (n>0) && (c)) // ....H...T.......... <- pointers
{
long BytesAppend, BytesAhead;
if((BytesToIn=fGetRemain())>n)
BytesToIn=n;
if((BytesAhead=_Tail+BytesToIn-_BufSize)<0)
BytesAhead=0;
BytesAppend=BytesToIn-BytesAhead;
memcpy(_Buffer+_Tail, c , BytesAppend);
memcpy(_Buffer , c+BytesAppend, BytesAhead );
_Tail = (_Tail + BytesToIn) % _BufSize;
}
return BytesToIn;
}
//---------------------------------------------------------------------------
long TCommQueue::Out(char far *c)
{
if((_Buffer) && (c) && (fGetCount()>0))
{
*c = _Buffer[_Head];
_Head = (_Head+1)%_BufSize;
return 1;
}
return 0;
}
//---------------------------------------------------------------------------
long TCommQueue::Out(char far *c, long n)
{
long BytesToOut = 0;
if((_Buffer) && (n>0) && (c))
{
long BytesTail, BytesAhead;
if((BytesToOut=fGetCount())>n)
BytesToOut=n;
if((BytesAhead=_Head+BytesToOut-_BufSize)<0)
BytesAhead=0;
BytesTail=BytesToOut-BytesAhead;
memcpy(c , _Buffer+_Head, BytesTail );
memcpy(c+BytesTail, _Buffer , BytesAhead);
_Head = (_Head + BytesToOut) % _BufSize;
}
return BytesToOut;
}
/***************************************************************************\
* TCommSerialPortInfo *
\***************************************************************************/
__fastcall TCommSerialPortInfo::TCommSerialPortInfo()
{
_bFromSysDrv = false;
_PortList = new TStringList;
Refresh();
}
//---------------------------------------------------------------------------
__fastcall TCommSerialPortInfo::~TCommSerialPortInfo()
{
delete _PortList;
}
//---------------------------------------------------------------------------
void __fastcall TCommSerialPortInfo::Refresh(void)
{
_PortList->Clear();
_bFromSysDrv = false;
ListFromSystem();
if(_PortList->Count<=0)
{
for(int i=1; i<=4; i++)
_PortList->Add(PortName(i));
_bFromSysDrv = false;
}
}
//---------------------------------------------------------------------------
int __fastcall TCommSerialPortInfo::PortNo(AnsiString s)
{
if(s.SubString(1,3).UpperCase()=="COM")
{
int n = atoi(s.SubString(4,s.Length()).c_str());
if(n>0)return n;
}
return 0;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TCommSerialPortInfo::PortName(int iPortNo)
{
AnsiString s;
s.sprintf("COM%d",iPortNo);
return s;
}
//---------------------------------------------------------------------------
void __fastcall TCommSerialPortInfo::ListFromSystem(void)
{
TRegistry *reg=NULL;
TStringList *names=NULL;
AnsiString sPName;
int iPortNo;
try
{
try
{
names = new TStringList;
reg = new TRegistry;
reg->RootKey=HKEY_LOCAL_MACHINE;
reg->OpenKey("HARDWARE\\DEVICEMAP\\SERIALCOMM",false);
reg->GetValueNames(names);
for(int i=0; i<names->Count; i++)
{
try
{
sPName = reg->ReadString(names->Strings[i]);
iPortNo = PortNo(sPName);
if(iPortNo>0)
{
_PortList->Add(PortName(iPortNo));
}
}
catch(Exception &e)
{
//ignore errors
}
}
_PortList->CustomSort(PortListSortCompare);
_bFromSysDrv = true;
}
catch(Exception &e)
{
//ignore errors
}
}
__finally
{
if(reg) delete reg;
if(names) delete names;
}
}
//---------------------------------------------------------------------------
int __fastcall TCommSerialPortInfo::PortListSortCompare(TStringList* lpList, int Index1, int Index2)
{
return PortNo(lpList->Strings[Index1]) - PortNo(lpList->Strings[Index2]);
}
//---------------------------------------------------------------------------
/***************************************************************************\
* TComm32 Threads *
\***************************************************************************/
void TComm32::_ReadThread(void *Param)
{
TComm32 *Comm = (TComm32 *) Param;
Comm->_ReadThreadRunning = 1;
COMSTAT ComStat;
const RecvBufSize = 2048;
char RecvBuf[RecvBufSize];
DWORD dwErrorFlag, dwBytes, BytesToRead, BytesRemain;
OVERLAPPED os;
DWORD dwEvtMask, dwModemStatus;
os.hEvent = CreateEvent(NULL, true, false, NULL);
if(os.hEvent)
{
if(SetCommMask(Comm->Handle, EV_RXCHAR|EV_TXEMPTY|EV_CTS|EV_DSR|EV_RLSD|EV_RXFLAG|EV_RX80FULL|EV_ERR))
{
HANDLE StatusWaits[2] = {Comm->_hKillRead, os.hEvent};
while(Comm->_RunReadThread)
{
dwEvtMask = 0;
if(!WaitCommEvent(Comm->Handle, &dwEvtMask, &os))
{
if(GetLastError() == ERROR_IO_PENDING)
{
if(WaitForMultipleObjects(2, StatusWaits, false, INFINITE) == WAIT_OBJECT_0)
break;
}
}
if(!Comm->_RunReadThread)
break;
if(dwEvtMask & EV_RXCHAR)
{
ClearCommError(Comm->Handle, &dwErrorFlag, &ComStat);
BytesRemain = ComStat.cbInQue;
while(BytesRemain>0)
{
BytesToRead = BytesRemain<RecvBufSize?BytesRemain:RecvBufSize;
if(ReadFile(Comm->Handle, RecvBuf, BytesToRead, &dwBytes, &Comm->_ReadOS))
{
Comm->_InQueue->In(RecvBuf, dwBytes);
BytesRemain-=dwBytes;
}
}
}
if(dwEvtMask & (EV_CTS|EV_DSR|EV_RLSD))
{
if(GetCommModemStatus(Comm->Handle, &dwModemStatus))
{
Comm->_ModemStatus = dwModemStatus;
}
if(dwEvtMask & EV_CTS)
{
if((!Comm->FromHandle) && (Comm->_dcb.fOutxCtsFlow) && (Comm->_ModemStatus & MS_CTS_ON))
dwEvtMask |= EV_TXEMPTY;
}
if(dwEvtMask & EV_RLSD)
{
Comm->_dwDetectingRing = 0;
}
}
if(dwEvtMask & EV_TXEMPTY)
{
if((Comm->_ModemStatus & MS_CTS_ON) || (!Comm->_dcb.fOutxCtsFlow) || (Comm->FromHandle))
{
if(Comm->_InQueue->Count)
dwEvtMask &=~ EV_TXEMPTY;
SetEvent(Comm->_hSyncWrite);
}
}
if(dwEvtMask & EV_ERR)
{
ClearCommError(Comm->Handle, &dwErrorFlag, &ComStat);
}
Comm->CommNotify(dwEvtMask);
}
}
CloseHandle(os.hEvent);
}
Comm->_ReadThreadRunning = 0;
}
//---------------------------------------------------------------------------
void TComm32::_WriteThread(void *Param)
{
TComm32 *Comm = (TComm32 *) Param;
Comm->_WriteThreadRunning = 1;
const SendBufSize = 256;
char SendBuf[SendBufSize];
DWORD BytesSent=0, BytesToSend=0;
COMSTAT ComStat;
DWORD dwErrorFlag, dwBytesWr;
int iSingled;
HANDLE MainWaits[2] = {Comm->_hKillWrite, Comm->_hSyncWrite};
HANDLE OvlWriteWaits[2] = {Comm->_hKillWrite, Comm->_WriteOS.hEvent};
while(Comm->_RunWriteThread)
{
iSingled = WaitForMultipleObjects(2, MainWaits, false, INFINITE);
if((!Comm->_RunWriteThread) || (iSingled==WAIT_OBJECT_0))
break;
ResetEvent(Comm->_hSyncWrite);
if(BytesSent<BytesToSend)
{
if(WriteFile(Comm->Handle, SendBuf+BytesSent, BytesToSend-BytesSent, &dwBytesWr, &Comm->_WriteOS))
{
BytesSent+=dwBytesWr;
}
else if(GetLastError()==ERROR_IO_PENDING)
{
iSingled = WaitForMultipleObjects(2, OvlWriteWaits, false, INFINITE);
if((!Comm->_RunWriteThread) || (iSingled==WAIT_OBJECT_0))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -