CnComm v1.51 多线程串口通讯库

/*! \mainpage CnComm v1.51 多线程串口通讯库 
 *	\section About 关于
 *  
 *  \n 版本: CnComm v1.51
 *  \n 用途: WINDOWS/WINCE 多线程串口通讯库
 *  \n 语言: C++ (ANSI/UNICODE)
 *  \n 平台: WINDOWS(WIN98/NT/2000/XP/2003/Vista); WINCE 5.0 模拟器; Pocket PC 2003 模拟器;
 *  \n 硬件: PC串口; 串口服务器; USB串口; 虚拟串口;
 *  \n 编译: BC++ 5(free tool); C++ BUILDER 4, 5, 6, X; EVC 4(sp4); G++ 3, 4; Intel C++ 7, 8, 9; VC++ 6(sp6), .NET, 2003, 2005;
 *  \n 作者: llbird
 *  \n 邮箱: wushaojian@21cn.com
 *  \n 博客: http://blog.csdn.net/wujian53 http://www.cppblog.com/llbird  
 *  \n 维护: 2002.10 - 2009.8
 *
 *  \section Announce 说明
 *  \n 1) 可以自由使用及传播, 请保留相关声明;                                           
 *  \n 2) 不推荐直接在本代码上修改, 应通过C++继承扩展机制扩展本代码;                          
 *  \n 3) 如果您直接修改本代码, 请发一份给我,便于同网友分享您有益的改动;                              
 *  \n 4) 不兼容cnComm1.4以下版本, 有很大改动,同时也更名CnComm;
 *  \n 5) 还是那句老话, 水平有限, 错误在所难免, 欢迎来信指正, 收入有限, 时间有限, 不提供除CnComm内部问题外的咨询;
 *  
 *  \section Log 日志
 *  \n 2009 v1.51 修正版; 考虑到将来的工作中可能不会再和串口打交道,这很可能是最后一版;
 *  \n 2009 v1.5  增加内置分块链表缓冲区; 增加对WINCE的支持(模拟器下测试通过);
 *  \n 2008 v1.4  增加对同步IO的多线程支持; 增加C++异常的支持; 改名CnComm; Cn == C Next;
 *  \n 2007 v1.3  细节部分修订;
 *  \n 2006 v1.2  细节部分修订;
 *  \n 2005 v1.1  细节部分修订;
 *  \n 2004 v1.0  采用VC命名风格(匈牙利), 在多个WINDOW平台、编译器测试通过, 首次公开发布cnComm;
 *  \n 2002 v0.1  因工作需要开发串口通讯基础类, 传统C++的继承机制, 传统C命名风格;
 */

#ifndef _CN_COMM_H_
#define _CN_COMM_H_

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tchar.h>

#if defined(UNDER_CE) && !defined(CN_COMM_FOR_CE)
	#define CN_COMM_FOR_CE		UNDER_CE			//!< 配置WINCE的支持   
#endif

#ifndef CN_COMM_FOR_CE
	#include <mcx.h>
	#include <process.h>							// WINCE没有process.h
#endif

#ifndef ON_COM_MSG_BASE 
	#define ON_COM_MSG_BASE		WM_USER + 618		//!< 消息编号的基点  
#endif

// 送到窗口的消息 WPARAM COM端口号
#define ON_COM_RECEIVE			ON_COM_MSG_BASE + 0	//!< EV_RXCHAR 
#define ON_COM_RXCHAR			ON_COM_MSG_BASE + 0 //!< EV_RXCHAR 
#define ON_COM_CTS				ON_COM_MSG_BASE + 1 //!< EV_CTS  LPARAM==1 CTS ON 
#define ON_COM_DSR				ON_COM_MSG_BASE + 2 //!< EV_DSR  LPARAM==1 DSR ON
#define ON_COM_RING				ON_COM_MSG_BASE + 3 //!< EV_RING LPARAM==1 RING ON
#define ON_COM_RLSD				ON_COM_MSG_BASE + 4 //!< EV_RLSD LPARAM==1 RLSD ON
#define ON_COM_BREAK			ON_COM_MSG_BASE + 5 //!< EV_BREAK
#define ON_COM_TXEMPTY			ON_COM_MSG_BASE + 6 //!< EV_TXEMPTY 
#define ON_COM_ERROR			ON_COM_MSG_BASE + 7 //!< EV_ERR  LPARAM Error ID 
#define ON_COM_RXFLAG			ON_COM_MSG_BASE + 8 //!< EV_RXFLAG
#define ON_COM_POWER			ON_COM_MSG_BASE + 9 //!< EV_POWER 
#define ON_COM_EVENT1			ON_COM_MSG_BASE + 10//!< EV_EVENT1
#define ON_COM_EVENT2			ON_COM_MSG_BASE + 11//!< EV_EVENT2 
#define ON_COM_RX80FULL			ON_COM_MSG_BASE + 12//!< EV_RX80FULL
#define ON_COM_PERR				ON_COM_MSG_BASE + 13//!< EV_PERR

#ifndef CN_COMM_WAIT_EVENT
	#ifdef CN_COMM_FOR_CE
		#define CN_COMM_WAIT_EVENT	EV_RXCHAR | EV_ERR | EV_CTS | EV_DSR | EV_BREAK | EV_TXEMPTY | EV_RING | EV_RLSD | EV_POWER //!< WINCE 默认的等待事件| EV_RXFLAG 
	#else
		#define CN_COMM_WAIT_EVENT	EV_RXCHAR | EV_ERR | EV_CTS | EV_DSR | EV_BREAK | EV_TXEMPTY | EV_RING | EV_RLSD 			//!< WIN32 默认的等待事件| EV_RXFLAG
	#endif
#endif

#ifndef CN_COMM_BUFFER_MIN_BLOCK_SIZE
	#define CN_COMM_BUFFER_MIN_BLOCK_SIZE 1024		//!< 定义缓冲区块的最小值 
#endif

#if CN_COMM_BUFFER_MIN_BLOCK_SIZE < 4
	#error CN_COMM_BUFFER_MIN_BLOCK_SIZE must >= 4	//!< 缓冲区块的最小值不允许小于4 
#endif

#ifndef CN_ASSERT
	#define CN_2STR(L)		_T(#L)					//!< 将表达式L转换成字符串
	#define CN_LINE(L)		CN_2STR(L)				//!< 将行号L转换成字符串
	/*! 内部断言 启用异常将抛出异常 否则调试版将退出 发行版未启用异常将不做任何处理 */
	#define CN_ASSERT(E)	((E) ? true : CnComm::Assert(_T("CN_ASSERT(")_T(#E)_T(") failed; CnComm(")CN_LINE(__LINE__)_T("); ")))
#endif

//CN_COMM_STD_EXCEPTION CN_ASSERT 将抛出标准C++异常			
#ifdef CN_COMM_STD_EXCEPTION
	#include <stdexcept> //throw runtime_error(msg)
#endif

//CN_COMM_VCL_EXCEPTION CN_ASSERT 将抛出VCL异常(C++ Builder)	
#if defined(CN_COMM_VCL_EXCEPTION) && defined(__BORLANDC__)
	#include <vcl.h> //throw new Exception(msg)	
#endif

//CN_COMM_MFC_EXCEPTION CN_ASSERT 将抛出MFC异常(VC++)			
#ifdef CN_COMM_MFC_EXCEPTION
	#include <Afx.h> //throw new MfcException(msg)	
#endif

/*! \class CnComm 
	\version 1.5 
	\date 2002.10-2009.4
	\author llbird(wushaojian@21cn.com http://www.cppblog.com/llbird  http://blog.csdn.net/wujian53) 
	\brief WIN32/WINCE C++ (ANSI/UNICODE) 多线程串口通讯基础库  
	\example doc_0.cpp 例子0 \example doc_1.cpp \example doc_2.cpp \example doc_3.cpp \example SerialDlg.cpp
 */
class CnComm    
{
public:
	//! 临界区
	struct	InnerLock;
	//! 缓冲区类
	class	BlockBuffer;	
	//! MFC异常
	class	MfcException;				
	//! 用于配置模式的枚举值, 32位掩码
	enum OptionEnum
	{
		EN_THREAD		= 0x00000001,	//!< 启用监视线程 伴随串口打开启动 WatchThread
		EN_OVERLAPPED	= 0x00000002,	//!< 启用异步重叠IO方式 
		EN_RX_BUFFER	= 0x00000004,	//!< 启用读缓冲
		EN_TX_BUFFER	= 0x00000008,	//!< 启用写缓冲
		EN_RX_THREAD	= 0x00000010,	//!< 启动读线程 暂时未用 ReadThread
		EN_TX_THREAD	= 0x00000020,	//!< 启动写线程 用于WINCE的双工操作 应同时启用写缓冲 伴随串口打开启动 WriteThread
		EN_SUSPEND		= 0x00000040,	//!< 启动线程时暂停 
		EN_ABOVE_NORMAL	= 0x00000080,	//!< 启动线程优先级高一个级别
		EN_FLUSH		= 0x00000100,	//!< 当关闭串口时输出队列未发送完的数据(端口缓冲区) 并阻塞等待                          
		EN_FLUSH_ALL	= 0x00000200	//!< 同上(包括写缓冲及端口队列) 您如果重载了写模块而又没有写好 可能导致线程挂起无法正常关闭 
	};
	//! 构造函数 配置具体应用模式 \param[in] dwOption 根据需要由OptionEnum组合而成
#ifdef CN_COMM_FOR_CE
	//! WINCE:默认打开串口时启动监视线程 启用写独立线程 启用写缓冲
	CnComm(DWORD dwOption = EN_THREAD ) 
#else 
	//! WIN32:默认打开串口时启动监视线程 异步重叠方式 
	CnComm(DWORD dwOption = EN_THREAD | EN_OVERLAPPED)
#endif
	{
		Init(); 
		SetOption(dwOption);
	}
	//! 另一模式构造 兼容cnComm1~1.3 \param[in] bThread 启动监视线程 \param[in] bOverlapped 启用重叠I/O
	CnComm(bool bThread, bool bOverlapped)
	{
		DWORD dwOption = 0;

		if (bThread)
			dwOption |= EN_THREAD;

		if (bOverlapped)
			dwOption |= EN_OVERLAPPED;

		Init(); 
		SetOption(dwOption);
	}
	//! 析构 自动关闭串口 
	virtual ~CnComm()
	{
		Close(); 
		Destroy();
	}
	//! 判断串口是或打开
	bool IsOpen()
	{
		return hComm_ != INVALID_HANDLE_VALUE;
	}
	//! 判断串口是或打开
	operator bool ()
	{
		return hComm_ != INVALID_HANDLE_VALUE;
	}
	//! 获得串口句炳
	HANDLE GetHandle()
	{
		return hComm_;
	}
	//! 获得串口句炳
	operator HANDLE()
	{
		return hComm_;
	}
	//! 获得串口序号
	DWORD GetPort()
	{
		return dwPort_;
	}
	//! 获得串口全名
	LPCTSTR GetPortName()
	{
		return szName_;
	}
	//! 获得CnComm的基本配置参数 返回32位配置掩码
	DWORD GetOption()
	{
		return dwOption_;
	}
	//! 设置CnComm的基本配置参数 在打开串口前设置有意义 \param[in] dwOption 32位配置掩码
	void SetOption(DWORD dwOption)
	{
		CN_ASSERT(!IsOpen());//! 打开状态下不可以设置参数

		dwOption_ = dwOption;

	#ifdef CN_COMM_FOR_CE
		CN_ASSERT(!IsOverlappedMode()); //! WINCE不允许使用重叠IO 即EN_OVERLAPPED掩码
		dwOption_ &= (~EN_OVERLAPPED);
	#endif
	}
	//! 修改CnComm的基本配置参数 在打开串口前设置有意义 \param[in] dwRemove 删除的32位配置掩码 \param[in] dwAdd 添加的32位配置掩码
	void ModifyOption(DWORD dwRemove, DWORD dwAdd)
	{
		CN_ASSERT(!IsOpen());//! 打开状态下不可以设置参数

		dwOption_ &= ~dwRemove;
		dwOption_ |= dwAdd;

	#ifdef CN_COMM_FOR_CE
		CN_ASSERT(!IsOverlappedMode()); //! WINCE不允许使用重叠IO 即EN_OVERLAPPED掩码
		dwOption_ &= (~EN_OVERLAPPED);
	#endif
	}
	//! 是否重叠IO模式
	bool IsOverlappedMode()
	{
		return dwOption_ & EN_OVERLAPPED ? true : false;
	}
	//! 是否输出缓冲区模式
	bool IsTxBufferMode()
	{
		return dwOption_ & EN_TX_BUFFER ? true : false;
	}
	//! 是否输入缓冲区模式
	bool IsRxBufferMode()
	{
		return dwOption_ & EN_RX_BUFFER ? true : false;
	}
	//! 关联消息的窗口句柄
	void SetWnd(HWND hWnd)
	{
		CN_ASSERT(::IsWindow(hWnd));
		hNotifyWnd_ = hWnd;
	}
	//! 关联消息的窗口句柄
	HWND GetWnd()
	{
		return hNotifyWnd_;
	}
	//! 关联消息的窗口句柄
	void SetNotifyThreadId(DWORD dwId)
	{
		hNotifyThreadId_ = dwId;
	}
	//! 关联消息的窗口句柄
	DWORD GetNotifyThreadId()
	{
		return hNotifyThreadId_;
	}
	//! 设定发送通知, 接受字符最小值
	void SetNotifyNum(DWORD dwNum)
	{
		dwNotifyNum_ = dwNum;
	}
	//! 获得线程句柄 \param[in] iOption EN_THREAD获得hWatchThread_ EN_RX_THREAD获得hReadThread_ EN_TX_THREAD获得hWriteThread_ \return HANDLE 线程句柄
	HANDLE GetThread(int iOption = EN_THREAD)
	{
		return iOption == EN_THREAD ? hWatchThread_ : ((iOption == EN_RX_THREAD) ? hReadThread_ : hWriteThread_);
	}
	//! 设置要监视的事件, 打开前设置有效
	void SetWaitEvent(DWORD dwEvent = CN_COMM_WAIT_EVENT)
	{
		CN_ASSERT(!IsOpen());///打开状态下不可以设置参数

		dwWaitEvent_ = dwEvent;
	}
	//! 输入缓冲区
	BlockBuffer& Input()
	{
		return I_;
	}
	//! 输出缓冲区
	BlockBuffer& Output()
	{
		return O_;
	}
	//! 获得输入输出的计数 \param[in] bInput 为true获得输入计数,默认为true 重叠IO下输出是不精确的 因为输出由系统后台控制 假设完全输出 
	DWORD GetCounter(bool bInput = true)
	{
		return bInput ? dwInCount_ : dwOutCount_;
	}
	//! 输入输出计数器清零
	void ResetCounter()
	{
		dwInCount_ = dwOutCount_ = 0;
	}
	//! 打开串口 请注意与cnComm1~1.3的区别 cnComm1~1.3将使用9600, n, 8, 1配置端口 而1.5将只打开端口不配置波特率等参数  \param[in] dwPort 串口序号 1~1024
	bool Open(DWORD dwPort)
	{
		if (!CN_ASSERT(dwPort>=1 && dwPort<=1024))
			return false;
		
		BindPort(dwPort);
		
		if(!CN_ASSERT(OpenPort()))
			return false;
		
		if(!CN_ASSERT(SetupPort()))
			return Close(), false;

		if ((dwOption_ & (EN_THREAD|EN_RX_THREAD|EN_TX_THREAD)) && !CN_ASSERT(BeginThread()))
			return Close(), false;

		return true;
	}
	/*! \param[in] dwPort 串口序号 1~1024 \param[in] dwBaudRate 波特率 \param[in] btParity  奇偶校验 \param[in] btByteSize 数据位数	\param[in] btStopBits 停止位数	*/
	//! 打开串口 缺省 9600, n, 8, 1 \sa bool Open(DWORD dwPort, LPCTSTR szSetStr)
	bool Open(DWORD dwPort, DWORD dwBaudRate, BYTE btParity = NOPARITY, BYTE btByteSize = 8, BYTE btStopBits = ONESTOPBIT)
	{
		if (!CN_ASSERT(dwPort>=1 && dwPort<=1024))
			return false;
		
		BindPort(dwPort);
		
		if (!CN_ASSERT(OpenPort()))
			return false;
		
		if (!CN_ASSERT(SetState(dwBaudRate, btParity, btByteSize, btStopBits)))
			return Close(), false;

		if (!CN_ASSERT(SetupPort()))
			return Close(), false;

		if ((dwOption_ & (EN_THREAD|EN_RX_THREAD|EN_TX_THREAD)) && !CN_ASSERT(BeginThread()))
			return Close(), false;

		return true;
	}
#ifndef CN_COMM_FOR_CE
	/*! \param[in] dwPort 串口序号 1~1024 \param[in] szSetStr 字符串参数 "BBBB,P,D,S"  例: "9600,N,8,1"  "1200,O,7,2" 
		 BBBB为波特率 P为奇偶校验(E | M | N | O | S) D为数据位数(4 ~ 8) S为停止位数(1 | 1.5 | 2)
		 \code Open(1, "9600,E,8,2"); \endcode  \b 请注意字符串参数的顺序 并检查返回值
		 不支持WINCE, 原本我自己写了一个替代函数, 考虑到WINCE硬件的复杂性, 移植性可能不好, 故从这个版本中删除了	*/
	//! 打开串口, 字符串设置串口
	bool Open(DWORD dwPort, LPCTSTR szSetStr)
	{
		if (!CN_ASSERT(dwPort>=1 && dwPort<=1024))
			return false;
		
		BindPort(dwPort);
		
		if (!CN_ASSERT(OpenPort()))
			return false;
		
		if (!CN_ASSERT(SetState(szSetStr))) 
			return Close(), false;

		if (!CN_ASSERT(SetupPort()))
			return Close(), false;

		if ((dwOption_ & (EN_THREAD|EN_RX_THREAD|EN_TX_THREAD)) && !CN_ASSERT(BeginThread()))
			return Close(), false;
		
		return true;
	}
#endif
	/*! \param[in] dwPort 此时该参数没有具体意义,仅用于消息通知中辨别端口号,应注意不和其他端口号重复 
		\param[in] szPortName 为指定的端口名称, 就像WINDOWS下\\\\.\\COM1或者WINCE下COM1: , 有些虚拟串口可以有特殊的名称
		\param[in] dwBaudRate 波特率	\param[in] btParity 奇偶校验	\param[in] btByteSize 数据位数	\param[in] btStopBits 停止位数
		\code Open(9999, "COM3:", 2400); \endcode 	\code Open(1028, "COM3:", 9600, N, 7, ONESTOPBIT); \endcode	*/
	//! 指定的端口名称打开串口
	bool Open(DWORD dwPort, LPCTSTR szPortName, DWORD dwBaudRate, BYTE btParity = NOPARITY, BYTE btByteSize = 8, BYTE btStopBits = ONESTOPBIT)
	{
		if(!CN_ASSERT(_tcslen(szPortName) < 64 - 1))
			return false;
		
		_tcscpy(szName_, szPortName);
		dwPort_ = dwPort;//用于通知消息
		
		if (!CN_ASSERT(OpenPort()))
			return false;
		
		if (!CN_ASSERT(SetState(dwBaudRate, btParity, btByteSize, btStopBits)))
			return Close(), false;

		if (!CN_ASSERT(SetupPort()))
			return Close(), false;

		if ((dwOption_ & (EN_THREAD|EN_RX_THREAD|EN_TX_THREAD)) && !CN_ASSERT(BeginThread()))
			return Close(), false;
		
		return true;
	}
	//! 直接读物理端口 \param[out] pBuffer 目标缓冲区 \param[in] dwLength 读取长度 \param[in] dwWaitTime 等待时间(默认INFINITE) \return 返回实际读取字节数
	DWORD ReadPort(LPVOID pBuffer, DWORD dwLength, DWORD dwWaitTime = INFINITE)
	{
		COMSTAT Stat;
		DWORD	dwError, dwReadResult = 0;
		
		if(!CN_ASSERT(IsOpen()) || !dwLength)
			return 0;
		
		if(::ClearCommError(hComm_, &dwError, &Stat) && dwError > 0)
			::PurgeComm(hComm_, PURGE_RXABORT);

	#ifndef CN_COMM_FOR_CE
		if (IsOverlappedMode())//! 重叠I/O下 dwWaitTime==INFINITE 将等待到自然超时或任务完成 具体时间由超时结构决定 默认设定0.5秒
		{
			if (dwWaitTime == INFINITE)//! 如果你没有启用读反冲 直接读取端口将导致阻塞 相当于原来1.3版本 Read(pBuffer, dwLength, false);
			{
				if (!::ReadFile(hComm_, pBuffer, dwLength, &dwReadResult, &RO_))
				{//! 在界面里使用CnComm推荐使用读缓冲区或者在dwWaitTime指定超时时间
					if (CN_ASSERT(::GetLastError() == ERROR_IO_PENDING))
					{
						while (!CN_ASSERT(::GetOverlappedResult(hComm_, &RO_, &dwReadResult, TRUE)))
							;
					}
				}
			}
			else//! 重叠I/O下 dwWaitTime!=INFINITE 将等待到超时或任务完成 具体时间由dwWaitTime决定 
			{	//! dwWaitTime = 0 相当于原来1.3版本的功能
				DWORD dwBegin = GetTickCount(), dwEnd, dwCost, uReadLength, uReadReturn;
				
				uReadLength = Stat.cbInQue > dwLength ? dwLength : Stat.cbInQue;
				CN_ASSERT(::ReadFile(hComm_, pBuffer, uReadLength, &uReadReturn, &RO_));
				dwReadResult += uReadReturn;

				do
				{
					if (!::ReadFile(hComm_, (LPBYTE)pBuffer + dwReadResult, 1, &uReadReturn, &RO_))
					{
						if (dwWaitTime > 5 && WaitForSingleObject(RO_.hEvent, dwWaitTime) == WAIT_OBJECT_0)
						{
							dwEnd = GetTickCount();
							dwCost = dwEnd>=dwBegin ? dwEnd-dwBegin : DWORD(-1L)-dwBegin+dwEnd;
							CN_ASSERT(::GetOverlappedResult(hComm_, &RO_, &uReadReturn, FALSE));
							dwWaitTime = dwWaitTime > dwCost ? dwWaitTime-dwCost : 0;
						} 
						else
						{
							CN_ASSERT(::PurgeComm(hComm_, PURGE_RXABORT));
							break;
						}
					}
				}
				while (uReadReturn && ++dwReadResult < dwLength);
			}
			return dwInCount_ += dwReadResult, dwReadResult;
		}
	#endif
		//! 阻塞I/O和WinCE的I/O下 dwWaitTime无意义 超时时间由超时结构决定 默认设定1/4秒
		CN_ASSERT(::ReadFile(hComm_, pBuffer, dwLength, &dwReadResult, NULL));
		return dwInCount_ += dwReadResult, dwReadResult;
	}
	//! 读取串口 dwLength个字符到 pBuffer 返回实际读到的字符数  可读任意数据
	DWORD Read(LPVOID pBuffer, DWORD dwLength, DWORD dwWaitTime = INFINITE)
	{
		CN_ASSERT(pBuffer);

		if (dwOption_ & EN_RX_BUFFER)
		{
			BlockBuffer::InnerLock locker(&I_);
			return I_.Read(pBuffer, dwLength);
		}

	#ifdef CN_COMM_FOR_CE
		return ReadPort(pBuffer, dwLength, dwWaitTime);
	#else
		return ReadPort(pBuffer, dwLength, dwWaitTime);
	#endif
	}
	//! 读取串口 dwLength - 1 个ANSI字符到 szBuffer 返回 C 模式字符串指针 适合一般字符通讯
	char * ReadString(char *szBuffer, DWORD dwLength, DWORD dwWaitTime = INFINITE)
	{
		CN_ASSERT(szBuffer);
		szBuffer[Read(szBuffer, dwLength - 1, dwWaitTime)] = '\0';
		return szBuffer;
	}
	//! 读取串口 dwLength - 1 个UNICODE字符到 szBuffer 返回 C 模式字符串指针 适合一般字符通讯
	wchar_t * ReadString(wchar_t *szBuffer, DWORD dwLength, DWORD dwWaitTime = INFINITE)
	{
		CN_ASSERT(szBuffer);
		szBuffer[(Read(szBuffer, (dwLength - 1)*sizeof(wchar_t), dwWaitTime) +1)/ sizeof(wchar_t)] = L'\0';
		return szBuffer;
	}
	//! 直接写入端口
	DWORD WritePort(LPCVOID pBuffer, DWORD dwLength)
	{
		if(!CN_ASSERT(IsOpen()) || !dwLength)
			return 0;

		DWORD dwError;
		unsigned long uWriteLength = 0;

		if(::ClearCommError(hComm_, &dwError, NULL) && dwError > 0) 
			::PurgeComm(hComm_, PURGE_TXABORT); 

	#ifndef CN_COMM_FOR_CE
		if (IsOverlappedMode())//! 使用重叠IO是返回0,写出计数直接加上待写入长度,即假设写入成功
		{//! 重叠IO下超时由超时结构控制 默认为长度*1毫秒+10秒
			if(!::WriteFile(hComm_, pBuffer, dwLength, &uWriteLength, &WO_) 
				&& !CN_ASSERT(::GetLastError() == ERROR_IO_PENDING))
				uWriteLength = 0;
			else
				dwOutCount_ += dwLength;
		}
		else
	#endif //! 使用阻塞IO或WINCE下是返回实际写入长度,写出计数直接加上实际写入长度, 超时默认1/4秒
			::WriteFile(hComm_, pBuffer, dwLength, &uWriteLength, NULL), dwOutCount_ += uWriteLength;

		return uWriteLength;
	}
	//! 写 EN_TX_BUFFER 决定写入缓冲区还是直接写入端口
	DWORD Write(LPCVOID pBuffer, DWORD dwLength)
	{
		if (dwLength && (dwOption_&EN_TX_BUFFER))
		{
			BlockBuffer::InnerLock locker(&O_);

			O_.Write(pBuffer, dwLength);

			if (dwOption_ & EN_TX_THREAD)
				SetEvent(hWatchEvent_);
			else
			{
			#ifdef CN_COMM_FOR_CE
				SetCommMask(hComm_, dwWaitEvent_);
			#else
				if (IsOverlappedMode())
					SetCommMask(hComm_, dwWaitEvent_);
				else
					SetEvent(hWatchEvent_);
			#endif
			}
			return 0;
		}
			
	#ifdef CN_COMM_FOR_CE
		return WritePort(pBuffer, dwLength);
	#else
		return WritePort(pBuffer, dwLength);
	#endif
	}
	//! 写串口 ANSI字符 写ANSI C 模式字符串指针 
	DWORD Write(const char *szBuffer)
	{
		CN_ASSERT(szBuffer);
		
		return Write((LPCVOID)szBuffer, strlen(szBuffer));
	}
	//! 写串口 UNICODE字符 写ANSI C 模式字符串指针 
	DWORD Write(const wchar_t *szBuffer)
	{
		CN_ASSERT(szBuffer);
		
		return Write((LPCVOID)szBuffer, wcslen(szBuffer)*sizeof(wchar_t));
	}
	//! 写串口 szBuffer 可以输出格式字符串 包含缓冲区长度
	DWORD Write(char *szBuffer, DWORD dwLength, char * szFormat, ...)
	{
		va_list va;
		va_start(va, szFormat);
		_vsnprintf(szBuffer, dwLength, szFormat, va);
		va_end(va);
		
		return Write(szBuffer);
	}
	//! 写串口 UNICODE szBuffer 可以输出格式字符串 包含缓冲区长度
	DWORD Write(wchar_t *szBuffer, DWORD dwLength, wchar_t * szFormat, ...)
	{
		va_list va;
		va_start(va, szFormat);
		_vsnwprintf(szBuffer, dwLength, szFormat, va);
		va_end(va);
		
		return Write(szBuffer);
	}
	//! 写串口 szBuffer 可以输出格式字符串 不检查缓冲区长度 小心溢出
	DWORD Write(char *szBuffer, char * szFormat, ...)
	{
		va_list va;
		va_start(va, szFormat);
		vsprintf(szBuffer, szFormat, va);
		va_end(va);
		
		return Write(szBuffer);
	}
	//! 写串口 szBuffer 可以输出格式字符串 不检查缓冲区长度 小心溢出
	DWORD Write(wchar_t *szBuffer, wchar_t * szFormat, ...)
	{
		va_list va;
		va_start(va, szFormat);
		vswprintf(szBuffer, szFormat, va);
		va_end(va);
		
		return Write(szBuffer);
	}
	//! 强制输出队列内数据并等待
	void FlushPort()
	{
		if(CN_ASSERT(IsOpen()))
			FlushFileBuffers(hComm_);
	}
	//! 强制输出写缓冲区并强制输出队列内数据并等待
	void Flush()
	{
		if(CN_ASSERT(IsOpen()))
		{
			if (dwOption_ & EN_TX_BUFFER)
			{
				while(O_.SafeSize())
					Sleep(50);
			}

			FlushFileBuffers(hComm_);
		}
	}
	//! 抢先输出字符 
	bool TransmitChar(char c)
	{
		if (CN_ASSERT(IsOpen()))
		{
			if (::TransmitCommChar(hComm_, c))
				return dwOutCount_++, true;
		}

		return false;
	}
	//! 启动辅助线程控制 
	bool BeginThread(DWORD dwThreadOption = 0) 
	{
		DWORD dwCreationFlags;

		if(CN_ASSERT(!hWatchThread_ && !hReadThread_ && !hWriteThread_)) 
		{//! 必须是没有线程在运行状态下才可以启动线程
			bContinue_		= true;
			dwCreationFlags	= dwOption_ & EN_SUSPEND ? CREATE_SUSPENDED : 0;

			if (dwThreadOption)//! 根据配置创建监视线程,独立读或写线程
				dwOption_ |= dwThreadOption;
			
		#if defined(_MT) && !defined(CN_COMM_FOR_CE)
			unsigned int id, rid, wid;

			if (dwOption_ & EN_THREAD)
				hWatchThread_ = (HANDLE)_beginthreadex(NULL, 0, WatchThreadProc, this, dwCreationFlags, &id);

			if (dwOption_ & EN_RX_THREAD)
				hReadThread_ = (HANDLE)_beginthreadex(NULL, 0, ReadThreadProc, this, dwCreationFlags, &rid);

			if (dwOption_ & EN_TX_THREAD)
				hWriteThread_ = (HANDLE)_beginthreadex(NULL, 0, WriteThreadProc, this, dwCreationFlags, &wid);
		#else
			DWORD id, rid, wid;

			if (dwOption_ & EN_THREAD)
				hWatchThread_ = ::CreateThread(NULL, 0, WatchThreadProc, this, dwCreationFlags , &id); 

			if (dwOption_ & EN_RX_THREAD)
				hReadThread_ = ::CreateThread(NULL, 0, ReadThreadProc, this, dwCreationFlags, &rid); 

			if (dwOption_ & EN_TX_THREAD)
				hWriteThread_ = ::CreateThread(NULL, 0, WriteThreadProc, this, dwCreationFlags, &wid); 
		#endif

			if (dwOption_ & EN_THREAD)
			{
				CN_ASSERT(hWatchThread_ != NULL);
				hWatchThreadId_ = id;

				if (!hWatchThread_)
				{
					EndThread();
					return false;
				}
				else
				{
					if (dwOption_ & EN_ABOVE_NORMAL)
						SetThreadPriority(hWatchThread_, THREAD_PRIORITY_ABOVE_NORMAL);
				}
			}

			if (dwOption_ & EN_RX_THREAD)
			{
				CN_ASSERT(hReadThread_ != NULL);
				hReadThreadId_	= rid;

				if (!hReadThreadId_)
				{
					EndThread();
					return false;
				}
				else
				{
					if (dwOption_ & EN_ABOVE_NORMAL)
						SetThreadPriority(hReadThread_, THREAD_PRIORITY_ABOVE_NORMAL);
				}
			}

			if (dwOption_ & EN_TX_THREAD)
			{
				CN_ASSERT(hWriteThread_ != NULL);
				hWriteThreadId_	= wid;

				if (!hWriteThreadId_)
				{
					EndThread();
					return false;
				}
				else
				{
					if (dwOption_ & EN_ABOVE_NORMAL)
						SetThreadPriority(hWriteThread_, THREAD_PRIORITY_ABOVE_NORMAL);
				}
			}

			return true; 
		}

		return false;
	}
	//! 暂停线程
	bool SuspendThread(int iOption = EN_THREAD)
	{
		return ::SuspendThread(GetThread(iOption)) != 0xFFFFFFFF;
	}
	//! 恢复线程
	bool ResumeThread(int iOption = EN_THREAD)
	{
		return ::ResumeThread(GetThread(iOption)) != 0xFFFFFFFF;
	}
	//! 终止线程
	bool EndThread(DWORD dwWaitTime = 500)
	{
		if(hWatchThread_ || hReadThread_ || hWriteThread_) 
		{
			if ((dwOption_&EN_FLUSH_ALL) && (dwOption_&EN_TX_BUFFER))
			{//! 如果启用EN_FLUSH_ALL,将循环等待写缓冲区清空,如果写入线程不能正常工作,将挂起
				while(O_.Size())
					Sleep(50);
			}

			bContinue_ = false;

		#ifdef CN_COMM_FOR_CE
			::SetCommMask(hComm_, 0);
		#else
			if (IsOverlappedMode())
				::SetCommMask(hComm_, 0);
		#endif

			if (hWatchThread_)
			{
				SetEvent(hWatchEvent_);
				if(::WaitForSingleObject(hWatchThread_, dwWaitTime) != WAIT_OBJECT_0)
					if(!::TerminateThread(hWatchThread_, 0))
						return false;

				::CloseHandle(hWatchThread_);
				hWatchThread_ = NULL;
			}

			if (hReadThread_)
			{
				SetEvent(hReadEvent_);
				if(::WaitForSingleObject(hReadThread_, dwWaitTime) != WAIT_OBJECT_0)
					if(!::TerminateThread(hReadThread_, 0))
						return false;

				::CloseHandle(hReadThread_);
				hReadThread_ = NULL;
			}
			
			if (hWriteThread_)
			{
				SetEvent(hWriteEvent_);
				if(::WaitForSingleObject(hWriteThread_, dwWaitTime) != WAIT_OBJECT_0)
					if(!::TerminateThread(hWriteThread_, 0))
						return false;

				::CloseHandle(hWriteThread_);
				hWriteThread_ = NULL;
			}
				
			return true;
		}

		return false;
	}
	//! 关闭串口 同时也关闭关联线程
	virtual void Close(DWORD dwWaitTime = 500)
	{
		if(IsOpen())  
		{
			EndThread(dwWaitTime);//! 同步结束线程

			if (dwOption_&EN_FLUSH || dwOption_&EN_FLUSH_ALL)
				FlushFileBuffers(hComm_);

			::PurgeComm(hComm_, PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_RXABORT); 
			::CloseHandle(hComm_);
			hComm_ = INVALID_HANDLE_VALUE;
		}
	}
	//! 锁定
	void Lock()							
	{	
		::EnterCriticalSection(&CS_);		
	}
	//! 解锁
	void Unlock()						
	{	
		::LeaveCriticalSection(&CS_);		
	}
	//! 自动锁 用于函数内部 利用对象的生命周期完成锁定及解锁
	struct InnerLock
	{
		CnComm* ptr;//!< CnComm 对象指针
		//! 锁定
		InnerLock(CnComm* p) : ptr(p)	
		{	
			ptr->Lock();						
		}
		//! 解锁
		~InnerLock()					
		{	
			ptr->Unlock();						
		}
	};
	//! 获得串口参数 DCB
	DCB *GetState(DCB *pDcb = NULL)
	{
		return CN_ASSERT(IsOpen()) && ::GetCommState(hComm_, pDcb == NULL ? &DCB_ : pDcb) == TRUE ? (pDcb == NULL ? &DCB_ : pDcb) : NULL;
	}
	//! 设置串口参数 DCB
	bool SetState(DCB *pDcb = NULL)
	{
		return CN_ASSERT(IsOpen()) ? ::SetCommState(hComm_, pDcb == NULL ? &DCB_ : pDcb) == TRUE : false;
	}
	//! 设置串口参数:波特率,停止位,等 ***
	bool SetState(DWORD dwBaudRate, BYTE btParity = NOPARITY, BYTE btByteSize = 8, BYTE btStopBits = ONESTOPBIT)
	{
		if(CN_ASSERT(IsOpen()))
		{
			if(::GetCommState(hComm_, &DCB_) != TRUE)
				return false;

			DCB_.BaudRate = dwBaudRate;
			DCB_.ByteSize = btByteSize;
			DCB_.Parity   = btParity;
			DCB_.StopBits = btStopBits;
			DCB_.fParity  = (btParity != NOPARITY);

			return ::SetCommState(hComm_, &DCB_) == TRUE;
		}
		return false;
	}
#ifndef CN_COMM_FOR_CE
	//! 设置串口参数 支持设置字符串 "9600, n, 8, 1"
	bool SetState(LPCTSTR szSetStr) 
	{
		if(CN_ASSERT(IsOpen()))
		{
			if(!::GetCommState(hComm_, &DCB_))
				return false;

			if(!BuildCommDCB(szSetStr, &DCB_))
				return false;

			DCB_.fParity  = (DCB_.Parity != NOPARITY);
			return ::SetCommState(hComm_, &DCB_) == TRUE;
		}

		return false;
	}
#endif
	//! 获得超时结构
	LPCOMMTIMEOUTS GetTimeouts(LPCOMMTIMEOUTS lpCO = NULL)
	{
		return CN_ASSERT(IsOpen()) && ::GetCommTimeouts(hComm_, lpCO ? lpCO : &CO_) == TRUE  ? (lpCO ? lpCO : &CO_) : NULL;
	}
	//! 设置超时
	bool SetTimeouts(LPCOMMTIMEOUTS lpCO = NULL)
	{
		return CN_ASSERT(IsOpen()) ? ::SetCommTimeouts(hComm_, lpCO ? lpCO : &CO_) == TRUE : false;
	}
	//! 设置串口的I/O缓冲区大小
	bool Setup(DWORD dwInputSize = 4096, DWORD dwOutputSize = 4096)
	{
		return CN_ASSERT(IsOpen()) ? ::SetupComm(hComm_, dwInputSize, dwOutputSize) == TRUE : false; 
	}
	//! 调整端口功能
	bool Escape(DWORD dwType)
	{
		return CN_ASSERT(IsOpen()) ? EscapeCommFunction(hComm_, dwType) != 0 : false;
	}
	//! 获得调制解调器相关信号状态
	DWORD GetModemStatus()
	{
		DWORD dwModemStat = 0;
		return CN_ASSERT(IsOpen()) && GetCommModemStatus(hComm_, &dwModemStat) ? dwModemStat : 0;
	}
	//! 获得端口参数 \param[in] pCP 结构指针 如果pCP==NULL, CnComm将从堆分配内存, 并由CnComm负责释放, 用户不需要自己释放内存
	LPCOMMPROP GetProperties(LPCOMMPROP pCP = NULL)	
	{
		if (CN_ASSERT(IsOpen()))
		{
			if (!pCP)
			{
			#ifdef CN_COMM_FOR_CE
				USHORT dwSize = sizeof(COMMPROP);
			#else
				USHORT dwSize = sizeof(COMMPROP) + sizeof(MODEMDEVCAPS);
			#endif

				if (!pCP_)
					pCP_ = (LPCOMMPROP) new BYTE[dwSize];

				if (pCP_)
				{
					memset(pCP_, 0, dwSize);

					pCP_->wPacketLength = dwSize;
				#ifndef CN_COMM_FOR_CE
					pCP_->dwProvSubType = PST_MODEM;
				#endif
					pCP_->dwProvSpec1	= COMMPROP_INITIALIZED;
					pCP = pCP_;
				}
			}
		}

		return pCP && GetCommProperties(hComm_, pCP) ? pCP : NULL;
	}
	//! 获取事件标识
	DWORD GetMask()
	{
		DWORD dwMask;
		return CN_ASSERT(IsOpen()) && GetCommMask(hComm_, &dwMask) ? dwMask : 0;	
	}
	//! 清除端口缓冲区
	bool Purge(DWORD dwPara = PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR)
	{
		return CN_ASSERT(IsOpen()) ? ::PurgeComm(hComm_, dwPara)==TRUE : false;
	}
	//! 获得错误代码
	DWORD ClearError()
	{
		DWORD dwError;
		return CN_ASSERT(IsOpen()) && ::ClearCommError(hComm_, &dwError, NULL) ? dwError : 0;
	}
	//! 获得读物理缓冲区的字符数
	DWORD GetQueueCount(bool bInput = true)
	{
		COMSTAT Stat;
		DWORD dwError;
		
		return CN_ASSERT(IsOpen()) && ::ClearCommError(hComm_, &dwError, &Stat) ? (bInput ? Stat.cbInQue : Stat.cbOutQue) : (DWORD)-1L;
	}
	//! 调制解调器 CTS ON
	bool CheckCTS()				
	{	
		return (GetModemStatus()&MS_CTS_ON) != 0;		
	}
	//! 调制解调器 DSR ON
	bool CheckDSR()				
	{	
		return (GetModemStatus()&MS_DSR_ON) != 0;		
	}
	//! 调制解调器 Ring ON
	bool CheckRING()				
	{	
		return (GetModemStatus()&MS_RING_ON) != 0;		
	}
	//! 调制解调器 RLSD ON
	bool CheckRLSD()				
	{	
		return (GetModemStatus()&MS_RLSD_ON) != 0;		
	}
	//! DTR 电平控制
	bool SetDTR(bool bSetOrClr = true)	
	{	
		return Escape(bSetOrClr ? SETDTR : CLRDTR);		
	}
	//! RTS 电平控制
	bool SetRTS(bool bSetOrClr = true)	
	{	
		return Escape(bSetOrClr ? SETRTS : CLRRTS);		
	}
	//! 调制解调器
	bool SetBreak(bool bSetOrClr = true)	
	{	
		return Escape(bSetOrClr ? SETBREAK : CLRBREAK);	
	}
#ifdef CN_COMM_FOR_CE
	//! WINCE
	bool SetIR(bool bSetOrClr)	
	{	
		return Escape(bSetOrClr ? SETIR : CLRIR);	
	}
#endif
	//! 流控制 SETXON SETXOFF
	bool SetX(bool bOnOrOff)				
	{	
		return Escape(bOnOrOff ? SETXON : SETXOFF);							
	}
	//! 根据通讯特点开发的缓冲区类 单向链表内存块 有一些扩展以支持和API挂接 
	class BlockBuffer
	{
	public:
		//! 缓冲区内存块
		struct Block
		{
			DWORD			B_;		//!< 开始偏移
			DWORD			E_;		//!< 结束偏移
			DWORD			S_;		//!< 块大小 内存块最大值不限 内存块最小值由CN_COMM_BUFFER_MIN_BLOCK_SIZE决定 
			Block*			N_;		//!< 下一个块指针 
			BYTE			P_[4];	//!< 缓冲区指针 实际大小由S_决定 
		
			//! 容量
			DWORD Capacity()		{	return S_;			}
			//! 实际大小
			DWORD Size()			{	return E_ - B_;		}
			//! 开始缓冲区指针
			BYTE* Begin()			{	return P_ + B_;		}
			//! 末端缓冲区指针
			BYTE* End()				{	return P_ + E_;		}
			//! 下一个块
			Block* Next()			{	return N_;			}
			//! 是否空
			bool IsEmpty()			{	return B_ == E_;	}
			//! 空闲大小
			DWORD FreeSize()		{	return S_ - E_;		}
		};

		//! 用于缓冲区单向迭代子
		struct Iterator
		{
			BlockBuffer*	P_;		//!< 对象指针
			Block*			B_;		//!< 当前块指针
			DWORD			I_;		//!< 当前块偏移
			DWORD			O_;		//!< 全缓冲区偏移

			//! 构造
			Iterator(BlockBuffer *P = NULL, Block* B = NULL, DWORD I = 0, DWORD O = 0) 
				: P_(P), B_(B), I_(I), O_(O)	
			{										
			}
			//! 是否有效
			operator bool()				
			{	
				return B_ && I_<B_->E_&&I_>=B_->B_;	
			}
			//! 是否可写
			bool CanWrite()				
			{	
				return B_ && I_ < B_->S_;			
			}
			//! 取值引用
			BYTE& operator *()			
			{	
				CN_ASSERT( P_ && B_ && I_<B_->E_&&I_>=B_->B_);
				return B_->P_[I_];					
			}
			//! 移动迭代子 ++Iter;
			Iterator& operator ++ ()		
			{
				return operator +=(1);			
			}
			//! 移动迭代子 Iter++;
			Iterator& operator ++ (int)	
			{
				return operator +=(1);				
			}
			//! 移动迭代子  \param dwOffset 为偏移量
			Iterator& operator += (DWORD dwOffset)
			{
				while (dwOffset) 
				{
					if (I_+dwOffset < B_->E_)
						I_ += dwOffset, O_ += dwOffset, dwOffset = 0; 
					else
						dwOffset -= B_->E_-I_, I_ += B_->E_-I_, O_ += B_->E_-I_, B_ = B_->N_, I_ = 0;
				}

				return *this;
			}
			//! 比较
			bool operator == (const Iterator& iter)
			{
				return (P_ == iter.P_) && (B_ == iter.B_) && (I_ == iter.I_);
			}
		};
		//! 友元
		friend struct Iterator;
		//! 锁定
		void Lock()							
		{	
			::EnterCriticalSection(&C_);			
		}
		//! 解锁
		void Unlock()						
		{	
			::LeaveCriticalSection(&C_);			
		}
		//! 自动锁
		struct InnerLock
		{
			BlockBuffer* ptr;//!<对象指针
			///锁定
			InnerLock(BlockBuffer* p) : ptr(p)	
			{
				if (ptr)
					ptr->Lock();						
			}
			///解锁
			~InnerLock()					
			{
				if (ptr)
					ptr->Unlock();						
			}
		};
		//! 构造
		BlockBuffer()
		{
			::InitializeCriticalSection(&C_);
			S_ = 0, F_ = L_ = NULL, M_ = CN_COMM_BUFFER_MIN_BLOCK_SIZE;
		}
		//! 析构自动释放空间
		virtual ~BlockBuffer()
		{
			Clear();
			::DeleteCriticalSection(&C_);
		}
		//! 获得起始迭代子
		Iterator Begin()					
		{	
			return Iterator(this, F_, F_? F_->B_ : 0, 0);	
		}
		//! 设置块的最小长度
		void SetMinBlockSize(DWORD dwMinSize)
		{
			M_ = dwMinSize;
		}
		//! 获得块的最小长度
		DWORD GetMinBlockSize()
		{
			return M_;
		}
		//! 缓冲区内数据字节数
		DWORD Size()						
		{	
			return S_;								
		}
		//! 缓冲区大小
		DWORD SafeSize()						
		{
			InnerLock lock(this);
			return S_;								
		}
		//! 写入ANSI字符串缓冲区 \sa Write(LPCVOID lpBuf, DWORD dwSize)
		DWORD Write(const char* lpBuf)
		{
			return Write(lpBuf, strlen(lpBuf));
		}
		//! 写入UNICODE字符串缓冲区 \sa Write(LPCVOID lpBuf, DWORD dwSize)
		DWORD Write(const wchar_t* lpBuf)
		{
			return Write(lpBuf, wcslen(lpBuf)*sizeof(wchar_t));
		}
		//! 写入缓冲区 \param[out] lpBuf 目标缓冲区 \param[in] dwSize 数据字节数 \return 实际复制数据字节数
		DWORD Write(LPCVOID lpBuf, DWORD dwSize)
		{
			DWORD dwTemp = dwSize, dwFree = FreeSize(), dwCopy = 0;
			
			if (dwFree)//! 首先查找末尾空闲,并写入数据
			{
				dwCopy = dwFree > dwSize ? dwSize : dwFree;
				memcpy(L_->P_ + L_->E_, lpBuf, dwCopy);
				dwTemp -= dwCopy, L_->E_ += dwCopy;
			}

			if (dwTemp)//! 剩余的数据分配新的空间并写入
			{
				memcpy(NewBlock(dwSize)->P_, ((LPBYTE)lpBuf )+ dwCopy, dwTemp);
				L_->E_ += dwTemp;
			}

			S_ += dwSize;
			return dwSize;
		}
		//! 线程安全写入缓冲区 \sa Write(LPCVOID lpBuf, DWORD dwSize)
		DWORD SafeWrite(LPCVOID lpBuf, DWORD dwSize)
		{
			InnerLock lock(this);
			return Write(lpBuf, dwSize);
		}
		//! 线程安全写入ANSI字符串缓冲区 \sa Write(LPCVOID lpBuf, DWORD dwSize)
		DWORD SafeWrite(const char* lpBuf)
		{
			InnerLock lock(this);
			return Write(lpBuf, strlen(lpBuf));
		}
		//! 线程安全写入UNICODE字符串缓冲区 \sa Write(LPCVOID lpBuf, DWORD dwSize)
		DWORD SafeWrite(const wchar_t* lpBuf)
		{
			InnerLock lock(this);
			return Write(lpBuf, wcslen(lpBuf)*sizeof(wchar_t));
		}
		//! 复制数据 \param[out] lpBuf 目标缓冲区 \param[in] dwSize 数据字节数 \param[in] dwStart 源缓冲区开始偏移值 \return 实际复制数据字节数
		DWORD Copy(LPVOID lpBuf, DWORD dwSize, DWORD dwStart = 0)
		{
			CN_ASSERT(lpBuf);

			if (!F_ || !dwSize || dwStart >= S_)
				return 0;

			DWORD dwTemp, dwIndex;
			Block * pCur = F_, *pNext = F_->N_;

			for (dwTemp = 0, dwIndex = pCur->B_; dwTemp < dwStart; pCur = pCur->N_, dwIndex = pCur ? pCur->B_ : 0)
			{
				if (dwStart - dwTemp < pCur->E_ - pCur->B_)
				{
					dwIndex = pCur->B_ + dwStart - dwTemp;
					break;
				}

				dwTemp += pCur->E_ - pCur->B_;
			}

			for (dwTemp = 0; dwTemp < dwSize && pCur; pCur = pCur->N_, dwIndex = pCur ? pCur->B_ : 0)
			{
				if (dwSize - dwTemp < pCur->E_ - dwIndex)
				{
					memcpy((LPBYTE)lpBuf+dwTemp, pCur->P_ + dwIndex, dwSize - dwTemp );
					dwTemp = dwSize;
					break;
				}
				else
				{
					memcpy((LPBYTE)lpBuf+dwTemp, pCur->P_ + dwIndex, pCur->E_ - dwIndex);
					dwTemp += pCur->E_ - dwIndex;
				}
			}

			return dwTemp;
		}
		//! 线程安全复制数据 \sa Copy(LPVOID lpBuf, DWORD dwSize, DWORD dwStart=0)
		DWORD SafeCopy(LPVOID lpBuf, DWORD dwSize, DWORD dwStart = 0)
		{
			InnerLock lock(this);
			return Copy(lpBuf, dwSize, dwStart);
		}
		/*! \param[out] lpBuf 目标缓冲区 为NULL时仅删除不复制数据  \param[in] dwSize 操作数据字节数 \return 实际复制或删除字节数 */
		//! 复制并删除缓冲区的数据到lpBuf
		DWORD Read(LPVOID lpBuf, DWORD dwSize)
		{
			DWORD dwTemp = 0, dwCopy;

			for (Block * pCur = F_, *pNext = NULL; dwTemp<dwSize && pCur; pCur = pNext)
			{
				if (dwSize-dwTemp > pCur->E_-pCur->B_ )
					dwCopy = pCur->E_ - pCur->B_; 
				else
					dwCopy = dwSize - dwTemp;

				if (lpBuf) 
					memcpy((LPBYTE)lpBuf+dwTemp, pCur->P_ + pCur->B_, dwCopy);

				pNext = pCur->N_, dwTemp += dwCopy;

				if (dwCopy == pCur->E_-pCur->B_)
				{//! 删除回收完全空闲块, 当一般保留1个块, 在小于4*CN_COMM_BUFFER_MIN_BLOCK_SIZE的情况下 
					if (pNext || pCur->S_>(M_<<2))
					{
						delete[] (BYTE*)pCur;
						F_ = pNext;
						if (!F_)
							L_ = NULL;
					}
					else
						pCur->B_ = pCur->E_ = 0;
				}
				else
					pCur->B_ += dwCopy;

				S_ -= dwCopy;
			}

			return dwTemp;
		}
		//! 读入ANSI字符串缓冲区
		char* ReadString(char* lpBuf, DWORD dMaxSize)
		{
			lpBuf[Read(lpBuf, dMaxSize)] = '\0';
			return lpBuf;
		}
		//! 读入UNICODE字符串缓冲区
		wchar_t* ReadString(wchar_t* lpBuf, DWORD dMaxSize)
		{
			lpBuf[(Read(lpBuf, dMaxSize*sizeof(wchar_t))+1) / sizeof(wchar_t)] = L'\0';
			return lpBuf;
		}
		//! 线程安全的读函数
		DWORD SafeRead(LPVOID lpBuf, DWORD dwSize)
		{
			InnerLock lock(this);
			return  Read(lpBuf, dwSize);
		}
		//! 线程安全读入ANSI字符串缓冲区
		char* SafeReadString(char* lpBuf, DWORD dMaxSize)
		{
			InnerLock lock(this);
			return ReadString(lpBuf, dMaxSize);
		}
		//! 线程安全读入UNICODE字符串缓冲区
		wchar_t* SafeReadString(wchar_t* lpBuf, DWORD dMaxSize)
		{
			InnerLock lock(this);
			return ReadString(lpBuf, dMaxSize);
		}
		//! 清除 \param bDeleteAll 为true时释放所有内存, 否则保留一个内存块以提高效率
		void Clear(bool bDeleteAll = false)
		{
			if (F_ && (F_==L_) && F_->S_>(M_<<2))
			{
                DWORD S = F_->S_;
                memset(F_, 0, sizeof(Block)), F_->S_ = S;
            }
			else
			{
				for (Block* t = F_;  t; delete  F_)
					F_ = t, t = t->N_;

				F_ = L_ = NULL, S_ = 0;
			}
		}
		//! 线程安全的清除函数  \sa void Clear(bool bDeleteAll = false)
		void SafeClear(bool bDeleteAll = false)
		{
			InnerLock lock(this);
			Clear(bDeleteAll);
		}
		//! 获得内存块指针 \param bFirst 为true时获得链表头部指针否则获得链表尾部指针
		Block* GetBlockPtr(bool bFirst = true)	
		{	
			return bFirst ? F_ : L_;						
		}
		//! 缓冲区尾部的空闲空间
		DWORD FreeSize()					
		{	
			return L_ ? L_->S_-L_->E_ : 0 ;			
		}
		//! 获得供API插入数据的直写缓冲区 传入所需大小dwSize 空闲不足分配新块 传入0返回尾部的空闲指针 尾部无空闲返回NULL 
		LPVOID GetFreePtr(DWORD dwSize = 0)
		{
			if (dwSize)
				return FreeSize() > dwSize ? L_->P_ + L_->E_ : NewBlock(dwSize)->P_;
			else
				return L_ ? L_->P_ + L_->E_ : NULL;
		}
		/*! \param[in] dwSize 传入增量并非全量
			\code strcpy(GetFreePtr(100), "test"), Release(4); //获取100字节的缓冲区 拷入四个字节 调整大小增加4个字节 \endcode
		*/
		//! 利用API直接写入用GetFreePtr()获得空闲指针, 同步调整缓冲区大小 
		DWORD Release(DWORD dwSize)
		{
			return (dwSize <= L_->S_) ? (L_->E_ += dwSize, S_ += dwSize, dwSize) : 0;		
		}
		//! 获得第一个有效块的缓冲区指针
		LPVOID GetPtr()
		{
			return F_ ? F_->P_ + F_->B_ : NULL;
		}
		//! 获得第一个有效块的缓冲区指针指向的数据大小
		DWORD GetPtrSize()
		{
			return F_ ? F_->E_ - F_->B_ : 0;
		}
		//! 数组访问 如果块数超过1 效率很低 推荐用迭代子访问可以获得理想性能
		BYTE& operator[](DWORD dwOffset)
		{
			CN_ASSERT(F_);

			if (F_ == L_)	
			{
				CN_ASSERT(F_->S_ > dwOffset);
				return F_->P_[dwOffset];
			}
			else			
			{
				Iterator iter = Begin();
				iter += dwOffset;
				CN_ASSERT(iter);
				return *iter;
			}
		}
		
	protected:

		//! 新建块 自动添加在尾部
		Block* NewBlock(DWORD dwSize)
		{
			dwSize = dwSize < M_ ? M_ : dwSize;
			Block * pNew = (Block *) new BYTE[sizeof(Block) - 4 + dwSize];

			if (pNew)
			{
				memset(pNew, 0, sizeof(Block));
				pNew->S_ = dwSize;

				if (L_)
					L_->N_ = pNew, L_ = pNew;
				else
					F_ = L_ = pNew;
			}
			
			return pNew;
		}

		Block*				F_;//!< 头指针
		Block*				L_;//!< 尾指针
		DWORD				S_;//!< 大小
		DWORD				M_;//!< 块最小长度
		CRITICAL_SECTION	C_;//!< 锁结构
	};

#if defined(CN_COMM_MFC_EXCEPTION)
	/*! 需要定义宏 CN_COMM_MFC_EXCEPTION CN_ASSERT \n 将使用throw new MfcException(msg);语句抛出MFC异常(VC++) */
	//! 用于MFC的异常  
	class MfcException : public CException
	{
	public:
		//! 构造函数,要求CException自动析构
		MfcException(LPCTSTR szMsg) : CException(TRUE)
		{
			lstrcpy(szMsg_, szMsg);

		#ifdef _DEBUG
			CException::m_bReadyForDelete = TRUE;
		#endif
		}
		//! 错误提示信息
		BOOL GetErrorMessage( LPTSTR lpszError, UINT nMaxError, PUINT pnHelpContext = NULL )
		{
		#ifndef CN_COMM_FOR_CE
			lstrcpyn(lpszError, szMsg_, nMaxError);
		#else
			_tcsncpy(lpszError, szMsg_, nMaxError - 1);
			lpszError[nMaxError - 1] = _T('\0');
		#endif
			return TRUE;
		}
	protected:
		TCHAR szMsg_[256]; //!< 错误信息 格式:CN_ASSERT(表达式) failed; CnComm(行号); Code(GetLastError()); 错误代码描述
	};
#endif

	//! 用户启用异常 则抛出异常; 未启用异常: DEBUG版本 控制台版本输出错误信息 并退出; Release版本弹出提示框并响应用户要求
	static bool Assert(LPCTSTR szMessage)
	{
	#if defined(_DEBUG) || defined(CN_COMM_STD_EXCEPTION) || defined(CN_COMM_VCL_EXCEPTION) || defined(CN_COMM_MFC_EXCEPTION)
		TCHAR szMsg[256];
		DWORD dwError, dwLength;
		
		_tcscpy(szMsg, szMessage);

		dwError = GetLastError();
		if (dwError)//! 错误代码(GetLastError())不为 0 输出错误描述  
		{
			dwLength = _tcslen(szMsg);
			_sntprintf(szMsg + dwLength, 256 - _tcslen(szMsg), _T("Code:%d; "), dwError);
			dwLength = _tcslen(szMsg);

			FormatMessage(
				FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
				NULL,
				dwError,
				MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),	//! 错误描述采用本地语言
				szMsg + dwLength - 1,							
				256 - dwLength - 1,									
				NULL
				);
		}
	#else 
		;// Release版本 什么都不做  预留
	#endif

	#if	defined(CN_COMM_STD_EXCEPTION)

		#ifdef _UNICODE
			char szTemp[512] = {0};
			WideCharToMultiByte(CP_ACP, 0, szMsg, -1, szTemp, wcslen(szMsg)*sizeof(wchar_t), NULL, NULL);
			throw std::runtime_error(szTemp);
		#else
			throw std::runtime_error(szMsg);
		#endif

	#elif defined(CN_COMM_VCL_EXCEPTION)

		throw Exception(szMsg);

	#elif defined(CN_COMM_MFC_EXCEPTION)

		throw (new MfcException(szMsg));

	#elif defined(_DEBUG)

		OutputDebugString(szMsg);
		#ifdef _CONSOLE
			// 需要 setlocale(LC_ALL, "chs"); 控制台才可以正确输出UNICODE中文 这里转换ANSI 避免这样问题
			#ifdef _UNICODE
				char szTemp[512] = {0};
				WideCharToMultiByte(CP_ACP, 0, szMsg, -1, szTemp, wcslen(szMsg)*sizeof(wchar_t), NULL, NULL);
				fprintf(stderr, szTemp);
			#else
				fprintf(stderr, szMsg);
			#endif

			system("pause");
			exit(1);
		#else
			switch(MessageBox(NULL, szMsg, _T("CN_ASSERT"), MB_ABORTRETRYIGNORE))
			{
			case IDABORT:
				exit(1);

			case IDRETRY:
				DebugBreak();
				break;

			case IDIGNORE:
				break;
			}
		#endif

	#else 
		;// Release版本 什么都不做  预留
	#endif
		return false;
	}

protected:

	DWORD				dwOption_;			//!< 关键模式配置 在构造函数中设定
	HANDLE				hComm_;				//!< 串口句柄
	DWORD				dwPort_;			//!< 串口号 0为特殊串口 -1为无效 主要终于消息通知甄别
	TCHAR				szName_[64];		//!< 保存串口名称 类似COM1的字符串
	CRITICAL_SECTION	CS_;				//!< 临界互斥锁
	DCB					DCB_;				//!< 波特率,停止位,等   
	COMMTIMEOUTS		CO_;				//!< 超时结构 
	COMMPROP*			pCP_;				//!< 串口参数

	BlockBuffer			I_;					//!< 读缓冲区
	BlockBuffer			O_;					//!< 写缓冲区
	DWORD				dwInCount_;			//!< 读计数
	DWORD				dwOutCount_;		//!< 写计数

	bool				bContinue_;			//!< 线程继续运行循环标志
	DWORD				dwWaitEvent_;		//!< WaitCommEvent 的监视事件

	HANDLE				hWatchThread_;		//!< 监视辅助线程
	DWORD				hWatchThreadId_;	//!< 监视辅助线程 ID
	HANDLE				hWatchEvent_;		//!< 通知监视线程

	HANDLE				hReadThread_;		//!< 接收辅助线程 实现双工提高效率
	DWORD				hReadThreadId_;		//!< 接收辅助线程 ID
	HANDLE				hReadEvent_;		//!< 通知接收线程

	HANDLE				hWriteThread_;		//!< 发送辅助线程 实现双工提高效率
	DWORD				hWriteThreadId_;	//!< 发送辅助线程 ID
	HANDLE				hWriteEvent_;		//!< 通知发送线程

	HWND				hNotifyWnd_;		//!< 通知窗口
	DWORD				hNotifyThreadId_;	//!< 通知线程
	DWORD				dwNotifyNum_;		//!< 接受多少字节(>=dwNotifyNum_)发送通知消息

#ifndef CN_COMM_FOR_CE
	OVERLAPPED			RO_;				//!< 重叠I/O ReadFile
	OVERLAPPED			WO_;				//!< 重叠I/O WriteFile
	OVERLAPPED			EO_;				//!< 重叠I/O WaitCommEvent 
#endif

	//! 初始化
	virtual void Init() 
	{
		::InitializeCriticalSection(&CS_);

		memset(szName_, 0, 64*sizeof(TCHAR));

		memset(&DCB_,	0, sizeof(DCB_));
		DCB_.DCBlength	= sizeof(DCB_);

		hComm_				= INVALID_HANDLE_VALUE;
		dwPort_				= (DWORD)-1;
		dwOutCount_			= 0;
		dwInCount_			= 0;
		
		dwWaitEvent_		= CN_COMM_WAIT_EVENT;
		hWatchThread_		= NULL;
		hReadThread_		= NULL;
		hWriteThread_		= NULL;
		hWatchThreadId_		= 0;
		hReadThreadId_		= 0;
		hWriteThreadId_		= 0;
		
		hNotifyWnd_			= NULL;
		dwNotifyNum_		= 0;
		hNotifyThreadId_	= 0;
		pCP_				= NULL;

	#ifndef CN_COMM_FOR_CE
		memset(&RO_, 0, sizeof(RO_));
		memset(&WO_, 0, sizeof(WO_));
		memset(&EO_, 0, sizeof(EO_));
		
		RO_.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
		CN_ASSERT(RO_.hEvent != NULL); 
		
		WO_.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
		CN_ASSERT(WO_.hEvent != NULL);
		
		EO_.hEvent= ::CreateEvent(NULL, TRUE, FALSE, NULL);
		CN_ASSERT(EO_.hEvent != NULL); 
	#endif

		hWatchEvent_	= ::CreateEvent(NULL, TRUE, FALSE, NULL);
		CN_ASSERT(hWatchEvent_ != NULL); 
		hReadEvent_		= ::CreateEvent(NULL, TRUE, FALSE, NULL);
		CN_ASSERT(hReadEvent_ != NULL); 
		hWriteEvent_	= ::CreateEvent(NULL, TRUE, FALSE, NULL);
		CN_ASSERT(hWriteEvent_ != NULL); 
	} 
	//! 析构
	virtual void Destroy()
	{
	#ifndef CN_COMM_FOR_CE
		if(RO_.hEvent != NULL)
			CloseHandle(RO_.hEvent);
		
		if(WO_.hEvent != NULL)
			CloseHandle(WO_.hEvent);
		
		if(EO_.hEvent != NULL)
			CloseHandle(EO_.hEvent);
	#endif

		if(hWatchEvent_ != NULL)
			CloseHandle(hWatchEvent_);

		if(hReadEvent_ != NULL)
			CloseHandle(hReadEvent_);

		if(hWriteEvent_ != NULL)
			CloseHandle(hWriteEvent_);

		if (pCP_)
			delete[] ((BYTE*)pCP_);

		::DeleteCriticalSection(&CS_);
	}
	//! 绑定串口 
	void BindPort(DWORD dwPort)
	{
		dwPort_ = dwPort;

	#if defined(CN_COMM_FOR_CE)
		wsprintf(szName_, _T("COM%d:"), dwPort);
	#else
		wsprintf(szName_, _T("\\\\.\\COM%d"), dwPort);
	#endif
	}
	//! 打开串口 
	virtual bool OpenPort()
	{
		CN_ASSERT(!IsOpen());

		if(IsOpen())
			Close();
		
		hComm_ = ::CreateFile(
			szName_,
			GENERIC_READ | GENERIC_WRITE,
			0,
			NULL,
			OPEN_EXISTING,
			FILE_ATTRIBUTE_NORMAL | (IsOverlappedMode() ? FILE_FLAG_OVERLAPPED : 0),
			NULL
			);
		
		return IsOpen();
	}
	//! 设置串口 
	virtual bool SetupPort()
	{
		if(!CN_ASSERT(IsOpen()))
			return false;

		#if defined(CN_COMM_FOR_CE)
			::SetupComm(hComm_, 4096, 4096);
		#else
			if(!CN_ASSERT(::SetupComm(hComm_, 4096, 4096)))//! 配置端口发送接收队列大小, 读4096字节, 写4096字节, 阻塞I/O模式发送队列无意义
			return false; 
		#endif
		
		if(!CN_ASSERT(::GetCommTimeouts(hComm_, &CO_)))
			return false;

		CO_.ReadIntervalTimeout			= 100;//! 配置超时结构 字符最小间隔100ms
		CO_.ReadTotalTimeoutMultiplier	= 0;
		CO_.ReadTotalTimeoutConstant	= IsOverlappedMode() ? 500 : 250;//! 读超时 重叠I/O模式下500毫秒 阻塞I/O模式下250毫秒
		CO_.WriteTotalTimeoutMultiplier = IsOverlappedMode() ? 1 : 0;
		CO_.WriteTotalTimeoutConstant	= IsOverlappedMode() ? 10000 : 250;//! 写超时 重叠I/O模式下(10000+1×字节数)毫秒 阻塞I/O模式下250毫秒

		if(!CN_ASSERT(::SetCommTimeouts(hComm_, &CO_)))
			return false; 
		
		if(!CN_ASSERT(::PurgeComm(hComm_, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR )))//! 清除端口
			return false; 
		
		return true;
	} 
	//! 将端口数据读入缓冲区的
	DWORD PortToBuffer(DWORD dwPortByteNum)
	{
		BlockBuffer::InnerLock locker(&I_);
		return dwPortByteNum ? I_.Release(ReadPort(I_.GetFreePtr(dwPortByteNum), dwPortByteNum)) : 0;
	}
	//! 将缓冲区的数据写入端口 
	DWORD BufferToPort(DWORD dwMaxSize = 1024)
	{
		if (IsOverlappedMode())
		{
			BlockBuffer::InnerLock locker(&O_);

			if (!O_.Size())
				return 0;

			DWORD dwWrite = dwMaxSize > O_.GetPtrSize() ? O_.GetPtrSize() : dwMaxSize;
			WritePort(O_.GetPtr(), dwWrite);
			return O_.Read(NULL, dwWrite);
		}
		else
		{
			BYTE btTemp[1024];
			DWORD dwLength, dwIndex = 0;

			O_.Lock();
			dwLength = O_.Read(btTemp, 1024);
			O_.Unlock();

			while ( dwIndex < dwLength )
				dwIndex += WritePort(btTemp + dwIndex, dwLength - dwIndex);

			return dwLength;
		}
	}
	/*! \param uMsg 消息 \param lParam 参数 \param bPostMode 采用PostMessage或者SendMessage发送消息*/
	//! 当窗口句柄或线程ID有效, 送出消息, 用于相应事件通知, WPARAM默认包含串口编号 
	virtual void Notify(UINT uMsg, LPARAM lParam = 0, bool bPostMode = true)
	{
		if(hNotifyWnd_ && ::IsWindow(hNotifyWnd_))//窗口句柄有效
		{
			if (bPostMode)
				PostMessage(hNotifyWnd_, uMsg, WPARAM(dwPort_), lParam);
			else
				SendMessage(hNotifyWnd_, uMsg, WPARAM(dwPort_), lParam);
		}

		if (hNotifyThreadId_)//线程ID有效
			PostThreadMessage(hNotifyThreadId_, uMsg, WPARAM(dwPort_), lParam);
	}
	//---------------------------------------threads callback-----------------------------------------------------
	//! 响应EV_RXCHAR事件 由线程回调, 虚函数可以在基层类中扩展(推荐方式)    
	virtual void OnReceive() 
	{
		Notify(ON_COM_RECEIVE);
	}
	//! 响应EV_DSR事件
	virtual void OnDSR()
	{
		Notify(ON_COM_DSR, CheckDSR() ? 1 : 0);
	}
	//! 响应EV_CTS事件
	virtual void OnCTS()
	{
		Notify(ON_COM_CTS, CheckCTS() ? 1 : 0);
	}
	//! 响应EV_BREAK事件
	virtual void OnBreak()
	{
		ClearCommBreak(hComm_);
		Notify(ON_COM_BREAK);
	}
	//! 响应EV_TXEMPTY事件
	virtual void OnTxEmpty()
	{
		Notify(ON_COM_TXEMPTY);
	}
	//! 响应EV_ERROR事件
	virtual void OnError()
	{
		Notify(ON_COM_ERROR, ClearError());
	}
	//! 响应EV_RING事件
	virtual void OnRing()
	{
		Notify(ON_COM_RING, CheckRING() ? 1 : 0);
	}
	//! 响应EV_RLSD事件
	virtual void OnRLSD()
	{
		Notify(MS_RLSD_ON, CheckRLSD() ? 1 : 0);
	}
	//! 响应EV_RXFLAG事件
	virtual void OnRxFlag()
	{
		Notify(ON_COM_RXFLAG);
	}
	//! 响应EV_POWER事件
	virtual void OnPower()
	{
		Notify(ON_COM_POWER);
	}
	//! 响应EV_RX80FULL事件
	virtual void OnRx80Full()
	{
		Notify(ON_COM_RX80FULL);
	}
	//! 响应EV_EVENT1事件
	virtual void OnEvent1()
	{
		Notify(ON_COM_EVENT1);
	}
	//! 响应EV_EVENT2事件
	virtual void OnEvent2()
	{
		Notify(ON_COM_EVENT2);
	}
	//! 响应EV_PERR事件
	virtual void OnPrintErr()
	{
		Notify(ON_COM_PERR);
	}
	//! 通用的事件处理
	virtual void HandleEvent(DWORD dwMask)
	{
		if ((dwMask & EV_RXCHAR) && !(dwOption_&EN_RX_THREAD))
		{
			DWORD dwLength = GetQueueCount(true);

			if (dwLength)
			{
				if (dwOption_ & EN_RX_BUFFER)
				{
					PortToBuffer((dwLength << 1) + 64);//多出的字节数 用来避免事件间隙的陷阱

					if (I_.Size() >= dwNotifyNum_)
						OnReceive();
				}
				else
				{
					if (dwLength >= dwNotifyNum_)
						OnReceive();
				}
			}
		}

		if (dwMask & EV_TXEMPTY)
		{
			if ((dwOption_&EN_TX_BUFFER) && !(dwOption_&EN_TX_THREAD) && O_.SafeSize())
				BufferToPort();

			OnTxEmpty();
		}

		if (dwMask & EV_RXFLAG)
			OnRxFlag();

		if (dwMask & EV_CTS)
			OnCTS();
			
		if (dwMask & EV_DSR)
			OnDSR();
			
		if (dwMask & EV_RING)
			OnRing();
			
		if (dwMask & EV_RLSD)
			OnRLSD();
			
		if (dwMask & EV_BREAK)
			OnBreak();
			
		if (dwMask & EV_ERR)
			OnError();

	#ifdef CN_COMM_FOR_CE
		if (dwMask & EV_POWER)
			OnPower();
	#endif
	}
	
#ifndef CN_COMM_FOR_CE
	//! 监视线程用于重叠I/O模型 
	virtual DWORD OverlappedModel()
	{
		if(!CN_ASSERT(IsOpen()))
			return 1;

		if(!CN_ASSERT(::SetCommMask(hComm_, dwWaitEvent_)))
			return 1;

		for(DWORD dwMask = 0, dwLength; bContinue_ && IsOpen(); dwMask = 0)
		{
			if (GetQueueCount(true))//! 等待事件前会先扫描队列是否还有未处理数据 如果有模拟一个EV_RXCHAR事件 避免事件通知的陷阱
				dwMask = EV_RXCHAR, Sleep(10);
			else
			{
				if(!::WaitCommEvent(hComm_, &dwMask, &EO_))
				{
					if(::GetLastError() == ERROR_IO_PENDING)
						::GetOverlappedResult(hComm_, &EO_, &dwLength, TRUE);
					else
					{
						Sleep(10);
						continue;
					}
				}
			}
			
			if(dwMask == 0)
			{
				if ((dwOption_&EN_TX_BUFFER) && !(dwOption_&EN_TX_THREAD) && O_.SafeSize())
					BufferToPort();

				continue;
			}
			
			HandleEvent(dwMask);
		}//for

		return 0;
	}
#endif
	//! 监视线程用于阻塞I/O模型 
	virtual DWORD NonoverlappedModel()
	{
		if(!CN_ASSERT(IsOpen()))
			return 1;

		for (DWORD dwReturn; bContinue_ && IsOpen();)
		{
			dwReturn = WaitForSingleObject(hWatchEvent_, 50);

			if (!bContinue_) 
				break;

			switch (dwReturn)
			{
			case WAIT_OBJECT_0:
				while ((dwOption_&EN_TX_BUFFER) && O_.SafeSize())
					BufferToPort();

				ResetEvent(hWatchEvent_);

				break;

			case WAIT_TIMEOUT:

				DWORD dwLength = GetQueueCount(true);

				if (dwLength)
				{
					if (dwOption_ & EN_RX_BUFFER)
					{
						PortToBuffer(dwLength);

						if (I_.Size() >= dwNotifyNum_)
							OnReceive();
					}
					else
					{
						if (dwLength >= dwNotifyNum_)
							OnReceive();
					}
				}

				if ( (dwOption_&EN_TX_BUFFER) && O_.SafeSize() )
					BufferToPort();

				break;
			}
		}

		return 0;
	}
#ifdef CN_COMM_FOR_CE
	//! 监视线程用于WINCE的I/O模型(重叠+阻塞 也不知微软把它叫什么模式)
	virtual DWORD EmbeddedModel()
	{
		if(!CN_ASSERT(IsOpen()))
			return 1;

		if(!CN_ASSERT(::SetCommMask(hComm_, dwWaitEvent_)))
			return 1;

		for(DWORD dwMask = 0; bContinue_ && IsOpen(); dwMask = 0)
		{
			if (GetQueueCount(true))//! 等待事件前会先扫描队列是否还有未处理数据 如果有模拟一个EV_RXCHAR事件 避免事件通知的陷阱
				dwMask = EV_RXCHAR, Sleep(10);
			else
			{
				if(!::WaitCommEvent(hComm_, &dwMask, NULL))
					continue;
			}
			
			if(dwMask == 0)
			{
				if ( (dwOption_&EN_TX_BUFFER) && !(dwOption_&EN_TX_THREAD) && O_.SafeSize())
					BufferToPort();

				continue;
			}
		
			HandleEvent(dwMask);

		}//for

		return 0;
	}
#endif
	//! 用于双工处理当然您可以改变用途 
	virtual DWORD ReadModel()
	{
		while(bContinue_)
		{
			Sleep(50);

			DWORD dwLength = GetQueueCount(true);

			if (dwLength)
			{
				if (dwOption_ & EN_RX_BUFFER)
				{
					PortToBuffer(dwLength);

					if (I_.Size() >= dwNotifyNum_)
						OnReceive();
				}
				else
				{
					if (dwLength >= dwNotifyNum_)
						OnReceive();
				}
			}
		}

		return 0;
	}
	//! 用于双工处理当然您可以改变用途 
	virtual DWORD WriteModel()
	{
		CN_ASSERT(dwOption_ & EN_TX_BUFFER);

		while (bContinue_)
		{
			DWORD dwReturn = ::WaitForSingleObject(hWriteEvent_, 200);

			while(bContinue_ && O_.SafeSize())
				BufferToPort();

			if (dwReturn == WAIT_OBJECT_0)
				ResetEvent(hWatchEvent_);
		}

		return 0;
	}
	
private:  
	//! 禁止拷贝构造
	CnComm(const CnComm&);
	//! 禁止赋值函数
	CnComm &operator = (const CnComm&);

#if defined(_MT) && !defined(CN_COMM_FOR_CE)
	//! 监视线程 Watch Thread 完成监视 并根据配置决定是否完成读写
	static UINT APIENTRY WatchThreadProc(LPVOID lpPara)
#else
	//! 监视线程 Watch Thread 完成监视 并根据配置决定是否完成读写
	static DWORD WINAPI WatchThreadProc(LPVOID lpPara)
#endif
	{
	#ifdef CN_COMM_FOR_CE 
		DWORD dwCode = ((CnComm *)lpPara)->EmbeddedModel();
	#else
		DWORD dwCode = ((CnComm *)lpPara)->IsOverlappedMode() 
			? ((CnComm *)lpPara)->OverlappedModel() 
			: ((CnComm *)lpPara)->NonoverlappedModel();

		#if defined(_MT) 
			_endthreadex(dwCode);
		#endif
	#endif

		return dwCode;
	}

#if defined(_MT) && !defined(CN_COMM_FOR_CE)
	//! 双工的线程 暂时未用 估计用不着
	static UINT APIENTRY ReadThreadProc(LPVOID lpPara)
#else
	//! 双工的线程 暂时未用 估计用不着
	static DWORD WINAPI ReadThreadProc(LPVOID lpPara)
#endif
	{
		DWORD dwCode = ((CnComm *)lpPara)->ReadModel();

		#if defined(_MT) && !defined(CN_COMM_FOR_CE)
			_endthreadex(dwCode);
		#endif

		return dwCode;
	}

#if defined(_MT) && !defined(CN_COMM_FOR_CE)
	//! 双工的线程 WINCE可以采用
	static UINT APIENTRY WriteThreadProc(LPVOID lpPara)
#else 
	//! 双工的线程 WINCE可以采用
	static DWORD WINAPI WriteThreadProc(LPVOID lpPara)
#endif
	{
		DWORD dwCode = ((CnComm *)lpPara)->WriteModel();

		#if defined(_MT) && !defined(CN_COMM_FOR_CE)
			_endthreadex(dwCode);
		#endif

		return dwCode;
	}
};

#endif //! _CN_COMM_H_

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值