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

📄 serialwnd.cpp

📁 这是一个串口调试程序,带有源代码的,还是比较好用的.
💻 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 + -