从串口mfc读取信息

发布于 2024-11-30 02:29:31 字数 103 浏览 0 评论 0原文

我正在尝试编写一个基于 MFC 对话框的应用程序,该应用程序从 PC 的串行 COMM 端口读取信息,然后将一些信息写回到串行 COMM 端口。知道我从哪里开始吗?

提前致谢。

I am trying to write an MFC dialog based application that reads the information from the serial COMM port of your PC and then write some information back to the serial COMM port. Any idea as to where do I start from?

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

枫以 2024-12-07 02:29:31

这有帮助吗? :-)

<块引用>

SerialPort.h

/* /////////////////// Macros / Structs etc ////////////////////////// */

#ifndef __SERIALPORT_H__
#define __SERIALPORT_H__

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <vector>


/* ///////////////////////// Classes /////////////////////////////////////////// */


/* //// Serial port exception class //////////////////////////////////////////// */

void AfxThrowSerialException(DWORD dwError = 0);

class CSerialException : public CException
{
 public:
  /* Constructors / Destructors */
  CSerialException (DWORD dwError);
  ~CSerialException ();

  /* Methods */
#ifdef _DEBUG
  virtual void  Dump(CDumpContext & dc) const;
#endif

  virtual BOOL    GetErrorMessage(LPTSTR lpstrError, UINT nMaxError, PUINT pnHelpContext = NULL);
  CString         GetErrorMessage();

  /* Data members */
  DWORD m_dwError;

 protected:
  DECLARE_DYNAMIC(CSerialException)
};


/* // The actual serial port class ///////////////////////////////////////////// */

class CSerialPort : public CObject
{
 public:
  /* Enums */
  enum FlowControl {
    NoFlowControl,
    CtsRtsFlowControl,
    CtsDtrFlowControl,
    DsrRtsFlowControl,
    DsrDtrFlowControl,
    XonXoffFlowControl
  };

  enum Parity {
    EvenParity,
    MarkParity,
    NoParity,
    OddParity,
    SpaceParity
  };

  enum StopBits {
    OneStopBit,
    OnePointFiveStopBits,
    TwoStopBits
  };

  /* Constructors / Destructors */
  CSerialPort ();
  ~CSerialPort ();

  /* General Methods */
  static std::vector<CString> EnumSerialPorts( void );

  void Open(int nPort, DWORD dwBaud = 9600, Parity parity = NoParity, BYTE dataBits = 8, 
            StopBits stopBits = OneStopBit, FlowControl fc = NoFlowControl, BOOL bOverlapped = FALSE);
  void Open(LPCTSTR szPort, DWORD dwBaud = 9600, Parity parity = NoParity, BYTE dataBits = 8, 
            StopBits stopBits = OneStopBit, FlowControl fc = NoFlowControl, BOOL bOverlapped = FALSE);
  void    Close();
  void    Attach(HANDLE hComm);
  HANDLE  Detach();

  operator HANDLE() const { return m_hComm; }
  BOOL IsOpen() const { return m_hComm != INVALID_HANDLE_VALUE; }
#ifdef _DEBUG
  void CSerialPort::Dump(CDumpContext & dc) const;
#endif


  /* Reading / Writing Methods */
  DWORD         Read(void *lpBuf, DWORD dwCount);
  BOOL          Read(void *lpBuf, DWORD dwCount, OVERLAPPED &overlapped);
  void          ReadEx(void *lpBuf, DWORD dwCount);
  DWORD         Write(const void *lpBuf, DWORD dwCount);
  BOOL          Write(const void *lpBuf, DWORD dwCount, OVERLAPPED &overlapped);
  void          WriteEx(const void *lpBuf, DWORD dwCount);
  void          TransmitChar(char cChar);
  void          GetOverlappedResult(OVERLAPPED & overlapped,
                                    DWORD & dwBytesTransferred,
                                    BOOL bWait);
  void          CancelIo();

  /* Configuration Methods */
  void          GetConfig(COMMCONFIG & config);
  static void   GetDefaultConfig(int nPort, COMMCONFIG & config);
  void          SetConfig(COMMCONFIG & Config);
  static void   SetDefaultConfig(int nPort, COMMCONFIG & config);

  /* Misc RS232 Methods */
  void          ClearBreak();
  void          SetBreak();
  void          ClearError(DWORD & dwErrors);
  void          GetStatus(COMSTAT & stat);
  void          GetState(DCB & dcb);
  void          SetState(DCB & dcb, BOOL bClosePortOnErr = FALSE);
  void          Escape(DWORD dwFunc);
  void          ClearDTR();
  void          ClearRTS();
  void          SetDTR();
  void          SetRTS();
  void          SetXOFF();
  void          SetXON();
  void          GetProperties(COMMPROP & properties);
  void          GetModemStatus(DWORD & dwModemStatus);

  /* Timeouts */
  void          SetTimeouts(const COMMTIMEOUTS& timeouts);
  void          GetTimeouts(COMMTIMEOUTS& timeouts);
  void          Set0Timeout();
  void          Set0WriteTimeout();
  void          Set0ReadTimeout();

  /* Event Methods */
  void          SetMask(DWORD dwMask);
  void          GetMask(DWORD & dwMask);
  void          WaitEvent(DWORD & dwMask);
  void          WaitEvent(DWORD & dwMask, OVERLAPPED & overlapped);

  /* Queue Methods */
  void          Flush();
  void          Purge(DWORD dwFlags);
  void          TerminateOutstandingWrites();
  void          TerminateOutstandingReads();
  void          ClearWriteBuffer();
  void          ClearReadBuffer();
  void          Setup(DWORD dwInQueue, DWORD dwOutQueue);

  /* Overridables */
  virtual void  OnCompletion(DWORD dwErrorCode, DWORD dwCount, LPOVERLAPPED lpOverlapped);

 protected:
  HANDLE      m_hComm;        /* Handle to the comms port */
  BOOL        m_bOverlapped;  /* Is the port open in overlapped IO */

  static void WINAPI  _OnCompletion(DWORD dwErrorCode, DWORD dwCount, LPOVERLAPPED lpOverlapped);

  DECLARE_DYNAMIC(CSerialPort)

 private:
  void OpenComm(LPCTSTR szPort, DWORD dwBaud = 9600, Parity parity = NoParity, BYTE dataBits = 8, 
            StopBits stopBits = OneStopBit, FlowControl fc = NoFlowControl, BOOL bOverlapped = FALSE);
};


#endif /* __SERIALPORT_H__ */

<块引用>

SerialPort.cpp

/* ///////////////////////////////  Includes  ////////////////////////////////// */
#include "stdafx.h"
#include <winspool.h>
#include "serialport.h"
#include "winerror.h"


/* /////////////////////////////// defines ///////////////////////////////////// */

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
  static char THIS_FILE[] = __FILE__;
#endif


/* ////////////////////////////// Implementation /////////////////////////////// */


/* Class which handles CancelIo function which must be constructed at run time
 * since it is not imeplemented on NT 3.51 or Windows 95. To avoid the loader
 * bringing up a message such as "Failed to load due to missing export...", the
 * function is constructed using GetProcAddress. The CSerialPort::CancelIo
 * function then checks to see if the function pointer is NULL and if it is it
 * throws an exception using the error code ERROR_CALL_NOT_IMPLEMENTED which
 * is what 95 would have done if it had implemented a stub for it in the first
 * place !!
 */

class _SERIAL_PORT_DATA
{
 public:
/* Constructors /Destructors */
  _SERIAL_PORT_DATA ();
  ~_SERIAL_PORT_DATA ();

  HINSTANCE  m_hKernel32;
  typedef BOOL ( CANCELIO )( HANDLE );
  typedef CANCELIO    *LPCANCELIO;
  LPCANCELIO m_lpfnCancelIo;
};

_SERIAL_PORT_DATA::_SERIAL_PORT_DATA ()
{
  m_hKernel32    = LoadLibrary( _T("KERNEL32.DLL") );
  VERIFY(m_hKernel32 != NULL);
  m_lpfnCancelIo = (LPCANCELIO)GetProcAddress(m_hKernel32, "CancelIo");
}


_SERIAL_PORT_DATA::~_SERIAL_PORT_DATA ()
{
  FreeLibrary(m_hKernel32);
  m_hKernel32 = NULL;
}


/* The local variable which handle the function pointers */

_SERIAL_PORT_DATA _SerialPortData;


/* //////// Exception handling code */

void AfxThrowSerialException(DWORD dwError /* = 0 */)
{
  if(dwError == 0) {
    dwError = ::GetLastError();
  }
  CSerialException *pException = new CSerialException(dwError);

  TRACE( _T("Warning: throwing CSerialException for error %d\n"), dwError );
  THROW( pException );
}


BOOL CSerialException::GetErrorMessage(LPTSTR pstrError, UINT nMaxError, PUINT pnHelpContext)
{
  ASSERT( pstrError != NULL && AfxIsValidString(pstrError, nMaxError) );

  if(pnHelpContext != NULL) {
    *pnHelpContext = 0;
  }
  LPTSTR lpBuffer;
  BOOL   bRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                              NULL,  m_dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
                              (LPTSTR)&lpBuffer, 0, NULL);

  if(bRet == FALSE) {
    *pstrError = '\0';
  } else {
    lstrcpyn(pstrError, lpBuffer, nMaxError);
    bRet = TRUE;

    LocalFree(lpBuffer);
  }
  return bRet;
} /* GetErrorMessage */


CString CSerialException::GetErrorMessage()
{
  CString rVal;
  LPTSTR  pstrError = rVal.GetBuffer(4096);

  GetErrorMessage(pstrError, 4096, NULL);
  rVal.ReleaseBuffer();
  return rVal;
}


CSerialException::CSerialException (DWORD dwError)
{
  m_dwError = dwError;
}


CSerialException::~CSerialException ()
{}


IMPLEMENT_DYNAMIC(CSerialException, CException)

#ifdef _DEBUG
  void CSerialException::Dump(CDumpContext & dc) const
  {
    CObject::Dump(dc);

    dc << "m_dwError = " << m_dwError;
  }


#endif


/* //////// The actual serial port code */

CSerialPort::CSerialPort ()
{
  m_hComm       = INVALID_HANDLE_VALUE;
  m_bOverlapped = FALSE;
}


CSerialPort::~CSerialPort ()
{
  Close();
}


IMPLEMENT_DYNAMIC(CSerialPort, CObject)

#ifdef _DEBUG
  void CSerialPort::Dump(CDumpContext & dc) const
  {
    CObject::Dump(dc);

    dc << _T("m_hComm = ") << m_hComm << _T("\n");
    dc << _T("m_bOverlapped = ") << m_bOverlapped;
  }


#endif


std::vector<CString> CSerialPort::EnumSerialPorts(void)
{
  /* Clear existing list of COMM ports */
  std::vector<CString> commPortList;

  /* COM ports can be numbered from 1 to 255, loop through all possibilities and add the ones we 
   * find.
   */
  for( UINT i = 1; i < 256; i++ ) {
    //Form the Raw device name
    CString sPort;
    sPort.Format( _T("COM%d"), i );

    COMMCONFIG cc;
    DWORD dwSize = sizeof(cc);
    if( GetDefaultCommConfig(sPort, &cc, &dwSize) != 0 ) {
      commPortList.push_back( (LPCTSTR)sPort );
    }
  }

  return commPortList;
}


void CSerialPort::Open(int nPort, DWORD dwBaud, Parity parity, BYTE dataBits, StopBits stopBits,
                       FlowControl fc, BOOL bOverlapped)
{
  /* Validate our parameters */
  ASSERT(nPort > 0 && nPort <= 255);

  /* Call CreateFile to open up the comms port */
  CString sPort;
  sPort.Format(_T("\\\\.\\COM%d"), nPort);

  OpenComm(sPort, dwBaud, parity, dataBits, stopBits, fc, bOverlapped);
}

void CSerialPort::Open(LPCTSTR szPort, DWORD dwBaud, Parity parity, BYTE dataBits, StopBits stopBits,
                       FlowControl fc, BOOL bOverlapped)
{
  OpenComm(szPort, dwBaud, parity, dataBits, stopBits, fc, bOverlapped);
}

void CSerialPort::OpenComm(LPCTSTR szPort, DWORD dwBaud, Parity parity, BYTE dataBits, StopBits stopbits, 
              FlowControl fc, BOOL bOverlapped)
{
  m_hComm       = CreateFile(szPort, (GENERIC_READ | GENERIC_WRITE), 0, NULL, OPEN_EXISTING,
                             bOverlapped ? FILE_FLAG_OVERLAPPED : 0, NULL);
  if(m_hComm == INVALID_HANDLE_VALUE) {
    TRACE( _T("Failed to open up the comms port\n") );
    AfxThrowSerialException();
  }
  m_bOverlapped = bOverlapped;

  /* Get the current state prior to changing it */
  DCB dcb;
  GetState(dcb);

  /* Setup the baud rate */
  dcb.BaudRate  = dwBaud;

  /* Setup the Parity */
  switch(parity) {
    case EvenParity:
      dcb.Parity = EVENPARITY;  break;

    case MarkParity:
      dcb.Parity = MARKPARITY;  break;

    case NoParity:
      dcb.Parity = NOPARITY;    break;

    case OddParity:
      dcb.Parity = ODDPARITY;   break;

    case SpaceParity:
      dcb.Parity = SPACEPARITY; break;

    default:
      ASSERT(FALSE);            break;
  }

  /* Setup the data bits */
  dcb.ByteSize = dataBits;

  /* Setup the stop bits */
  switch(stopbits) {
    case OneStopBit:
      dcb.StopBits = ONESTOPBIT;   break;

    case OnePointFiveStopBits:
      dcb.StopBits = ONE5STOPBITS; break;

    case TwoStopBits:
      dcb.StopBits = TWOSTOPBITS;  break;

    default:
      ASSERT(FALSE);               break;
  }

  /* Setup the flow control */
  dcb.fDsrSensitivity = FALSE;
  switch(fc) {
    case NoFlowControl:
    {
      dcb.fOutxCtsFlow = FALSE;
      dcb.fOutxDsrFlow = FALSE;
      dcb.fOutX        = FALSE;
      dcb.fInX = FALSE;
      break;
    }

    case CtsRtsFlowControl:
    {
      dcb.fOutxCtsFlow = TRUE;
      dcb.fOutxDsrFlow = FALSE;
      dcb.fRtsControl  = RTS_CONTROL_HANDSHAKE;
      dcb.fOutX        = FALSE;
      dcb.fInX = FALSE;
      break;
    }

    case CtsDtrFlowControl:
    {
      dcb.fOutxCtsFlow = TRUE;
      dcb.fOutxDsrFlow = FALSE;
      dcb.fDtrControl  = DTR_CONTROL_HANDSHAKE;
      dcb.fOutX        = FALSE;
      dcb.fInX = FALSE;
      break;
    }

    case DsrRtsFlowControl:
    {
      dcb.fOutxCtsFlow = FALSE;
      dcb.fOutxDsrFlow = TRUE;
      dcb.fRtsControl  = RTS_CONTROL_HANDSHAKE;
      dcb.fOutX        = FALSE;
      dcb.fInX = FALSE;
      break;
    }

    case DsrDtrFlowControl:
    {
      dcb.fOutxCtsFlow = FALSE;
      dcb.fOutxDsrFlow = TRUE;
      dcb.fDtrControl  = DTR_CONTROL_HANDSHAKE;
      dcb.fOutX        = FALSE;
      dcb.fInX = FALSE;
      break;
    }

    case XonXoffFlowControl:
    {
      dcb.fOutxCtsFlow = FALSE;
      dcb.fOutxDsrFlow = FALSE;
      dcb.fOutX        = TRUE;
      dcb.fInX = TRUE;
      dcb.XonChar      = 0x11;
      dcb.XoffChar     = 0x13;
      dcb.XoffLim      = 100;
      dcb.XonLim       = 100;
      break;
    }

    default:
    {
      ASSERT(FALSE);
      break;
    }
  }

  /* Now that we have all the settings in place, make the changes */
  SetState(dcb);
} /* Open */


void CSerialPort::Close()
{
  if( IsOpen() ) {
    BOOL bSuccess = CloseHandle(m_hComm);
    m_hComm       = INVALID_HANDLE_VALUE;
    if(!bSuccess) {
      TRACE( _T("Failed to close up the comms port, GetLastError:%d\n"), GetLastError() );
    }
    m_bOverlapped = FALSE;
  }
}


void CSerialPort::Attach(HANDLE hComm)
{
  Close();
  m_hComm = hComm;
}


HANDLE CSerialPort::Detach()
{
  HANDLE hrVal = m_hComm;

  m_hComm = INVALID_HANDLE_VALUE;
  return hrVal;
}


DWORD CSerialPort::Read(void *lpBuf, DWORD dwCount)
{
  ASSERT( IsOpen() );
  ASSERT(!m_bOverlapped);

  DWORD dwBytesRead = 0;
  if( !ReadFile(m_hComm, lpBuf, dwCount, &dwBytesRead, NULL) ) {
    TRACE( _T("Failed in call to ReadFile\n") );
    AfxThrowSerialException();
  }
  return dwBytesRead;
}


BOOL CSerialPort::Read(void *lpBuf, DWORD dwCount, OVERLAPPED & overlapped)
{
  ASSERT( IsOpen() );
  ASSERT(m_bOverlapped);
  ASSERT(overlapped.hEvent);

  DWORD dwBytesRead = 0;
  BOOL  bSuccess    = ReadFile(m_hComm, lpBuf, dwCount, &dwBytesRead, &overlapped);
  if(!bSuccess) {
    if(GetLastError() != ERROR_IO_PENDING) {
      TRACE( _T("Failed in call to ReadFile\n") );
      AfxThrowSerialException();
    }
  }
  return bSuccess;
}


DWORD CSerialPort::Write(const void *lpBuf, DWORD dwCount)
{
  ASSERT( IsOpen() );
  ASSERT(!m_bOverlapped);

  DWORD dwBytesWritten = 0;
  if( !WriteFile(m_hComm, lpBuf, dwCount, &dwBytesWritten, NULL) ) {
    TRACE( _T("Failed in call to WriteFile\n") );
    AfxThrowSerialException();
  }
  return dwBytesWritten;
}


BOOL CSerialPort::Write(const void *lpBuf, DWORD dwCount, OVERLAPPED & overlapped)
{
  ASSERT( IsOpen() );
  ASSERT(m_bOverlapped);
  ASSERT(overlapped.hEvent);

  DWORD dwBytesWritten = 0;
  BOOL  bSuccess       = WriteFile(m_hComm, lpBuf, dwCount, &dwBytesWritten, &overlapped);
  if(!bSuccess) {
    if(GetLastError() != ERROR_IO_PENDING) {
      TRACE( _T("Failed in call to WriteFile\n") );
      AfxThrowSerialException();
    }
  }
  return bSuccess;
}


void CSerialPort::GetOverlappedResult(OVERLAPPED & overlapped,
                                      DWORD & dwBytesTransferred,
                                      BOOL bWait)
{
  ASSERT( IsOpen() );
  ASSERT(m_bOverlapped);
  ASSERT(overlapped.hEvent);

  //DWORD dwBytesWritten = 0;
  if( !::GetOverlappedResult(m_hComm, &overlapped, &dwBytesTransferred, bWait) ) {
    if(GetLastError() != ERROR_IO_PENDING) {
      TRACE( _T("Failed in call to GetOverlappedResult\n") );
      AfxThrowSerialException();
    }
  }
}


void CSerialPort::_OnCompletion(DWORD dwErrorCode, DWORD dwCount, LPOVERLAPPED lpOverlapped)
{
  /* Validate our parameters */
  ASSERT(lpOverlapped);

  /* Convert back to the C++ world */
  CSerialPort *pSerialPort = (CSerialPort *)lpOverlapped->hEvent;
  ASSERT( pSerialPort->IsKindOf( RUNTIME_CLASS(CSerialPort) ) );

  /* Call the C++ function */
  pSerialPort->OnCompletion(dwErrorCode, dwCount, lpOverlapped);
}


void CSerialPort::OnCompletion(DWORD /*dwErrorCode*/, DWORD /*dwCount*/, LPOVERLAPPED lpOverlapped)
{
  /* Just free up the memory which was previously allocated for the OVERLAPPED structure */
  delete lpOverlapped;

  /* Your derived classes can do something useful in OnCompletion, but don't forget to
   * call CSerialPort::OnCompletion to ensure the memory is freed up
   */
}


void CSerialPort::CancelIo()
{
  ASSERT( IsOpen() );

  if(_SerialPortData.m_lpfnCancelIo == NULL) {
    TRACE( _T(
            "CancelIo function is not supported on this OS. You need to be running at least NT 4 or Win 98 to use this function\n") );
    AfxThrowSerialException(ERROR_CALL_NOT_IMPLEMENTED);
  }
  if( !::_SerialPortData.m_lpfnCancelIo(m_hComm) ) {
    TRACE( _T("Failed in call to CancelIO\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::WriteEx(const void *lpBuf, DWORD dwCount)
{
  ASSERT( IsOpen() );

  OVERLAPPED *pOverlapped = new OVERLAPPED;
  ZeroMemory( pOverlapped, sizeof(OVERLAPPED) );
  pOverlapped->hEvent = (HANDLE) this;
  if( !WriteFileEx(m_hComm, lpBuf, dwCount, pOverlapped, _OnCompletion) ) {
    delete pOverlapped;
    TRACE( _T("Failed in call to WriteFileEx\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::ReadEx(void *lpBuf, DWORD dwCount)
{
  ASSERT( IsOpen() );

  OVERLAPPED *pOverlapped = new OVERLAPPED;
  ZeroMemory( pOverlapped, sizeof(OVERLAPPED) );
  pOverlapped->hEvent = (HANDLE) this;
  if( !ReadFileEx(m_hComm, lpBuf, dwCount, pOverlapped, _OnCompletion) ) {
    delete pOverlapped;
    TRACE( _T("Failed in call to ReadFileEx\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::TransmitChar(char cChar)
{
  ASSERT( IsOpen() );

  if( !TransmitCommChar(m_hComm, cChar) ) {
    TRACE( _T("Failed in call to TransmitCommChar\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::GetConfig(COMMCONFIG & config)
{
  ASSERT( IsOpen() );

  DWORD dwSize = sizeof(COMMCONFIG);
  if( !GetCommConfig(m_hComm, &config, &dwSize) ) {
    TRACE( _T("Failed in call to GetCommConfig\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::SetConfig(COMMCONFIG & config)
{
  ASSERT( IsOpen() );

  DWORD dwSize = sizeof(COMMCONFIG);
  if( !SetCommConfig(m_hComm, &config, dwSize) ) {
    TRACE( _T("Failed in call to SetCommConfig\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::SetBreak()
{
  ASSERT( IsOpen() );

  if( !SetCommBreak(m_hComm) ) {
    TRACE( _T("Failed in call to SetCommBreak\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::ClearBreak()
{
  ASSERT( IsOpen() );

  if( !ClearCommBreak(m_hComm) ) {
    TRACE( _T("Failed in call to SetCommBreak\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::ClearError(DWORD & dwErrors)
{
  ASSERT( IsOpen() );

  if( !ClearCommError(m_hComm, &dwErrors, NULL) ) {
    TRACE( _T("Failed in call to ClearCommError\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::GetDefaultConfig(int nPort, COMMCONFIG & config)
{
  /* Validate our parameters */
  ASSERT(nPort > 0 && nPort <= 255);

  /* Create the device name as a string */
  CString sPort;
  sPort.Format(_T("COM%d"), nPort);

  DWORD   dwSize = sizeof(COMMCONFIG);
  if( !GetDefaultCommConfig(sPort, &config, &dwSize) ) {
    TRACE( _T("Failed in call to GetDefaultCommConfig\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::SetDefaultConfig(int nPort, COMMCONFIG & config)
{
  /* Validate our parameters */
  ASSERT(nPort > 0 && nPort <= 255);

  /* Create the device name as a string */
  CString sPort;
  sPort.Format(_T("COM%d"), nPort);

  DWORD   dwSize = sizeof(COMMCONFIG);
  if( !SetDefaultCommConfig(sPort, &config, dwSize) ) {
    TRACE( _T("Failed in call to GetDefaultCommConfig\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::GetStatus(COMSTAT & stat)
{
  ASSERT( IsOpen() );

  DWORD dwErrors;
  if( !ClearCommError(m_hComm, &dwErrors, &stat) ) {
    TRACE( _T("Failed in call to ClearCommError\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::GetState(DCB& dcb)
{
  ASSERT( IsOpen() );

  if( !GetCommState(m_hComm, &dcb) ) {
    TRACE( _T("Failed in call to GetCommState\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::SetState(DCB& dcb, BOOL bClosePortOnErr)
{
  ASSERT( IsOpen() );

  if( !SetCommState(m_hComm, &dcb) ) {
    if( bClosePortOnErr == TRUE ) {
      Close();
    }
    TRACE( _T("Failed in call to SetCommState\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::Escape(DWORD dwFunc)
{
  ASSERT( IsOpen() );

  if( !EscapeCommFunction(m_hComm, dwFunc) ) {
    TRACE( _T("Failed in call to EscapeCommFunction\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::ClearDTR()
{
  Escape(CLRDTR);
}


void CSerialPort::ClearRTS()
{
  Escape(CLRRTS);
}


void CSerialPort::SetDTR()
{
  Escape(SETDTR);
}


void CSerialPort::SetRTS()
{
  Escape(SETRTS);
}


void CSerialPort::SetXOFF()
{
  Escape(SETXOFF);
}


void CSerialPort::SetXON()
{
  Escape(SETXON);
}


void CSerialPort::GetProperties(COMMPROP & properties)
{
  ASSERT( IsOpen() );

  if( !GetCommProperties(m_hComm, &properties) ) {
    TRACE( _T("Failed in call to GetCommProperties\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::GetModemStatus(DWORD & dwModemStatus)
{
  ASSERT( IsOpen() );

  if( !GetCommModemStatus(m_hComm, &dwModemStatus) ) {
    TRACE( _T("Failed in call to GetCommModemStatus\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::SetMask(DWORD dwMask)
{
  ASSERT( IsOpen() );

  if( !SetCommMask(m_hComm, dwMask) ) {
    TRACE( _T("Failed in call to SetCommMask\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::GetMask(DWORD & dwMask)
{
  ASSERT( IsOpen() );

  if( !GetCommMask(m_hComm, &dwMask) ) {
    TRACE( _T("Failed in call to GetCommMask\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::Flush()
{
  ASSERT( IsOpen() );

  if( !FlushFileBuffers(m_hComm) ) {
    TRACE( _T("Failed in call to FlushFileBuffers\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::Purge(DWORD dwFlags)
{
  ASSERT( IsOpen() );

  if( !PurgeComm(m_hComm, dwFlags) ) {
    TRACE( _T("Failed in call to PurgeComm\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::TerminateOutstandingWrites()
{
  Purge(PURGE_TXABORT);
}


void CSerialPort::TerminateOutstandingReads()
{
  Purge(PURGE_RXABORT);
}


void CSerialPort::ClearWriteBuffer()
{
  Purge(PURGE_TXCLEAR);
}


void CSerialPort::ClearReadBuffer()
{
  Purge(PURGE_RXCLEAR);
}


void CSerialPort::Setup(DWORD dwInQueue, DWORD dwOutQueue)
{
  ASSERT( IsOpen() );

  if( !SetupComm(m_hComm, dwInQueue, dwOutQueue) ) {
    TRACE( _T("Failed in call to SetupComm\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::SetTimeouts(const COMMTIMEOUTS& timeouts)
{
  ASSERT( IsOpen() );

  if( !SetCommTimeouts(m_hComm, (LPCOMMTIMEOUTS)&timeouts) ) {
    TRACE( _T("Failed in call to SetCommTimeouts\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::GetTimeouts(COMMTIMEOUTS & timeouts)
{
  ASSERT( IsOpen() );

  if( !GetCommTimeouts(m_hComm, &timeouts) ) {
    TRACE( _T("Failed in call to GetCommTimeouts\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::Set0Timeout()
{
  COMMTIMEOUTS Timeouts;

  ZeroMemory( &Timeouts, sizeof(COMMTIMEOUTS) );
  Timeouts.ReadIntervalTimeout         = MAXDWORD;
  Timeouts.ReadTotalTimeoutMultiplier  = 0;
  Timeouts.ReadTotalTimeoutConstant    = 0;
  Timeouts.WriteTotalTimeoutMultiplier = 0;
  Timeouts.WriteTotalTimeoutConstant   = 0;
  SetTimeouts(Timeouts);
}


void CSerialPort::Set0WriteTimeout()
{
  COMMTIMEOUTS Timeouts;

  GetTimeouts(Timeouts);
  Timeouts.WriteTotalTimeoutMultiplier = 0;
  Timeouts.WriteTotalTimeoutConstant   = 0;
  SetTimeouts(Timeouts);
}


void CSerialPort::Set0ReadTimeout()
{
  COMMTIMEOUTS Timeouts;

  GetTimeouts(Timeouts);
  Timeouts.ReadIntervalTimeout        = MAXDWORD;
  Timeouts.ReadTotalTimeoutMultiplier = 0;
  Timeouts.ReadTotalTimeoutConstant   = 0;
  SetTimeouts(Timeouts);
}


void CSerialPort::WaitEvent(DWORD & dwMask)
{
  ASSERT( IsOpen() );
  ASSERT(!m_bOverlapped);

  if( !WaitCommEvent(m_hComm, &dwMask, NULL) ) {
    TRACE( _T("Failed in call to WaitCommEvent\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::WaitEvent(DWORD & dwMask, OVERLAPPED & overlapped)
{
  ASSERT( IsOpen() );
  ASSERT(m_bOverlapped);
  ASSERT(overlapped.hEvent);

  if( !WaitCommEvent(m_hComm, &dwMask, &overlapped) ) {
    if(GetLastError() != ERROR_IO_PENDING) {
      TRACE( _T("Failed in call to WaitCommEvent\n") );
      AfxThrowSerialException();
    }
  }
}

Does this help? :-)

SerialPort.h

/* /////////////////// Macros / Structs etc ////////////////////////// */

#ifndef __SERIALPORT_H__
#define __SERIALPORT_H__

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <vector>


/* ///////////////////////// Classes /////////////////////////////////////////// */


/* //// Serial port exception class //////////////////////////////////////////// */

void AfxThrowSerialException(DWORD dwError = 0);

class CSerialException : public CException
{
 public:
  /* Constructors / Destructors */
  CSerialException (DWORD dwError);
  ~CSerialException ();

  /* Methods */
#ifdef _DEBUG
  virtual void  Dump(CDumpContext & dc) const;
#endif

  virtual BOOL    GetErrorMessage(LPTSTR lpstrError, UINT nMaxError, PUINT pnHelpContext = NULL);
  CString         GetErrorMessage();

  /* Data members */
  DWORD m_dwError;

 protected:
  DECLARE_DYNAMIC(CSerialException)
};


/* // The actual serial port class ///////////////////////////////////////////// */

class CSerialPort : public CObject
{
 public:
  /* Enums */
  enum FlowControl {
    NoFlowControl,
    CtsRtsFlowControl,
    CtsDtrFlowControl,
    DsrRtsFlowControl,
    DsrDtrFlowControl,
    XonXoffFlowControl
  };

  enum Parity {
    EvenParity,
    MarkParity,
    NoParity,
    OddParity,
    SpaceParity
  };

  enum StopBits {
    OneStopBit,
    OnePointFiveStopBits,
    TwoStopBits
  };

  /* Constructors / Destructors */
  CSerialPort ();
  ~CSerialPort ();

  /* General Methods */
  static std::vector<CString> EnumSerialPorts( void );

  void Open(int nPort, DWORD dwBaud = 9600, Parity parity = NoParity, BYTE dataBits = 8, 
            StopBits stopBits = OneStopBit, FlowControl fc = NoFlowControl, BOOL bOverlapped = FALSE);
  void Open(LPCTSTR szPort, DWORD dwBaud = 9600, Parity parity = NoParity, BYTE dataBits = 8, 
            StopBits stopBits = OneStopBit, FlowControl fc = NoFlowControl, BOOL bOverlapped = FALSE);
  void    Close();
  void    Attach(HANDLE hComm);
  HANDLE  Detach();

  operator HANDLE() const { return m_hComm; }
  BOOL IsOpen() const { return m_hComm != INVALID_HANDLE_VALUE; }
#ifdef _DEBUG
  void CSerialPort::Dump(CDumpContext & dc) const;
#endif


  /* Reading / Writing Methods */
  DWORD         Read(void *lpBuf, DWORD dwCount);
  BOOL          Read(void *lpBuf, DWORD dwCount, OVERLAPPED &overlapped);
  void          ReadEx(void *lpBuf, DWORD dwCount);
  DWORD         Write(const void *lpBuf, DWORD dwCount);
  BOOL          Write(const void *lpBuf, DWORD dwCount, OVERLAPPED &overlapped);
  void          WriteEx(const void *lpBuf, DWORD dwCount);
  void          TransmitChar(char cChar);
  void          GetOverlappedResult(OVERLAPPED & overlapped,
                                    DWORD & dwBytesTransferred,
                                    BOOL bWait);
  void          CancelIo();

  /* Configuration Methods */
  void          GetConfig(COMMCONFIG & config);
  static void   GetDefaultConfig(int nPort, COMMCONFIG & config);
  void          SetConfig(COMMCONFIG & Config);
  static void   SetDefaultConfig(int nPort, COMMCONFIG & config);

  /* Misc RS232 Methods */
  void          ClearBreak();
  void          SetBreak();
  void          ClearError(DWORD & dwErrors);
  void          GetStatus(COMSTAT & stat);
  void          GetState(DCB & dcb);
  void          SetState(DCB & dcb, BOOL bClosePortOnErr = FALSE);
  void          Escape(DWORD dwFunc);
  void          ClearDTR();
  void          ClearRTS();
  void          SetDTR();
  void          SetRTS();
  void          SetXOFF();
  void          SetXON();
  void          GetProperties(COMMPROP & properties);
  void          GetModemStatus(DWORD & dwModemStatus);

  /* Timeouts */
  void          SetTimeouts(const COMMTIMEOUTS& timeouts);
  void          GetTimeouts(COMMTIMEOUTS& timeouts);
  void          Set0Timeout();
  void          Set0WriteTimeout();
  void          Set0ReadTimeout();

  /* Event Methods */
  void          SetMask(DWORD dwMask);
  void          GetMask(DWORD & dwMask);
  void          WaitEvent(DWORD & dwMask);
  void          WaitEvent(DWORD & dwMask, OVERLAPPED & overlapped);

  /* Queue Methods */
  void          Flush();
  void          Purge(DWORD dwFlags);
  void          TerminateOutstandingWrites();
  void          TerminateOutstandingReads();
  void          ClearWriteBuffer();
  void          ClearReadBuffer();
  void          Setup(DWORD dwInQueue, DWORD dwOutQueue);

  /* Overridables */
  virtual void  OnCompletion(DWORD dwErrorCode, DWORD dwCount, LPOVERLAPPED lpOverlapped);

 protected:
  HANDLE      m_hComm;        /* Handle to the comms port */
  BOOL        m_bOverlapped;  /* Is the port open in overlapped IO */

  static void WINAPI  _OnCompletion(DWORD dwErrorCode, DWORD dwCount, LPOVERLAPPED lpOverlapped);

  DECLARE_DYNAMIC(CSerialPort)

 private:
  void OpenComm(LPCTSTR szPort, DWORD dwBaud = 9600, Parity parity = NoParity, BYTE dataBits = 8, 
            StopBits stopBits = OneStopBit, FlowControl fc = NoFlowControl, BOOL bOverlapped = FALSE);
};


#endif /* __SERIALPORT_H__ */

SerialPort.cpp

/* ///////////////////////////////  Includes  ////////////////////////////////// */
#include "stdafx.h"
#include <winspool.h>
#include "serialport.h"
#include "winerror.h"


/* /////////////////////////////// defines ///////////////////////////////////// */

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
  static char THIS_FILE[] = __FILE__;
#endif


/* ////////////////////////////// Implementation /////////////////////////////// */


/* Class which handles CancelIo function which must be constructed at run time
 * since it is not imeplemented on NT 3.51 or Windows 95. To avoid the loader
 * bringing up a message such as "Failed to load due to missing export...", the
 * function is constructed using GetProcAddress. The CSerialPort::CancelIo
 * function then checks to see if the function pointer is NULL and if it is it
 * throws an exception using the error code ERROR_CALL_NOT_IMPLEMENTED which
 * is what 95 would have done if it had implemented a stub for it in the first
 * place !!
 */

class _SERIAL_PORT_DATA
{
 public:
/* Constructors /Destructors */
  _SERIAL_PORT_DATA ();
  ~_SERIAL_PORT_DATA ();

  HINSTANCE  m_hKernel32;
  typedef BOOL ( CANCELIO )( HANDLE );
  typedef CANCELIO    *LPCANCELIO;
  LPCANCELIO m_lpfnCancelIo;
};

_SERIAL_PORT_DATA::_SERIAL_PORT_DATA ()
{
  m_hKernel32    = LoadLibrary( _T("KERNEL32.DLL") );
  VERIFY(m_hKernel32 != NULL);
  m_lpfnCancelIo = (LPCANCELIO)GetProcAddress(m_hKernel32, "CancelIo");
}


_SERIAL_PORT_DATA::~_SERIAL_PORT_DATA ()
{
  FreeLibrary(m_hKernel32);
  m_hKernel32 = NULL;
}


/* The local variable which handle the function pointers */

_SERIAL_PORT_DATA _SerialPortData;


/* //////// Exception handling code */

void AfxThrowSerialException(DWORD dwError /* = 0 */)
{
  if(dwError == 0) {
    dwError = ::GetLastError();
  }
  CSerialException *pException = new CSerialException(dwError);

  TRACE( _T("Warning: throwing CSerialException for error %d\n"), dwError );
  THROW( pException );
}


BOOL CSerialException::GetErrorMessage(LPTSTR pstrError, UINT nMaxError, PUINT pnHelpContext)
{
  ASSERT( pstrError != NULL && AfxIsValidString(pstrError, nMaxError) );

  if(pnHelpContext != NULL) {
    *pnHelpContext = 0;
  }
  LPTSTR lpBuffer;
  BOOL   bRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                              NULL,  m_dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
                              (LPTSTR)&lpBuffer, 0, NULL);

  if(bRet == FALSE) {
    *pstrError = '\0';
  } else {
    lstrcpyn(pstrError, lpBuffer, nMaxError);
    bRet = TRUE;

    LocalFree(lpBuffer);
  }
  return bRet;
} /* GetErrorMessage */


CString CSerialException::GetErrorMessage()
{
  CString rVal;
  LPTSTR  pstrError = rVal.GetBuffer(4096);

  GetErrorMessage(pstrError, 4096, NULL);
  rVal.ReleaseBuffer();
  return rVal;
}


CSerialException::CSerialException (DWORD dwError)
{
  m_dwError = dwError;
}


CSerialException::~CSerialException ()
{}


IMPLEMENT_DYNAMIC(CSerialException, CException)

#ifdef _DEBUG
  void CSerialException::Dump(CDumpContext & dc) const
  {
    CObject::Dump(dc);

    dc << "m_dwError = " << m_dwError;
  }


#endif


/* //////// The actual serial port code */

CSerialPort::CSerialPort ()
{
  m_hComm       = INVALID_HANDLE_VALUE;
  m_bOverlapped = FALSE;
}


CSerialPort::~CSerialPort ()
{
  Close();
}


IMPLEMENT_DYNAMIC(CSerialPort, CObject)

#ifdef _DEBUG
  void CSerialPort::Dump(CDumpContext & dc) const
  {
    CObject::Dump(dc);

    dc << _T("m_hComm = ") << m_hComm << _T("\n");
    dc << _T("m_bOverlapped = ") << m_bOverlapped;
  }


#endif


std::vector<CString> CSerialPort::EnumSerialPorts(void)
{
  /* Clear existing list of COMM ports */
  std::vector<CString> commPortList;

  /* COM ports can be numbered from 1 to 255, loop through all possibilities and add the ones we 
   * find.
   */
  for( UINT i = 1; i < 256; i++ ) {
    //Form the Raw device name
    CString sPort;
    sPort.Format( _T("COM%d"), i );

    COMMCONFIG cc;
    DWORD dwSize = sizeof(cc);
    if( GetDefaultCommConfig(sPort, &cc, &dwSize) != 0 ) {
      commPortList.push_back( (LPCTSTR)sPort );
    }
  }

  return commPortList;
}


void CSerialPort::Open(int nPort, DWORD dwBaud, Parity parity, BYTE dataBits, StopBits stopBits,
                       FlowControl fc, BOOL bOverlapped)
{
  /* Validate our parameters */
  ASSERT(nPort > 0 && nPort <= 255);

  /* Call CreateFile to open up the comms port */
  CString sPort;
  sPort.Format(_T("\\\\.\\COM%d"), nPort);

  OpenComm(sPort, dwBaud, parity, dataBits, stopBits, fc, bOverlapped);
}

void CSerialPort::Open(LPCTSTR szPort, DWORD dwBaud, Parity parity, BYTE dataBits, StopBits stopBits,
                       FlowControl fc, BOOL bOverlapped)
{
  OpenComm(szPort, dwBaud, parity, dataBits, stopBits, fc, bOverlapped);
}

void CSerialPort::OpenComm(LPCTSTR szPort, DWORD dwBaud, Parity parity, BYTE dataBits, StopBits stopbits, 
              FlowControl fc, BOOL bOverlapped)
{
  m_hComm       = CreateFile(szPort, (GENERIC_READ | GENERIC_WRITE), 0, NULL, OPEN_EXISTING,
                             bOverlapped ? FILE_FLAG_OVERLAPPED : 0, NULL);
  if(m_hComm == INVALID_HANDLE_VALUE) {
    TRACE( _T("Failed to open up the comms port\n") );
    AfxThrowSerialException();
  }
  m_bOverlapped = bOverlapped;

  /* Get the current state prior to changing it */
  DCB dcb;
  GetState(dcb);

  /* Setup the baud rate */
  dcb.BaudRate  = dwBaud;

  /* Setup the Parity */
  switch(parity) {
    case EvenParity:
      dcb.Parity = EVENPARITY;  break;

    case MarkParity:
      dcb.Parity = MARKPARITY;  break;

    case NoParity:
      dcb.Parity = NOPARITY;    break;

    case OddParity:
      dcb.Parity = ODDPARITY;   break;

    case SpaceParity:
      dcb.Parity = SPACEPARITY; break;

    default:
      ASSERT(FALSE);            break;
  }

  /* Setup the data bits */
  dcb.ByteSize = dataBits;

  /* Setup the stop bits */
  switch(stopbits) {
    case OneStopBit:
      dcb.StopBits = ONESTOPBIT;   break;

    case OnePointFiveStopBits:
      dcb.StopBits = ONE5STOPBITS; break;

    case TwoStopBits:
      dcb.StopBits = TWOSTOPBITS;  break;

    default:
      ASSERT(FALSE);               break;
  }

  /* Setup the flow control */
  dcb.fDsrSensitivity = FALSE;
  switch(fc) {
    case NoFlowControl:
    {
      dcb.fOutxCtsFlow = FALSE;
      dcb.fOutxDsrFlow = FALSE;
      dcb.fOutX        = FALSE;
      dcb.fInX = FALSE;
      break;
    }

    case CtsRtsFlowControl:
    {
      dcb.fOutxCtsFlow = TRUE;
      dcb.fOutxDsrFlow = FALSE;
      dcb.fRtsControl  = RTS_CONTROL_HANDSHAKE;
      dcb.fOutX        = FALSE;
      dcb.fInX = FALSE;
      break;
    }

    case CtsDtrFlowControl:
    {
      dcb.fOutxCtsFlow = TRUE;
      dcb.fOutxDsrFlow = FALSE;
      dcb.fDtrControl  = DTR_CONTROL_HANDSHAKE;
      dcb.fOutX        = FALSE;
      dcb.fInX = FALSE;
      break;
    }

    case DsrRtsFlowControl:
    {
      dcb.fOutxCtsFlow = FALSE;
      dcb.fOutxDsrFlow = TRUE;
      dcb.fRtsControl  = RTS_CONTROL_HANDSHAKE;
      dcb.fOutX        = FALSE;
      dcb.fInX = FALSE;
      break;
    }

    case DsrDtrFlowControl:
    {
      dcb.fOutxCtsFlow = FALSE;
      dcb.fOutxDsrFlow = TRUE;
      dcb.fDtrControl  = DTR_CONTROL_HANDSHAKE;
      dcb.fOutX        = FALSE;
      dcb.fInX = FALSE;
      break;
    }

    case XonXoffFlowControl:
    {
      dcb.fOutxCtsFlow = FALSE;
      dcb.fOutxDsrFlow = FALSE;
      dcb.fOutX        = TRUE;
      dcb.fInX = TRUE;
      dcb.XonChar      = 0x11;
      dcb.XoffChar     = 0x13;
      dcb.XoffLim      = 100;
      dcb.XonLim       = 100;
      break;
    }

    default:
    {
      ASSERT(FALSE);
      break;
    }
  }

  /* Now that we have all the settings in place, make the changes */
  SetState(dcb);
} /* Open */


void CSerialPort::Close()
{
  if( IsOpen() ) {
    BOOL bSuccess = CloseHandle(m_hComm);
    m_hComm       = INVALID_HANDLE_VALUE;
    if(!bSuccess) {
      TRACE( _T("Failed to close up the comms port, GetLastError:%d\n"), GetLastError() );
    }
    m_bOverlapped = FALSE;
  }
}


void CSerialPort::Attach(HANDLE hComm)
{
  Close();
  m_hComm = hComm;
}


HANDLE CSerialPort::Detach()
{
  HANDLE hrVal = m_hComm;

  m_hComm = INVALID_HANDLE_VALUE;
  return hrVal;
}


DWORD CSerialPort::Read(void *lpBuf, DWORD dwCount)
{
  ASSERT( IsOpen() );
  ASSERT(!m_bOverlapped);

  DWORD dwBytesRead = 0;
  if( !ReadFile(m_hComm, lpBuf, dwCount, &dwBytesRead, NULL) ) {
    TRACE( _T("Failed in call to ReadFile\n") );
    AfxThrowSerialException();
  }
  return dwBytesRead;
}


BOOL CSerialPort::Read(void *lpBuf, DWORD dwCount, OVERLAPPED & overlapped)
{
  ASSERT( IsOpen() );
  ASSERT(m_bOverlapped);
  ASSERT(overlapped.hEvent);

  DWORD dwBytesRead = 0;
  BOOL  bSuccess    = ReadFile(m_hComm, lpBuf, dwCount, &dwBytesRead, &overlapped);
  if(!bSuccess) {
    if(GetLastError() != ERROR_IO_PENDING) {
      TRACE( _T("Failed in call to ReadFile\n") );
      AfxThrowSerialException();
    }
  }
  return bSuccess;
}


DWORD CSerialPort::Write(const void *lpBuf, DWORD dwCount)
{
  ASSERT( IsOpen() );
  ASSERT(!m_bOverlapped);

  DWORD dwBytesWritten = 0;
  if( !WriteFile(m_hComm, lpBuf, dwCount, &dwBytesWritten, NULL) ) {
    TRACE( _T("Failed in call to WriteFile\n") );
    AfxThrowSerialException();
  }
  return dwBytesWritten;
}


BOOL CSerialPort::Write(const void *lpBuf, DWORD dwCount, OVERLAPPED & overlapped)
{
  ASSERT( IsOpen() );
  ASSERT(m_bOverlapped);
  ASSERT(overlapped.hEvent);

  DWORD dwBytesWritten = 0;
  BOOL  bSuccess       = WriteFile(m_hComm, lpBuf, dwCount, &dwBytesWritten, &overlapped);
  if(!bSuccess) {
    if(GetLastError() != ERROR_IO_PENDING) {
      TRACE( _T("Failed in call to WriteFile\n") );
      AfxThrowSerialException();
    }
  }
  return bSuccess;
}


void CSerialPort::GetOverlappedResult(OVERLAPPED & overlapped,
                                      DWORD & dwBytesTransferred,
                                      BOOL bWait)
{
  ASSERT( IsOpen() );
  ASSERT(m_bOverlapped);
  ASSERT(overlapped.hEvent);

  //DWORD dwBytesWritten = 0;
  if( !::GetOverlappedResult(m_hComm, &overlapped, &dwBytesTransferred, bWait) ) {
    if(GetLastError() != ERROR_IO_PENDING) {
      TRACE( _T("Failed in call to GetOverlappedResult\n") );
      AfxThrowSerialException();
    }
  }
}


void CSerialPort::_OnCompletion(DWORD dwErrorCode, DWORD dwCount, LPOVERLAPPED lpOverlapped)
{
  /* Validate our parameters */
  ASSERT(lpOverlapped);

  /* Convert back to the C++ world */
  CSerialPort *pSerialPort = (CSerialPort *)lpOverlapped->hEvent;
  ASSERT( pSerialPort->IsKindOf( RUNTIME_CLASS(CSerialPort) ) );

  /* Call the C++ function */
  pSerialPort->OnCompletion(dwErrorCode, dwCount, lpOverlapped);
}


void CSerialPort::OnCompletion(DWORD /*dwErrorCode*/, DWORD /*dwCount*/, LPOVERLAPPED lpOverlapped)
{
  /* Just free up the memory which was previously allocated for the OVERLAPPED structure */
  delete lpOverlapped;

  /* Your derived classes can do something useful in OnCompletion, but don't forget to
   * call CSerialPort::OnCompletion to ensure the memory is freed up
   */
}


void CSerialPort::CancelIo()
{
  ASSERT( IsOpen() );

  if(_SerialPortData.m_lpfnCancelIo == NULL) {
    TRACE( _T(
            "CancelIo function is not supported on this OS. You need to be running at least NT 4 or Win 98 to use this function\n") );
    AfxThrowSerialException(ERROR_CALL_NOT_IMPLEMENTED);
  }
  if( !::_SerialPortData.m_lpfnCancelIo(m_hComm) ) {
    TRACE( _T("Failed in call to CancelIO\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::WriteEx(const void *lpBuf, DWORD dwCount)
{
  ASSERT( IsOpen() );

  OVERLAPPED *pOverlapped = new OVERLAPPED;
  ZeroMemory( pOverlapped, sizeof(OVERLAPPED) );
  pOverlapped->hEvent = (HANDLE) this;
  if( !WriteFileEx(m_hComm, lpBuf, dwCount, pOverlapped, _OnCompletion) ) {
    delete pOverlapped;
    TRACE( _T("Failed in call to WriteFileEx\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::ReadEx(void *lpBuf, DWORD dwCount)
{
  ASSERT( IsOpen() );

  OVERLAPPED *pOverlapped = new OVERLAPPED;
  ZeroMemory( pOverlapped, sizeof(OVERLAPPED) );
  pOverlapped->hEvent = (HANDLE) this;
  if( !ReadFileEx(m_hComm, lpBuf, dwCount, pOverlapped, _OnCompletion) ) {
    delete pOverlapped;
    TRACE( _T("Failed in call to ReadFileEx\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::TransmitChar(char cChar)
{
  ASSERT( IsOpen() );

  if( !TransmitCommChar(m_hComm, cChar) ) {
    TRACE( _T("Failed in call to TransmitCommChar\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::GetConfig(COMMCONFIG & config)
{
  ASSERT( IsOpen() );

  DWORD dwSize = sizeof(COMMCONFIG);
  if( !GetCommConfig(m_hComm, &config, &dwSize) ) {
    TRACE( _T("Failed in call to GetCommConfig\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::SetConfig(COMMCONFIG & config)
{
  ASSERT( IsOpen() );

  DWORD dwSize = sizeof(COMMCONFIG);
  if( !SetCommConfig(m_hComm, &config, dwSize) ) {
    TRACE( _T("Failed in call to SetCommConfig\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::SetBreak()
{
  ASSERT( IsOpen() );

  if( !SetCommBreak(m_hComm) ) {
    TRACE( _T("Failed in call to SetCommBreak\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::ClearBreak()
{
  ASSERT( IsOpen() );

  if( !ClearCommBreak(m_hComm) ) {
    TRACE( _T("Failed in call to SetCommBreak\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::ClearError(DWORD & dwErrors)
{
  ASSERT( IsOpen() );

  if( !ClearCommError(m_hComm, &dwErrors, NULL) ) {
    TRACE( _T("Failed in call to ClearCommError\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::GetDefaultConfig(int nPort, COMMCONFIG & config)
{
  /* Validate our parameters */
  ASSERT(nPort > 0 && nPort <= 255);

  /* Create the device name as a string */
  CString sPort;
  sPort.Format(_T("COM%d"), nPort);

  DWORD   dwSize = sizeof(COMMCONFIG);
  if( !GetDefaultCommConfig(sPort, &config, &dwSize) ) {
    TRACE( _T("Failed in call to GetDefaultCommConfig\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::SetDefaultConfig(int nPort, COMMCONFIG & config)
{
  /* Validate our parameters */
  ASSERT(nPort > 0 && nPort <= 255);

  /* Create the device name as a string */
  CString sPort;
  sPort.Format(_T("COM%d"), nPort);

  DWORD   dwSize = sizeof(COMMCONFIG);
  if( !SetDefaultCommConfig(sPort, &config, dwSize) ) {
    TRACE( _T("Failed in call to GetDefaultCommConfig\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::GetStatus(COMSTAT & stat)
{
  ASSERT( IsOpen() );

  DWORD dwErrors;
  if( !ClearCommError(m_hComm, &dwErrors, &stat) ) {
    TRACE( _T("Failed in call to ClearCommError\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::GetState(DCB& dcb)
{
  ASSERT( IsOpen() );

  if( !GetCommState(m_hComm, &dcb) ) {
    TRACE( _T("Failed in call to GetCommState\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::SetState(DCB& dcb, BOOL bClosePortOnErr)
{
  ASSERT( IsOpen() );

  if( !SetCommState(m_hComm, &dcb) ) {
    if( bClosePortOnErr == TRUE ) {
      Close();
    }
    TRACE( _T("Failed in call to SetCommState\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::Escape(DWORD dwFunc)
{
  ASSERT( IsOpen() );

  if( !EscapeCommFunction(m_hComm, dwFunc) ) {
    TRACE( _T("Failed in call to EscapeCommFunction\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::ClearDTR()
{
  Escape(CLRDTR);
}


void CSerialPort::ClearRTS()
{
  Escape(CLRRTS);
}


void CSerialPort::SetDTR()
{
  Escape(SETDTR);
}


void CSerialPort::SetRTS()
{
  Escape(SETRTS);
}


void CSerialPort::SetXOFF()
{
  Escape(SETXOFF);
}


void CSerialPort::SetXON()
{
  Escape(SETXON);
}


void CSerialPort::GetProperties(COMMPROP & properties)
{
  ASSERT( IsOpen() );

  if( !GetCommProperties(m_hComm, &properties) ) {
    TRACE( _T("Failed in call to GetCommProperties\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::GetModemStatus(DWORD & dwModemStatus)
{
  ASSERT( IsOpen() );

  if( !GetCommModemStatus(m_hComm, &dwModemStatus) ) {
    TRACE( _T("Failed in call to GetCommModemStatus\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::SetMask(DWORD dwMask)
{
  ASSERT( IsOpen() );

  if( !SetCommMask(m_hComm, dwMask) ) {
    TRACE( _T("Failed in call to SetCommMask\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::GetMask(DWORD & dwMask)
{
  ASSERT( IsOpen() );

  if( !GetCommMask(m_hComm, &dwMask) ) {
    TRACE( _T("Failed in call to GetCommMask\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::Flush()
{
  ASSERT( IsOpen() );

  if( !FlushFileBuffers(m_hComm) ) {
    TRACE( _T("Failed in call to FlushFileBuffers\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::Purge(DWORD dwFlags)
{
  ASSERT( IsOpen() );

  if( !PurgeComm(m_hComm, dwFlags) ) {
    TRACE( _T("Failed in call to PurgeComm\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::TerminateOutstandingWrites()
{
  Purge(PURGE_TXABORT);
}


void CSerialPort::TerminateOutstandingReads()
{
  Purge(PURGE_RXABORT);
}


void CSerialPort::ClearWriteBuffer()
{
  Purge(PURGE_TXCLEAR);
}


void CSerialPort::ClearReadBuffer()
{
  Purge(PURGE_RXCLEAR);
}


void CSerialPort::Setup(DWORD dwInQueue, DWORD dwOutQueue)
{
  ASSERT( IsOpen() );

  if( !SetupComm(m_hComm, dwInQueue, dwOutQueue) ) {
    TRACE( _T("Failed in call to SetupComm\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::SetTimeouts(const COMMTIMEOUTS& timeouts)
{
  ASSERT( IsOpen() );

  if( !SetCommTimeouts(m_hComm, (LPCOMMTIMEOUTS)&timeouts) ) {
    TRACE( _T("Failed in call to SetCommTimeouts\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::GetTimeouts(COMMTIMEOUTS & timeouts)
{
  ASSERT( IsOpen() );

  if( !GetCommTimeouts(m_hComm, &timeouts) ) {
    TRACE( _T("Failed in call to GetCommTimeouts\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::Set0Timeout()
{
  COMMTIMEOUTS Timeouts;

  ZeroMemory( &Timeouts, sizeof(COMMTIMEOUTS) );
  Timeouts.ReadIntervalTimeout         = MAXDWORD;
  Timeouts.ReadTotalTimeoutMultiplier  = 0;
  Timeouts.ReadTotalTimeoutConstant    = 0;
  Timeouts.WriteTotalTimeoutMultiplier = 0;
  Timeouts.WriteTotalTimeoutConstant   = 0;
  SetTimeouts(Timeouts);
}


void CSerialPort::Set0WriteTimeout()
{
  COMMTIMEOUTS Timeouts;

  GetTimeouts(Timeouts);
  Timeouts.WriteTotalTimeoutMultiplier = 0;
  Timeouts.WriteTotalTimeoutConstant   = 0;
  SetTimeouts(Timeouts);
}


void CSerialPort::Set0ReadTimeout()
{
  COMMTIMEOUTS Timeouts;

  GetTimeouts(Timeouts);
  Timeouts.ReadIntervalTimeout        = MAXDWORD;
  Timeouts.ReadTotalTimeoutMultiplier = 0;
  Timeouts.ReadTotalTimeoutConstant   = 0;
  SetTimeouts(Timeouts);
}


void CSerialPort::WaitEvent(DWORD & dwMask)
{
  ASSERT( IsOpen() );
  ASSERT(!m_bOverlapped);

  if( !WaitCommEvent(m_hComm, &dwMask, NULL) ) {
    TRACE( _T("Failed in call to WaitCommEvent\n") );
    AfxThrowSerialException();
  }
}


void CSerialPort::WaitEvent(DWORD & dwMask, OVERLAPPED & overlapped)
{
  ASSERT( IsOpen() );
  ASSERT(m_bOverlapped);
  ASSERT(overlapped.hEvent);

  if( !WaitCommEvent(m_hComm, &dwMask, &overlapped) ) {
    if(GetLastError() != ERROR_IO_PENDING) {
      TRACE( _T("Failed in call to WaitCommEvent\n") );
      AfxThrowSerialException();
    }
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文