CCOM
来源:互联网 发布:网配圈广播剧的软件 编辑:程序博客网 时间:2024/05/17 03:35
#ifndef _COMM_H_
#define _COMM_H_
#include <assert.h>
#include <stdio.h>
#include <windows.h>
#include <process.h>
//送到窗口的消息 WPARAM 端口号
#define ON_COM_RECEIVE WM_USER + 2001
#define ON_COM_CTS WM_USER + 2002
#define ON_COM_DSR WM_USER + 2003
#define ON_COM_RING WM_USER + 2004
#define ON_COM_RLSD WM_USER + 2005
#define ON_COM_BREAK WM_USER + 2006
#define ON_COM_TXEMPTY WM_USER + 2007
#define ON_COM_ERROR WM_USER + 2008
#define ON_COM_SEND WM_USER + 2009
#define ON_COM_SENDED WM_USER + 2010
#define DEFAULT_COM_MASK_EVENT EV_RXCHAR | EV_ERR | EV_CTS | EV_DSR | EV_BREAK | EV_TXEMPTY | EV_RING | EV_RLSD
class CComm
{
public:
CComm(BOOL fAutoBeginThread = TRUE, DWORD dwIOMode = FILE_FLAG_OVERLAPPED,DWORD dwTXBufferSize = 4096,DWORD dwRXBufferSize = 4096)
: _dwIOMode(dwIOMode), _fAutoBeginThread(fAutoBeginThread),_TXBufferSize(dwTXBufferSize),_RXBufferSize(dwRXBufferSize)
{
_RXDataLength = 0;
_TXDataLength = 0;
_TXSendLength = 0;
ASSERT(_TXBufferSize != 0);
ASSERT(_RXBufferSize != 0);
_TXBuffer = new CHAR[_TXBufferSize];
ASSERT(_TXBuffer != NULL);
_RXBuffer = new CHAR[_RXBufferSize];
ASSERT(_RXBuffer != NULL);
Init();
}
virtual ~CComm()
{
Close();
Destroy();
if(_TXBuffer != NULL)
{
delete[] _TXBuffer;
}
if(_RXBuffer != NULL)
{
delete[] _RXBuffer;
}
}
inline BOOL IsOpen()
{
return _hCommHandle != INVALID_HANDLE_VALUE;
}
const TCHAR *GetPortName()
{
return _szCommStr;
}
DCB *GetState()
{
return IsOpen() && ::GetCommState(_hCommHandle, &_DCB) == TRUE ? &_DCB : NULL;
}
BOOL SetState(DCB *pdcb = NULL)
{
return IsOpen() ? ::SetCommState(_hCommHandle, pdcb == NULL ? &_DCB : pdcb) == TRUE : FALSE;
}
BOOL SetState(DWORD dwBaudRate, DWORD dwByteSize = 8, DWORD dwParity = NOPARITY, DWORD dwStopBits = ONESTOPBIT)
{
if(IsOpen())
{
if(::GetCommState(_hCommHandle, &_DCB) != TRUE)
return FALSE;
_DCB.BaudRate = dwBaudRate;
_DCB.ByteSize = (unsigned char)dwByteSize;
_DCB.Parity = (unsigned char)dwParity;
_DCB.StopBits = (unsigned char)dwStopBits;
return ::SetCommState(_hCommHandle, &_DCB) == TRUE;
}
return FALSE;
}
LPCOMMTIMEOUTS GetTimeouts(void)
{
return IsOpen() && ::GetCommTimeouts(_hCommHandle, &_CO) == TRUE ? &_CO : NULL;
}
BOOL SetTimeouts(LPCOMMTIMEOUTS lpCO)
{
return IsOpen() ? ::SetCommTimeouts(_hCommHandle, lpCO) == TRUE : FALSE;
}
BOOL SetBufferSize(DWORD dwInputSize, DWORD dwOutputSize)
{
return IsOpen() ? ::SetupComm(_hCommHandle, dwInputSize, dwOutputSize) == TRUE : FALSE;
}
void ClearInputBuffer()
{
if(IsOpen())
::PurgeComm(_hCommHandle, PURGE_RXABORT | PURGE_RXCLEAR );
}
void ClearOutputBuffer()
{
if(IsOpen())
::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR );
}
inline void SetWnd(HWND hWnd)
{
assert(::IsWindow(hWnd));
_hNotifyWnd = hWnd;
}
inline void SetNotifyNum(DWORD dwNum)
{
_dwNotifyNum = dwNum;
}
inline BOOL IsThreadRunning()
{
return _hThreadHandle != NULL;
}
inline HANDLE GetThread()
{
return _hThreadHandle;
}
void SetMaskEvent(DWORD dwEvent = DEFAULT_COM_MASK_EVENT)
{
_dwMaskEvent = dwEvent;
}
int GetInputSize()
{
COMSTAT Stat;
DWORD dwError;
return ::ClearCommError(_hCommHandle, &dwError, &Stat) == TRUE ? Stat.cbInQue : (DWORD)-1L;
}
BOOL Open(DWORD dwPort)
{
return Open(dwPort, 9600);
}
BOOL Open(DWORD dwPort, DWORD dwBaudRate)
{
if(dwPort < 1 || dwPort > 1024)
return FALSE;
BindCommPort(dwPort);
if(!OpenCommPort())
return FALSE;
if(!SetupPort())
return FALSE;
return SetState(dwBaudRate);
}
BOOL Open(LPCTSTR szPortName, DWORD dwBaudRate)
{
if(szPortName == NULL)
return FALSE;
_tcscpy(_szCommStr,szPortName);
if(!OpenCommPort())
return FALSE;
if(!SetupPort())
return FALSE;
return SetState(dwBaudRate);
}
DWORD Read(LPVOID Buffer, DWORD dwBufferLength, DWORD dwWaitTime = 10)
{
if(!IsOpen())
return 0;
COMSTAT Stat;
DWORD dwError;
if(::ClearCommError(_hCommHandle, &dwError, &Stat) && dwError > 0)
{
::PurgeComm(_hCommHandle, PURGE_RXABORT | PURGE_RXCLEAR);
return 0;
}
if(!Stat.cbInQue) // 缓冲区无数据
return 0;
unsigned long uReadLength = 0;
dwBufferLength = dwBufferLength > Stat.cbInQue ? Stat.cbInQue : dwBufferLength;
if(!::ReadFile(_hCommHandle, Buffer, dwBufferLength, &uReadLength, &_ReadOverlapped))
{
if(::GetLastError() == ERROR_IO_PENDING)
{
WaitForSingleObject(_ReadOverlapped.hEvent, dwWaitTime); // 结束异步I/O
if(!::GetOverlappedResult(_hCommHandle, &_ReadOverlapped, &uReadLength, FALSE))
{
if(::GetLastError() != ERROR_IO_INCOMPLETE)
uReadLength = 0;
}
}
else
uReadLength = 0;
}
return uReadLength;
}
DWORD Write(LPVOID Buffer, DWORD dwLength,DWORD dwWaitTime)
{
if(!IsOpen())
return 0;
DWORD dwError;
if(::ClearCommError(_hCommHandle, &dwError, NULL) && dwError > 0)
::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);
unsigned long uWriteLength = 0;
if(!::WriteFile(_hCommHandle, Buffer, dwLength, &uWriteLength, &_WriteOverlapped))
{
if(::GetLastError() == ERROR_IO_PENDING)
{
WaitForSingleObject(_WriteOverlapped.hEvent, dwWaitTime); // 结束异步I/O
if(!::GetOverlappedResult(_hCommHandle, &_WriteOverlapped, &uWriteLength, FALSE))
{
if(::GetLastError() != ERROR_IO_INCOMPLETE)
uWriteLength = 0;
}
}
else
uWriteLength = 0;
}
return uWriteLength;
}
DWORD Write(LPVOID Buffer, DWORD dwLength)
{
if(!IsOpen())
return 0;
DWORD dwError;
if(::ClearCommError(_hCommHandle, &dwError, NULL) && dwError > 0)
::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);
unsigned long uWriteLength = 0;
if(!::WriteFile(_hCommHandle, Buffer, dwLength, &uWriteLength,&_WriteOverlapped))
if(::GetLastError() != ERROR_IO_PENDING)
uWriteLength = 0;
return uWriteLength;
}
DWORD WriteComm(LPVOID Buffer, DWORD dwLength)
{
DWORD length = 0;
InnerLock lock(this);
length = min(_TXBufferSize,dwLength);
ZeroMemory(_TXBuffer,_TXBufferSize);
memcpy_s(_TXBuffer,_TXBufferSize, Buffer, length);
_TXDataLength = length;
SetEvent(_hEventArray[2]);
return length;
}
DWORD ReadComm(LPVOID Buffer, DWORD dwSize)
{
DWORD length = 0;
InnerLock lock(this);
if(_RXDataLength < _dwNotifyNum)
{
return 0;
}
length = min(dwSize,_RXDataLength);
memcpy_s(Buffer,dwSize,_RXBuffer,length);
if(length < _RXDataLength)
{
memcpy_s(_RXBuffer,_RXBufferSize,_RXBuffer+length,_RXDataLength - length);
_RXDataLength -= length;
}
else
{
_RXDataLength = 0;
}
return length;
}
DWORD ReadSync(LPVOID Buffer, DWORD dwBufferLength)
{
if(!IsOpen())
return 0;
DWORD dwError;
if(::ClearCommError(_hCommHandle, &dwError, NULL) && dwError > 0)
{
::PurgeComm(_hCommHandle, PURGE_RXABORT | PURGE_RXCLEAR);
return 0;
}
DWORD uReadLength = 0;
::ReadFile(_hCommHandle, Buffer, dwBufferLength, &uReadLength, NULL);
return uReadLength;
}
DWORD WriteSync(LPVOID Buffer, DWORD dwBufferLength)
{
if(!IsOpen())
return 0;
DWORD dwError;
if(::ClearCommError(_hCommHandle, &dwError, NULL) && dwError > 0)
::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);
unsigned long uWriteLength = 0;
::WriteFile(_hCommHandle, Buffer, dwBufferLength, &uWriteLength, NULL);
return uWriteLength;
}
virtual void Close()
{
if(IsOpen())
{
PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);
EndThread();
::CloseHandle(_hCommHandle);
_hCommHandle = INVALID_HANDLE_VALUE;
}
}
class InnerLock
{
CComm* ptr;
public:
InnerLock(CComm* p) : ptr(p)
{
ptr->Lock();
}
~InnerLock()
{
ptr->Unlock();
}
};
void Lock()
{
::EnterCriticalSection(&_Mutex);
}
void Unlock()
{
::LeaveCriticalSection(&_Mutex);
}
BOOL SetDTR(BOOL OnOrOff)
{
return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETDTR : CLRDTR) != 0 : FALSE;
}
BOOL SetRTS(BOOL OnOrOff)
{
return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETRTS : CLRRTS) != 0 : FALSE;
}
//
BOOL SetBreak(BOOL OnOrOff)
{
return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETBREAK : CLRBREAK) != 0 : FALSE;
}
BOOL BeginThread()
{
if(!IsThreadRunning())
{
_hThreadHandle = NULL;
DWORD id;
_hThreadHandle = ::CreateThread(NULL, 0, CommThreadProc, this, 0,&id);
return (_hThreadHandle != NULL);
}
return FALSE;
}
inline BOOL SuspendThread()
{
return IsThreadRunning() ? ::SuspendThread(_hThreadHandle) != 0xFFFFFFFF : FALSE;
}
inline BOOL ResumeThread()
{
return IsThreadRunning() ? ::ResumeThread(_hThreadHandle) != 0xFFFFFFFF : FALSE;
}
BOOL EndThread(DWORD dwWaitTime = 100)
{
if(IsThreadRunning())
{
::SetCommMask(_hCommHandle, 0);
::SetEvent(_WaitOverlapped.hEvent);
::SetEvent(_hEventArray[0]);
if(::WaitForSingleObject(_hThreadHandle, dwWaitTime) != WAIT_OBJECT_0)
if(!::TerminateThread(_hThreadHandle, 0))
return FALSE;
::CloseHandle(_hThreadHandle);
::ResetEvent(_WaitOverlapped.hEvent);
_hThreadHandle = NULL;
return TRUE;
}
return FALSE;
}
protected:
DWORD _dwPort; //串口号
HANDLE _hCommHandle; //串口句柄
TCHAR _szCommStr[20]; //保存COM1类似的字符串
DCB _DCB; //波特率,停止位,等
COMMTIMEOUTS _CO;
DWORD _dwIOMode;
OVERLAPPED _ReadOverlapped, _WriteOverlapped;
HANDLE _hEventArray[3];
HANDLE _hThreadHandle;
HWND _hNotifyWnd;
DWORD _dwNotifyNum; //接受多少字节(>=_dwNotifyNum)发送通知消息
DWORD _dwMaskEvent;
BOOL _fRunFlag;
BOOL _fAutoBeginThread;
OVERLAPPED _WaitOverlapped;
CHAR* _TXBuffer;
CHAR* _RXBuffer;
DWORD _TXBufferSize;
DWORD _RXBufferSize;
DWORD _TXDataLength;
DWORD _RXDataLength;
DWORD _TXSendLength;
virtual void Init()
{
memset(_szCommStr, 0, 20);
memset(&_DCB, 0, sizeof(_DCB));
_DCB.DCBlength = sizeof(_DCB);
_hCommHandle = INVALID_HANDLE_VALUE;
memset(&_ReadOverlapped, 0, sizeof(_ReadOverlapped));
memset(&_WriteOverlapped, 0, sizeof(_WriteOverlapped));
_ReadOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
assert(_ReadOverlapped.hEvent != NULL);
_WriteOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
assert(_WriteOverlapped.hEvent != NULL);
_hNotifyWnd = NULL;
_dwNotifyNum = 0;
_dwMaskEvent = DEFAULT_COM_MASK_EVENT;
_hThreadHandle = NULL;
memset(&_WaitOverlapped, 0, sizeof(_WaitOverlapped));
_WaitOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
assert(_WaitOverlapped.hEvent != NULL);
_hEventArray[0] = ::CreateEvent(NULL,FALSE,FALSE,NULL);
_hEventArray[1] = _WaitOverlapped.hEvent;
_hEventArray[2] = ::CreateEvent(NULL,TRUE,FALSE,NULL);
::InitializeCriticalSection(&_Mutex);
}
virtual void Destroy()
{
if(_ReadOverlapped.hEvent != NULL)
CloseHandle(_ReadOverlapped.hEvent);
if(_WriteOverlapped.hEvent != NULL)
CloseHandle(_WriteOverlapped.hEvent);
if(_WaitOverlapped.hEvent != NULL)
CloseHandle(_WaitOverlapped.hEvent);
if(_hEventArray[0] != NULL)
{
CloseHandle(_hEventArray[0]);
}
if(_hEventArray[2] != NULL)
{
CloseHandle(_hEventArray[2]);
}
::DeleteCriticalSection(&_Mutex);
}
void BindCommPort(DWORD dwPort)
{
assert(dwPort >= 1 && dwPort <= 1024);
TCHAR p[5];
_dwPort = dwPort;
_tcscpy(_szCommStr, _T("////.//COM"));
//ltoa(_dwPort, p, 10);
_tcscat(_szCommStr, p);
}
virtual BOOL OpenCommPort()
{
if(IsOpen())
Close();
_hCommHandle = ::CreateFile(
_szCommStr, //将要打开的串口逻辑名
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | _dwIOMode,
NULL
);
if(_fAutoBeginThread)
{
if(IsOpen() && BeginThread())
return TRUE;
else
{
Close(); //创建线程失败
return FALSE;
}
}
return IsOpen();
}
virtual BOOL SetupPort()
{
if(!IsOpen())
return FALSE;
if(!::SetupComm(_hCommHandle, 4096, 4096))
return FALSE;
if(!::GetCommTimeouts(_hCommHandle, &_CO))
return FALSE;
_CO.ReadIntervalTimeout = 0;
_CO.ReadTotalTimeoutMultiplier = 1;
_CO.ReadTotalTimeoutConstant = 1000;
_CO.WriteTotalTimeoutMultiplier = 1;
_CO.WriteTotalTimeoutConstant = 1000;
if(!::SetCommTimeouts(_hCommHandle, &_CO))
return FALSE;
if(!::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ))
return FALSE;
return TRUE;
}
virtual void OnReceive()//EV_RXCHAR
{
if(::IsWindow(_hNotifyWnd))
::SendMessage(_hNotifyWnd, ON_COM_RECEIVE, WPARAM(_dwPort), LPARAM(0));
}
virtual void OnDSR()
{
if(::IsWindow(_hNotifyWnd))
{
DWORD Status;
if(GetCommModemStatus(_hCommHandle, &Status))
::SendMessage(_hNotifyWnd, ON_COM_DSR, WPARAM(_dwPort), LPARAM( (Status & MS_DSR_ON) ? 1 : 0));
}
}
virtual void OnCTS()
{
if(::IsWindow(_hNotifyWnd))
{
DWORD Status;
if(GetCommModemStatus(_hCommHandle, &Status))
::SendMessage(_hNotifyWnd, ON_COM_CTS, WPARAM(_dwPort), LPARAM( (Status & MS_CTS_ON) ? 1 : 0));
}
}
virtual void OnBreak()
{
if(::IsWindow(_hNotifyWnd))
{
::SendMessage(_hNotifyWnd, ON_COM_BREAK , WPARAM(_dwPort), LPARAM(0));
}
}
virtual void OnTXEmpty()
{
if(::IsWindow(_hNotifyWnd))
::SendMessage(_hNotifyWnd, ON_COM_TXEMPTY, WPARAM(_dwPort), LPARAM(0));
}
virtual void OnSended()
{
if(::IsWindow(_hNotifyWnd))
::SendMessage(_hNotifyWnd, ON_COM_SENDED, WPARAM(_TXSendLength), LPARAM(0));
}
virtual void OnError()
{
DWORD dwError;
::ClearCommError(_hCommHandle, &dwError, NULL);
if(::IsWindow(_hNotifyWnd))
::SendMessage(_hNotifyWnd, ON_COM_ERROR, WPARAM(_dwPort), LPARAM(dwError));
}
virtual void OnRing()
{
if(::IsWindow(_hNotifyWnd))
::SendMessage(_hNotifyWnd, ON_COM_RING, WPARAM(_dwPort), LPARAM(0));
}
virtual void OnRLSD()
{
if(::IsWindow(_hNotifyWnd))
::SendMessage(_hNotifyWnd, ON_COM_RLSD, WPARAM(_dwPort), LPARAM(0));
}
virtual DWORD ThreadFunc()
{
if(!IsOpen())
{
return -1;
}
if(!::SetCommMask(_hCommHandle, _dwMaskEvent))
{
return -1;
}
if(!PurgeComm(_hCommHandle, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT))
{
return -1;
}
COMSTAT comstat;
DWORD dwError = 0,dwMask = 0,dwLength = 0;
BOOL bResult = FALSE,bRunFlag = TRUE;
do
{
if(!::WaitCommEvent(_hCommHandle, &dwMask, &_WaitOverlapped))
{
switch (dwError = GetLastError())
{
case ERROR_IO_PENDING:
{
break;
}
default:
{
break;
}
}
}
else
{
bResult = ClearCommError(_hCommHandle, &dwError, &comstat);
if (comstat.cbInQue == 0)
continue;
}
switch(WaitForMultipleObjects(3, _hEventArray, FALSE, INFINITE))
{
//shutdown event.
case WAIT_OBJECT_0:
bRunFlag = FALSE;
break;
//read event.
case WAIT_OBJECT_0+1:
{
switch(dwMask)
{
case EV_RXCHAR :
::ClearCommError(_hCommHandle, &dwError, &comstat);
if(comstat.cbInQue >= _dwNotifyNum)
{
ReceiveData();
if(_RXDataLength >= _dwNotifyNum)
{
OnReceive();
}
}
break;
case EV_CTS :
OnCTS();
break;
case EV_TXEMPTY:
OnTXEmpty();
break;
case EV_DSR :
OnDSR();
break;
case EV_RING :
OnRing();
break;
case EV_RLSD :
OnRLSD();
break;
case EV_BREAK:
OnBreak();
break;
case EV_ERR :
OnError();
break;
}//case
}
break;
//write event.
case WAIT_OBJECT_0+2:
{
SendData();
if(_TXSendLength >= _TXDataLength)
{
OnSended();
}
}
break;
}
}while(bRunFlag);
return 0;
}
void SendString()
{
BOOL bResult = TRUE;
DWORD offset = 0 ,BytesSent = 0;
LARGE_INTEGER m_liPerfStart={0};
LARGE_INTEGER m_liPerfFreq={0};
LARGE_INTEGER liPerfNow={0};
int delayTime = 10;
QueryPerformanceFrequency(&m_liPerfFreq);
QueryPerformanceCounter(&m_liPerfStart);
ResetEvent(_hEventArray[2]);
InnerLock lock(this);
PurgeComm(_hCommHandle, PURGE_TXCLEAR | PURGE_TXABORT);
while(offset<_TXDataLength)
{
// Clear buffer
//PurgeComm(_hCommHandle, PURGE_TXCLEAR | PURGE_TXABORT);
bResult = WriteFile(_hCommHandle, // Handle to COMM Port
_TXBuffer+offset, // Pointer to message buffer in calling function
1, // Length of message to send
&BytesSent, // Where to store the number of bytes sent
&_WriteOverlapped); // Overlapped structure
// deal with any error codes
if (!bResult && GetLastError() == ERROR_IO_PENDING)
{
if(!GetOverlappedResult(_hCommHandle,&_WriteOverlapped,&BytesSent,TRUE))
{
continue;
}
}
offset += BytesSent;
for(;;)
{
QueryPerformanceCounter(&liPerfNow);
double time=(((liPerfNow.QuadPart -
m_liPerfStart.QuadPart)*1000000)/(double)m_liPerfFreq.QuadPart);
if (time >= delayTime)
break;
}
}
_TXSendLength = _TXDataLength;
_TXDataLength = 0;
}
void SendData()
{
BOOL bResult = TRUE;
DWORD BytesSent = 0;
ResetEvent(_hEventArray[2]);
InnerLock lock(this);
// Clear buffer
PurgeComm(_hCommHandle, PURGE_TXCLEAR | PURGE_TXABORT);
bResult = WriteFile(_hCommHandle, // Handle to COMM Port
_TXBuffer, // Pointer to message buffer in calling function
_TXDataLength, // Length of message to send
&BytesSent, // Where to store the number of bytes sent
&_WriteOverlapped); // Overlapped structure
// deal with any error codes
if (!bResult && GetLastError() == ERROR_IO_PENDING)
{
if(!GetOverlappedResult(_hCommHandle,&_WriteOverlapped,&BytesSent,TRUE))
{
_TXSendLength = 0;
}
}
if(BytesSent == _TXDataLength)
{
_TXSendLength = _TXDataLength;
_TXDataLength = 0;
}
}
//
// Character received. Inform the owner
//
void ReceiveData()
{
BOOL bRead = TRUE;
BOOL bResult = TRUE;
DWORD dwError = 0;
DWORD BytesRead = 0,BytesToRead = 0;
COMSTAT comstat;
InnerLock lock(this);
// ClearCommError() will update the COMSTAT structure and
bResult = ClearCommError(_hCommHandle, &dwError, &comstat);
if (comstat.cbInQue == 0)
{
return;
}
BytesToRead = min(comstat.cbInQue,_RXBufferSize);
bResult = ReadFile(_hCommHandle, // Handle to COMM port
_RXBuffer, // RX Buffer Pointer
BytesToRead, // Read one byte
&BytesRead, // Stores number of bytes read
&_ReadOverlapped); // pointer to the m_ov structure
// deal with the error code
if (!bResult && GetLastError() == ERROR_IO_PENDING)
{
if(!GetOverlappedResult(_hCommHandle,&_ReadOverlapped,&BytesRead,TRUE))
{
BytesRead = 0;
}
}
_RXDataLength += BytesRead;
}
private: //the function protected
CComm(const CComm&);
CComm &operator = (const CComm&);
CRITICAL_SECTION _Mutex;
//base function for thread
static DWORD WINAPI CommThreadProc(LPVOID lpPara)
{
return ( (CComm *)lpPara )->ThreadFunc();
}
};
#endif //_COMM_H_
- CCOM
- CCOM改进(串口号大于10)
- 编写一个ASP类的方法
- CSS菜单
- 又加了俩功能-_-!
- WINCE6下基于deviceemulator bsp 包编译kitl的相关操作
- 关于23种设计模式的有趣见解
- CCOM
- ORACLE函数大全
- javascript中访问struts2 ValueStack中的数据
- 如何获取RowState为Deleted状态的数据
- Windows 7 关于锁定程序到任务栏及快捷方式小箭头的问题
- 短小精悍的英语短句
- %=&/?' 加密解密
- R12 APP-OFA-48392 Unable to Get The Concurrent Request Status Using Procedure FND_CONCURRENT.GET_REQUEST_STATUS
- 关于多边形的布尔运算