⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comm.cpp

📁 用bcb6.0修改了原来用delphi编的spcomm
💻 CPP
📖 第 1 页 / 共 4 页
字号:
///////////////////CommX.cpp///////////////////////////////////////////////////  
//Author:agzxp@163.com  
//Date:2008.3.18  
//  
//--------------------------------------------------------------------------- 
#include  <basepch.h> 
#pragma hdrstop 
#include "comm.h" 
#pragma package(smart_init) 
//--------------------------------------------------------------------------- 
// ValidCtrCheck is used to assure that the components created do not have 
// any pure virtual functions. 
// 

static inline void ValidCtrCheck(TCommX *)
{ 
    new TCommX(NULL);
} 
//--------------------------------------------------------------------------- 

namespace Comm
{ 
    void __fastcall PACKAGE Register() 
    { 
         TComponentClass classes[1] = {__classid(TCommX)};
         RegisterComponents("System", classes, 0); 
    }
} 
//--------------------------------------------------------------------------- 
/***************************************************************************/ 
//   TComm PUBLIC METHODS 
/***************************************************************************/ 

__fastcall TCommX::TCommX(TComponent* Owner)
    : TComponent(Owner) 
{ 
     ReadThread = NULL; 
     WriteThread = NULL; 

     hCommFile  = NULL; 
     hCloseEvent = NULL; 
     FSendDataEmpty = true; 

     FCommName  = "COM1"; 
     FBaudRate  = 9600; 
     FParityCheck = false; 
     FOutx_CtsFlow = false; 
     FOutx_DsrFlow = false; 
     FDtrControl = DtrEnable; 
     FDsrSensitivity = false; 
     FTxContinueOnXoff = true; 
     FOutx_XonXoffFlow = true; 
     FInx_XonXoffFlow  = true; 
     FReplaceWhenParityError = false; 
     FIgnoreNullChar = false; 
     FRtsControl = RtsEnable; 
     FXonLimit = 500; 
     FXoffLimit = 500; 
     FByteSize = _8; 
     FParity = None; 
     FStopBits = _1; 
 FXonChar = 0x11;  // Ctrl-Q 
 FXoffChar = 0x13; // Ctrl-S 
 FReplacedChar = 0x00; 
 FReadIntervalTimeout         = 100; 
 FReadTotalTimeoutMultiplier  = 0; 
 FReadTotalTimeoutConstant    = 0; 
 FWriteTotalTimeoutMultiplier = 0; 
     FWriteTotalTimeoutConstant   = 0; 

    if(!ComponentState.Contains(csDesigning))  
        FHWnd = AllocateHWnd(CommWndProc); 
} 
//--------------------------------------------------------------------------- 
__fastcall TCommX::~TCommX(void)
{ 
    if(!ComponentState.Contains(csDesigning)) 
        DeallocateHWnd(FHWnd); 
} 
//--------------------------------------------------------------------------- 
// 
//  FUNCTION: StartComm 
// 
//  PURPOSE: Starts communications over the comm port. 
// 
//  PARAMETERS: 
//    hNewCommFile - This is the COMM File handle to communicate with. 
//                   This handle is obtained from TAPI. 
// 
//  Output: 
//    Successful: Startup the communications. 
//    Failure: Raise a exception 
// 
//  COMMENTS: 
// 
//    StartComm makes sure there isn't communication in progress already, 
//    creates a Comm file, and creates the read and write threads.  It 
//    also configures the hNewCommFile for the appropriate COMM settings. 
// 
//    If StartComm fails for any reason, it's up to the calling application 
//    to close the Comm file handle. 
// 
// 
void __fastcall TCommX::StartComm(void)
{ 
    HANDLE hNewCommFile; 

    // Are we already doing comm? 
    if (hCommFile != NULL) 
        throw ECommsError( "This serial port already opened!\n\n串口已经打开!"); 

    hNewCommFile = CreateFile(  FCommName.c_str(), 
                                GENERIC_READ  | GENERIC_WRITE, 
                                0,      //not shared 
                                NULL,   //no security 
                                OPEN_EXISTING, 
                                FILE_ATTRIBUTE_NORMAL  | FILE_FLAG_OVERLAPPED, 
                                NULL);     //template 

    if (hNewCommFile == INVALID_HANDLE_VALUE) 
        throw ECommsError( "Error opening serial port!\n\n打开串口出现错误!"); 

    // Is this a valid comm handle? 
    if (GetFileType( hNewCommFile ) != FILE_TYPE_CHAR) 
    { 
        CloseHandle( hNewCommFile ); 
        throw ECommsError( "File handle is not a comm handle ! 打开的串口非通信串口!" ); 
    } 

    if (! SetupComm( hNewCommFile, 4096, 4096 ) ) 
    { 
        CloseHandle( hCommFile ); 
        throw ECommsError( "Cannot setup comm buffer!" ); 
    } 

    // It is ok to continue. 

    hCommFile = hNewCommFile; 

    // purge any information in the buffer 

    PurgeComm(hCommFile,PURGE_TXABORT |PURGE_RXABORT |PURGE_TXCLEAR |PURGE_RXCLEAR); 
    FSendDataEmpty =true; 

    // Setting the time-out value 
    _SetCommTimeout(); 

    // Querying then setting the comm port configurations. 
    _SetCommState(); 

    // Create the event that will signal the threads to close. 
    hCloseEvent = CreateEvent( NULL, true, false, NULL ); 

    if (hCloseEvent == NULL) 
    { 
          CloseHandle( hCommFile ); 
          hCommFile = NULL; 
          throw ECommsError( "Unable to create event" ); 
    } 

    // Create the Read thread. 
    try 
    { 
        ReadThread = new TReadThread( true /* suspended */  ); 
    } 
    catch(...) 
    { 
        ReadThread = NULL; 
        CloseHandle( hCloseEvent ); 
        CloseHandle( hCommFile ); 
        hCommFile = NULL; 
        throw ECommsError( "Unable to create read thread \n\n 无法创建读监控线程!" ); 
    } 

    ReadThread->hCommFile = hCommFile; 
    ReadThread->hCloseEvent = hCloseEvent; 
    ReadThread->hComm32Window = FHWnd; 

    // Comm threads should have a higher base priority than the UI thread. 
    // If they don't, then any temporary priority boost the UI thread gains 
    // could cause the COMM threads to loose data. 
    ReadThread->Priority = tpHighest; 

    // Create the Write thread. 
    try 
    { 
        WriteThread = new TWriteThread( true /* suspended */ ); 
    } 
    catch(...) 
    { 
        CloseReadThread(); 
        WriteThread = NULL; 
        CloseHandle( hCloseEvent ); 
        CloseHandle( hCommFile ); 
        hCommFile = NULL; 
throw ECommsError( "Unable to create write thread\n\n 无法创建写监控线程!" ); 
} 
     
    WriteThread->hCommFile = hCommFile; 
    WriteThread->hCloseEvent = hCloseEvent; 
    WriteThread->hComm32Window = FHWnd; 
WriteThread->pFSendDataEmpty = &FSendDataEmpty; 
WriteThread->Priority = tpHigher; 

    ReadThread->Resume(); 
    WriteThread->Resume(); 

// Everything was created ok.  Ready to go! 
}
//--------------------------------------------------------------------------- 
// 
//  FUNCTION: StopComm 
// 
//  PURPOSE: Stop and end all communication threads. 
// 
//  PARAMETERS: 
//    none 
// 
//  RETURN VALUE: 
//    none 
// 
//  COMMENTS: 
// 
//    Tries to gracefully signal all communication threads to 
//    close, but terminates them if it has to. 
// 
// 
void __fastcall TCommX::StopComm(void)
{ 
    // No need to continue if we're not communicating. 
    if (hCommFile == NULL) return; 

// Close the threads. 
CloseReadThread(); 
CloseWriteThread(); 

// Not needed anymore. 
CloseHandle( hCloseEvent ); 

// Now close the comm port handle. 
CloseHandle( hCommFile ); 
hCommFile = NULL; 
} 
//--------------------------------------------------------------------------- 
// 
//  FUNCTION: WriteCommData(PChar, Word) 
// 
//  PURPOSE: Send a String to the Write Thread to be written to the Comm. 
// 
//  PARAMETERS: 
//    pszStringToWrite     - String to Write to Comm port. 
//    nSizeofStringToWrite - length of pszStringToWrite. 
// 
//  RETURN VALUE: 
//    Returns TRUE if the PostMessage is successful. 
//    Returns FALSE if PostMessage fails or Write thread doesn't exist. 
// 
//  COMMENTS: 
// 
//    This is a wrapper function so that other modules don't care that 
//    Comm writing is done via PostMessage to a Write thread.  Note that 
//    using PostMessage speeds up response to the UI (very little delay to 
//    'write' a string) and provides a natural buffer if the comm is slow 
//    (ie: the messages just pile up in the message queue). 
// 
//    Note that it is assumed that pszStringToWrite is allocated with 
//    LocalAlloc, and that if WriteCommData succeeds, its the job of the 
//    Write thread to LocalFree it.  If WriteCommData fails, then its 
//    the job of the calling function to free the string. 
// 
// 
bool __fastcall TCommX::WriteCommData(char * pDataToWrite, Word dwSizeofDataToWrite) 
{ 
Pointer Buffer; 
    if ((WriteThread != NULL) && (dwSizeofDataToWrite != 0)) 
    { 
          Buffer = Pointer(LocalAlloc( LPTR, dwSizeofDataToWrite+1 )); 
          Move( pDataToWrite, Buffer, dwSizeofDataToWrite ); 

          if (PostThreadMessage(WriteThread->ThreadID, PWM_COMMWRITE, 
 WPARAM(dwSizeofDataToWrite), LPARAM(Buffer)) ) 
  { 
               FSendDataEmpty = false; 
               return true; 
          } 
          else 
          { 
                DWORD dwError = GetLastError(); 
                if (dwError == ERROR_INVALID_THREAD_ID) 
                { 
throw ECommsError("Write thread is not a valid thread,\n\ or Write thread does not have a message queue."); 
} 
  } 
    } 
    return false; 
} 
//--------------------------------------------------------------------------- 
// 
//  FUNCTION: GetModemState 
// 
//  PURPOSE: Read the state of modem input pin right now 
// 
//  PARAMETERS: 
//     none 
// 
//  RETURN VALUE: 
// 
//     A DWORD variable containing one or more of following codes: 
// 
//     Value       Meaning 
//     ----------  ----------------------------------------------------------- 
//     MS_CTS_ON   The CTS (clear-to-send) signal is on. 
//     MS_DSR_ON   The DSR (data-set-ready) signal is on. 
//     MS_RING_ON  The ring indicator signal is on. 
//     MS_RLSD_ON  The RLSD (receive-line-signal-detect) signal is on. 
// 
//     If this comm have bad handle or not yet opened, the return value is 0 
// 
//  COMMENTS: 
// 
//    This member function calls GetCommModemStatus and return its value. 
//    Before calling this member function, you must have a successful 
//    'StartOpen' call. 
// 
// 
DWORD __fastcall TCommX::GetModemState(void) 
{ 
    DWORD dwModemState; 
    if(! GetCommModemStatus( hCommFile, &dwModemState ) ) 
        return 0; 
    else return dwModemState; 
} 
//--------------------------------------------------------------------------- 
/***************************************************************************/ 
//  TComm PROTECTED METHODS 
/***************************************************************************/ 
//--------------------------------------------------------------------------- 
// 
//  FUNCTION: CloseReadThread 
// 
//  PURPOSE: Close the Read Thread. 
// 
//  PARAMETERS: 
//    none 
// 
//  RETURN VALUE: 
//    none 
// 
//  COMMENTS: 
// 
//    Closes the Read thread by signaling the CloseEvent. 
//    Purges any outstanding reads on the comm port. 
// 
//    Note that terminating a thread leaks memory. 
//    Besides the normal leak incurred, there is an event object 
//    that doesn't get closed.  This isn't worth worrying about 
//    since it shouldn't happen anyway. 
// 
// 
void __fastcall TCommX::CloseReadThread(void) 
{ 
     // If it exists... 
     if (ReadThread != NULL) 
     { 
          // Signal the event to close the worker threads. 
          SetEvent( hCloseEvent ); 

          // Purge all outstanding reads 
          PurgeComm( hCommFile, PURGE_RXABORT  | PURGE_RXCLEAR ); 

          // Wait 10 seconds for it to exit.  Shouldn't happen. 
          if (WaitForSingleObject((UINT*)ReadThread->Handle, 10000) == WAIT_TIMEOUT) 
             ReadThread->Terminate(); 
              
          ReadThread->Free(); 
          ReadThread = NULL; 
     } 
}
//--------------------------------------------------------------------------- 
// 
//  FUNCTION: CloseWriteThread 
// 
//  PURPOSE: Closes the Write Thread. 
// 
//  PARAMETERS: 
//    none 
// 
//  RETURN VALUE: 
//    none 
// 
//  COMMENTS: 
// 
//    Closes the write thread by signaling the CloseEvent. 
//    Purges any outstanding writes on the comm port. 
// 
//    Note that terminating a thread leaks memory. 
//    Besides the normal leak incurred, there is an event object 
//    that doesn't get closed.  This isn't worth worrying about 
//    since it shouldn't happen anyway. 
// 
// 
void __fastcall TCommX::CloseWriteThread(void) 
{ 
    // If it exists... 
    if (WriteThread != NULL) 
    { 
          // Signal the event to close the worker threads. 
          SetEvent(hCloseEvent); 

          // Purge all outstanding writes. 
          PurgeComm(hCommFile, PURGE_TXABORT  | PURGE_TXCLEAR); 
          FSendDataEmpty = true; 

          // Wait 10 seconds for it to exit.  Shouldn't happen. 
  if (WaitForSingleObject( (UINT*)WriteThread->Handle, 10000 ) == WAIT_TIMEOUT) 
 WriteThread->Terminate(); 
          WriteThread->Free(); 
          WriteThread = NULL; 
    } 
} 
//--------------------------------------------------------------------------- 
void __fastcall TCommX::ReceiveData(char * Buffer, Word BufferLength) 
{ 
    if (FOnReceiveData != NULL) 
        FOnReceiveData( this, Buffer, BufferLength ); 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -