📄 serialwnd.cpp
字号:
// SerialWnd.cpp - Implementation of the CSerialWnd class
//
// Copyright (C) 1999-2001 Ramon de Klein (R.de.Klein@iaf.nl)
//
// This program is free software; you can redistribute it and/ormodify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//////////////////////////////////////////////////////////////////////
// Include the precompiled header
#define STRICT
#include <crtdbg.h>
#include <tchar.h>
#include <windows.h>
//////////////////////////////////////////////////////////////////////
// Include module headerfile
#include "SerialWnd.h"
//////////////////////////////////////////////////////////////////////
// Disable warning C4127: conditional expression is constant, which
// is generated when using the _RPTF and _ASSERTE macros.
#pragma warning(disable: 4127)
//////////////////////////////////////////////////////////////////////
// Enable debug memory manager
#ifdef _DEBUG
static const char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Code
// Register the standard CSerialWnd COM message
const UINT CSerialWnd::mg_nDefaultComMsg = ::RegisterWindowMessage(_T("CSerialWnd_DefaultComMsg"));
CSerialWnd::CSerialWnd()
: m_hwndDest(0)
, m_nComMsg(WM_NULL)
, m_hevtStop(0)
, m_hevtCommEvent(0)
, m_hThread(0)
, m_lParam(0)
{
}
CSerialWnd::~CSerialWnd()
{
// Check if the thread handle is still there. If so, then we
// didn't close the serial port. We cannot depend on the
// CSerialAsync destructor, because if it calls Close then it
// won't call our overridden Close.
if (m_hThread)
{
// Display a warning
_RPTF0(_CRT_WARN, "CSerialWnd::~CSerialWnd- Serial port not closed\n");
// Close implicitly
Close();
}
}
DWORD WINAPI CSerialWnd::ThreadProc (LPVOID lpArg)
{
// Route the method to the actual object
CSerialWnd* pThis = reinterpret_cast<CSerialWnd*>(lpArg);
return pThis->ThreadProc();
}
DWORD CSerialWnd::ThreadProc (void)
{
// Create an overlapped structure, which we will use
// to wait for communication events.
OVERLAPPED overlapped = {0};
overlapped.hEvent = m_hevtCommEvent;
// Create the array of handles to wait for
HANDLE ah[2];
ah[0] = m_hevtStop; // Stop event
ah[1] = overlapped.hEvent; // COM event (from driver)
// Start the asynchronous WaitEvent
if (FAILED(WaitEvent(&overlapped)))
return m_lLastError;
// Keep looping
bool fStop = false;
while (!fStop)
{
// Wait until one of the events happens
switch (::WaitForMultipleObjects(sizeof(ah)/sizeof(HANDLE),ah,false,INFINITE))
{
case WAIT_OBJECT_0:
// We need to stop
fStop = true;
break;
case WAIT_OBJECT_0+1:
{
// Determine the event
EEvent eEvent = GetEventType();
// Obtain the error status during this event
DWORD dwErrors = 0;
if (!::ClearCommError(m_hFile,&dwErrors,0))
{
// Set the internal error code
m_lLastError = ::GetLastError();
// Issue an error and quit
_RPTF0(_CRT_WARN, "CSerialWnd::ThreadProc - Unable to obtain COM status\n");
}
// Convert the error
EError eError = EError(dwErrors);
// There was a COM event, which needs handling. We'll post
// the destination window a message that it should handle
// the message. We can receive a "zero" event, when the
// mask or event character has been set. We won't pass this
// down to the window.
if (eEvent)
{
::PostMessage(m_hwndDest,m_nComMsg,MAKEWPARAM(eEvent,eError),LPARAM(m_lParam));
}
// Start the asynchronous WaitComEvent again
if (FAILED(WaitEvent(&overlapped)))
{
return m_lLastError;
}
}
break;
default:
// Something went seriously wrong, which we'll need to report
fStop = true;
break;
}
}
// Bye bye
return 0;
}
LONG CSerialWnd::Open (LPCTSTR lpszDevice, HWND hwndDest, UINT nComMsg, LPARAM lParam, DWORD dwInQueue, DWORD dwOutQueue)
{
// Call the base class first
long lLastError = CSerial::Open(lpszDevice,dwInQueue,dwOutQueue);
if (FAILED(lLastError))
return lLastError;
// Create the event
m_hevtStop = ::CreateEvent(0,true,false,0);
m_hevtCommEvent = ::CreateEvent(0,true,false,0);
if ((m_hevtStop == 0) || (m_hevtCommEvent == 0))
{
// Obtain the error code
long lLastError = ::GetLastError();
// Display a warning
_RPTF0(_CRT_WARN, "CSerialWnd::Open - Unable to create event\n");
// Unable to start the watch thread, so we'll close the serial port again
CSerial::Close();
// Set the error code and exit
m_lLastError = lLastError;
return m_lLastError;
}
// Start the watcher thread
DWORD dwThreadId = 0;
m_hThread = ::CreateThread(0,0,ThreadProc,LPVOID(this),CREATE_SUSPENDED,&dwThreadId);
if (m_hThread == 0)
{
// Obtain the error code
long lLastError = ::GetLastError();
// Display a warning
_RPTF0(_CRT_WARN, "CSerialWnd::Open - Unable to start COM watcher thread\n");
// Close the event handle
::CloseHandle(m_hevtStop);
m_hevtStop = 0;
// Unable to start the watch thread, so we'll close the serial port again
CSerial::Close();
// Set the error code and exit
m_lLastError = lLastError;
return m_lLastError;
}
// Save the window handle, notification message and user message
m_hwndDest = hwndDest;
m_nComMsg = nComMsg?nComMsg:mg_nDefaultComMsg;
m_lParam = lParam;
// Start the thread
::ResumeThread(m_hThread);
// Return the error
return m_lLastError;
}
LONG CSerialWnd::Close (void)
{
// Signal the watcher thread that it should stop
::SetEvent(m_hevtStop);
// Wait until the watcher thread has stopped
::WaitForSingleObject(m_hThread,INFINITE);
// Close the event handles
if (m_hevtStop)
{
::CloseHandle(m_hevtStop);
m_hevtStop = 0;
}
if (m_hevtCommEvent)
{
::CloseHandle(m_hevtCommEvent);
m_hevtCommEvent = 0;
}
// Reset all members
m_hThread = 0;
m_hwndDest = 0;
m_nComMsg = WM_NULL;
m_lParam = 0;
// Call the base class
return CSerial::Close();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -