2011-08-17 47 views
3

我正在嘗試編寫一個基於MFC對話框的應用程序,它從您的PC的串行COMM端口讀取信息,然後將一些信息寫回串行COMM端口。任何想法,我從哪裏開始?從串口讀取信息mfc

在此先感謝。

回答

3

這有幫助嗎? :-)

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(); 
    } 
    } 
} 
+0

哇,看起來像你以前已經這樣做過。將在明天的計劃中嘗試執行此操作。 感謝您的幫助。如果我不明白什麼,我會在這裏發表意見。 再次歡呼。 – Neophile

+0

@ Nerds.Dont.Swear很高興能夠幫助,我從別人那裏繼承了這個類,而IMO是一個糟糕的設計,因爲沒有理由將串行端口類綁定到MFC,但這就是它在這裏完成的方式,重新使用MFC有它的樂趣。 – Praetorian