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

📄 comm.cpp

📁 用bcb6.0修改了原来用delphi编的spcomm
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//--------------------------------------------------------------------------- 
// 
//  FUNCTION: HandleCommEvent(LPOVERLAPPED, LPDWORD, BOOL) 
// 
//  PURPOSE: Handle an outstanding Comm Event. 
// 
//  PARAMETERS: 
//    lpOverlappedCommEvent - Pointer to the overlapped structure to use. 
//    lpfdwEvtMask          - Pointer to DWORD to received Event data. 
//     fRetrieveEvent       - Flag to signal if the event needs to be 
//                            retrieved, or has already been retrieved. 
// 
//  RETURN VALUE: 
//    TRUE if able to handle a Comm Event. 
//    FALSE if unable to setup WaitCommEvent, unable to handle 
//    an existing outstanding event or if the CloseEvent has been signaled. 
// 
//  COMMENTS: 
// 
//    This function is a helper function for the Read Thread that (if 
//    fRetrieveEvent == TRUE) retrieves an outstanding CommEvent and 
//    deals with it.  The only event that should occur is an EV_ERR event, 
//    signalling that there has been an error on the comm port. 
// 
//    Normally, comm errors would not be put into the normal data stream 
//    as this sample is demonstrating.  Putting it in a status bar would 
//    be more appropriate for a real application. 
// 
// 
bool __fastcall TReadThread::HandleCommEvent( 
        Windows::POverlapped lpOverlappedCommEvent, 
        DWORD &lpfdwEvtMask, 
        bool fRetrieveEvent) 
{ 
    DWORD dwDummy; 
    DWORD dwErrors; 
    DWORD dwLastError; 
    DWORD dwModemEvent; 

    // If this fails, it could be because the file was closed (and I/O is 
    // finished) or because the overlapped I/O is still in progress.  In 
    // either case (or any others) its a bug and return FALSE. 
    if (fRetrieveEvent) 
    { 
        if (! GetOverlappedResult( hCommFile, lpOverlappedCommEvent, &dwDummy, false )) 
        { 
            dwLastError = GetLastError(); 

            // Its possible for this error to occur if the 
            // service provider has closed the port.  Time to end. 
            if (dwLastError == ERROR_INVALID_HANDLE) 
                return false; 

            PostHangupCall(); 
            return false; 
        } 
    } 

    // Was the event an error? 
    if ((lpfdwEvtMask && EV_ERR) != 0) 
    { 
        // Which error was it? 
        if (! ClearCommError( hCommFile, &dwErrors, NULL ) ) 
        { 
            dwLastError = GetLastError(); 

            // Its possible for this error to occur if the 
            // service provider has closed the port.  Time to end. 
            if (dwLastError == ERROR_INVALID_HANDLE ) 
                return false; 

            PostHangupCall(); 
            return false; 
        } 

        // Its possible that multiple errors occured and were handled 
        // in the last ClearCommError.  Because all errors were signaled 
        // individually, but cleared all at once, pending comm events 
        // can yield EV_ERR while dwErrors equals 0.  Ignore this event. 

        if (! ReceiveError( dwErrors ) ) return false; 

        return true;//  Result := True 
    } 

    dwModemEvent = 0; 

    if ((lpfdwEvtMask && EV_RLSD) != 0) dwModemEvent = ME_RLSD; 
    if ((lpfdwEvtMask && EV_RING) != 0) dwModemEvent = dwModemEvent  | ME_RING; 
if (dwModemEvent != 0) 
    { 
if (! ModemStateChange( dwModemEvent ) ) 
return false; 

        return true; 
    } 

    if (((lpfdwEvtMask && EV_ERR)==0) && (dwModemEvent==0)) 
          PostHangupCall(); // Should not have gotten here. 

    return false; 
} 
//--------------------------------------------------------------------------- 
// 
// 
// 
bool __fastcall TReadThread::ReceiveData( 
            char * lpNewString, 
            DWORD dwSizeofNewString) 
{ 
    if (!PostMessage(hComm32Window,PWM_GOTCOMMDATA,WPARAM(dwSizeofNewString),LPARAM(lpNewString))) 
        PostHangupCall(); 
    else return true; 

    return false; 
} 
//--------------------------------------------------------------------------- 
// 
// 
// 
bool __fastcall TReadThread::ReceiveError(DWORD EvtMask) 
{ 
    if (!PostMessage(hComm32Window,PWM_RECEIVEERROR,0,LPARAM(EvtMask))) 
        PostHangupCall(); 
     else return true; 
     return false; 
} 
//--------------------------------------------------------------------------- 
// 
// 
bool __fastcall TReadThread::ModemStateChange(DWORD ModemEvent) 
{ 
    if(!PostMessage(hComm32Window,PWM_MODEMSTATECHANGE,0,LPARAM(ModemEvent))) 
        PostHangupCall(); 
    else return true; 
    return false; 
} 
//--------------------------------------------------------------------------- 
// 
// 
// 
void __fastcall TReadThread::PostHangupCall(void) 
{ 
    PostMessage( hComm32Window, PWM_REQUESTHANGUP, 0, 0 ); 
} 
//--------------------------------------------------------------------------- 
/***************************************************************************/ 
//  WRITE THREAD - 写线程 
/***************************************************************************/ 
//--------------------------------------------------------------------------- 
// 
//  PROCEDURE: TWriteThread.Execute 
// 
//  PURPOSE: The starting point for the Write thread. 
// 
//  PARAMETERS: 
//    lpvParam - unused. 
// 
//  RETURN VALUE: 
//    DWORD - unused. 
// 
//  COMMENTS: 
// 
//    The Write thread uses a PeekMessage loop to wait for a string to write, 
//    and when it gets one, it writes it to the Comm port.  If the CloseEvent 
//    object is signaled, then it exits.  The use of messages to tell the 
//    Write thread what to write provides a natural desynchronization between 
//    the UI and the Write thread. 
// 
// 
void __fastcall TWriteThread::Execute(void) 
{     
    TMsg        msg; 
    DWORD       dwHandleSignaled; 
    OVERLAPPED  overlappedWrite; 
    bool        CompleteOneWriteRequire; 

    // Needed for overlapped I/O. 
    memset( &overlappedWrite, 0, sizeof(overlappedWrite)); 

    overlappedWrite.hEvent = CreateEvent( NULL, true, true, NULL ); 
    if (overlappedWrite.hEvent == 0) 
    { 
          PostHangupCall(); 
  goto EndWriteThread; 
    } 

    CompleteOneWriteRequire = true; 

    // This is the main loop.  Loop until we break out. 
    while (true) 
    { 
        if (! PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )) 
        { 
            // If there are no messages pending, wait for a message or 
            // the CloseEvent. 

            *pFSendDataEmpty = true; 

            if (CompleteOneWriteRequire) 
            { 
                if (! PostMessage( hComm32Window, PWM_SENDDATAEMPTY, 0, 0 ) ) 
                { 
                    PostHangupCall(); 
goto EndWriteThread; 
                } 
            } 

            CompleteOneWriteRequire = false; 

            dwHandleSignaled = MsgWaitForMultipleObjects(1, &hCloseEvent, false, 
                                   INFINITE, QS_ALLINPUT); 

            switch( dwHandleSignaled ) 
            { 
                case  WAIT_OBJECT_0:     // CloseEvent signaled! 
                { 
                    // Time to exit. 
goto EndWriteThread; 
                } 

                case WAIT_OBJECT_0 + 1: // New message was received. 
                { 
                    // Get the message that woke us up by looping again. 
continue; 
                } 

                case WAIT_FAILED:       // Wait failed.  Shouldn't happen. 
                { 
                    PostHangupCall(); 
goto EndWriteThread; 
                } 
                
                default :               // This case should never occur. 
                { 
                    PostHangupCall(); 
goto EndWriteThread; 
                } 
            } 
        } 

        // Make sure the CloseEvent isn't signaled while retrieving messages. 
if (WAIT_TIMEOUT != WaitForSingleObject(hCloseEvent, 0)) 
 goto EndWriteThread; 

        // Process the message. 
        // This could happen if a dialog is created on this thread. 
        // This doesn't occur in this sample, but might if modified. 
        if (msg.hwnd != NULL) 
        { 
            TranslateMessage(&msg); 
            DispatchMessage(&msg); 
            continue; 
        } 

        // Handle the message. 
        switch (msg.message) 
        { 
case   PWM_COMMWRITE:  // New string to write to Comm port. 
            { 
// Write the string to the comm port.  HandleWriteData 
// does not return until the whole string has been written, 
                // an error occurs or until the CloseEvent is signaled. 
                if (! HandleWriteData( overlappedWrite, PChar(msg.lParam), DWORD(msg.wParam) )) 
                { 
                    // If it failed, either we got a signal to end or there 
                    // really was a failure. 

                    LocalFree( HLOCAL(msg.lParam) ); 
goto EndWriteThread; 
                } 

                CompleteOneWriteRequire = true; 

                // Data was sent in a LocalAlloc()d buffer.  Must free it. 
LocalFree( HLOCAL(msg.lParam) ); 

break; 
            } 
        } 
    } 

     // Thats the end.  Now clean up. 
EndWriteThread: 

PurgeComm(hCommFile, PURGE_TXABORT  | PURGE_TXCLEAR); 
*pFSendDataEmpty = true; 
    CloseHandle(overlappedWrite.hEvent); 
} 
//--------------------------------------------------------------------------- 
// 
//  FUNCTION: HandleWriteData(LPOVERLAPPED, LPCSTR, DWORD) 
// 
//  PURPOSE: Writes a given string to the comm file handle. 
// 
//  PARAMETERS: 
//    lpOverlappedWrite  - Overlapped structure to use in WriteFile 
//    pDataToWrite       - String to write. 
//    dwNumberOfBytesToWrite - Length of String to write. 
// 
//  RETURN VALUE: 
//    TRUE if all bytes were written.  False if there was a failure to 
//    write the whole string. 
// 
//  COMMENTS: 
// 
//    This function is a helper function for the Write Thread.  It 
//    is this call that actually writes a string to the comm file. 
//    Note that this call blocks and waits for the Write to complete 
//    or for the CloseEvent object to signal that the thread should end. 
//    Another possible reason for returning FALSE is if the comm port 
//    is closed by the service provider. 
// 
// 
 
 
bool __fastcall TWriteThread::HandleWriteData( 
OVERLAPPED OverlappedWrite, 
                char * pDataToWrite, 
                DWORD dwNumberOfBytesToWrite) 
{ 
    DWORD dwLastError; 
    DWORD dwNumberOfBytesWritten; 
    DWORD dwWhereToStartWriting; 
    DWORD dwHandleSignaled; 

    HANDLE HandlesToWaitFor[2]; 

    dwNumberOfBytesWritten = 0; 
    dwWhereToStartWriting  = 0; // Start at the beginning. 

    HandlesToWaitFor[0] = hCloseEvent; 
HandlesToWaitFor[1] = OverlappedWrite.hEvent; 

// Keep looping until all characters have been written. 
    do 
    { 
        // Start the overlapped I/O. 
        if (! WriteFile( hCommFile, 
                         &pDataToWrite[ dwWhereToStartWriting ], 
                         dwNumberOfBytesToWrite, 
                         &dwNumberOfBytesWritten, 
 &OverlappedWrite )) 
        { 
            // WriteFile failed.  Expected; lets handle it. 
            dwLastError = GetLastError(); 

            // Its possible for this error to occur if the 
            // service provider has closed the port.  Time to end. 
            if (dwLastError == ERROR_INVALID_HANDLE ) 
            { 
return false; 
            } 

            // Unexpected error.  No idea what. 
            if (dwLastError != ERROR_IO_PENDING) 
            { 
                PostHangupCall(); 
return false; 
            } 

            // This is the expected ERROR_IO_PENDING case. 

            // Wait for either overlapped I/O completion, 
            // or for the CloseEvent to get signaled. 
dwHandleSignaled = WaitForMultipleObjects(2,HandlesToWaitFor,false,INFINITE); 
switch (dwHandleSignaled) 
            { 
                case WAIT_OBJECT_0:     // CloseEvent signaled! 
                { 
return false; 
                } 

                case WAIT_OBJECT_0 + 1: // Wait finished. 
                { 
// Time to get the results of the WriteFile 
if (!GetOverlappedResult(hCommFile,&OverlappedWrite,&dwNumberOfBytesWritten,true)) 
                    { 
                        dwLastError = GetLastError(); 

                        // Its possible for this error to occur if the 
                        // service provider has closed the port. 
                        if (dwLastError == ERROR_INVALID_HANDLE) 
                        { 
return false; 
                        } 

                        // No idea what could cause another error. 
                        PostHangupCall(); 
return false; 
} 

break; 
                } 

case WAIT_FAILED: // Wait failed.  Shouldn't happen. 
                { 
                    PostHangupCall(); 
                    return false; 
                } 

                default :         // This case should never occur. 
                { 
                     PostHangupCall(); 
 return false; 
                }  
            } // switch  
} // writedata error 

// Some data was written.  Make sure it all got written. 
dwNumberOfBytesToWrite -= dwNumberOfBytesWritten; 
dwWhereToStartWriting  += dwNumberOfBytesWritten; 
}while (dwNumberOfBytesToWrite > 0);  // Write the whole thing! 

    // Wrote the whole string. 
    return true;     
} 
//--------------------------------------------------------------------------- 
void __fastcall TWriteThread::PostHangupCall(void) 
{ 
    PostMessage( hComm32Window, PWM_REQUESTHANGUP, 0, 0 ); 
} 
//--------------------------------------------------------------------------- 

⌨️ 快捷键说明

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