网上这方面三方类多如牛毛,真不知道用哪个好,不过不管用哪个,一定要在严格检查完善后再使用,不然给以后通信埋下隐患,只会让以后的调试会更痛苦!
ComAccess.h
#if !defined(AFX_COMACCESS_H__F15FFC6E_D059_4E57_97CD_A672C05FF9B7__INCLUDED_)
#define AFX_COMACCESS_H__F15FFC6E_D059_4E57_97CD_A672C05FF9B7__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CComAccess
{
private:
HANDLE m_hCom; // Device handle
OVERLAPPED m_ov; // A structure that contains informations which are
// used for asynchronous input and output operations
TCHAR m_lpszErrorMessage[256];
public:
CComAccess();
CComAccess(LPCSTR lpszPortNum);
~CComAccess();
// For more definitions see <winbase.h>
BOOL Open(LPCSTR lpszPortNum = "com1",
DWORD dwBaudRate = CBR_9600,
BYTE byParity = NOPARITY,
BYTE byStopBits = ONESTOPBIT,
BYTE byByteSize = 8);
VOID Close();
DWORD WriteData(LPCVOID pdata, DWORD len);
DWORD ReadData(LPVOID pdest, DWORD len, DWORD dwMaxWait = 500);
LPSTR GetErrorMessage(VOID) { return m_lpszErrorMessage; }
private:
VOID ErrorToString(LPCSTR lpszMessage);
BOOL IsNT(VOID);
};
#endif // !defined(AFX_COMACCESS_H__F15FFC6E_D059_4E57_97CD_A672C05FF9B7__INCLUDED_)
ComAccess.cpp
#include "stdafx.h"
#include "ComAccess.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CComAccess::CComAccess(VOID)
{
m_hCom = 0;
m_lpszErrorMessage[0] = '/0';
ZeroMemory(&m_ov, sizeof(m_ov));
}
CComAccess::CComAccess(LPCSTR lpszPortNum)
{
CComAccess::CComAccess();
CComAccess::Open(lpszPortNum);
}
CComAccess::~CComAccess()
{
Close();
}
////////////////////////////////////////////////////////////////////////////////////////
//
// Function: Open(LPCSTR lpszPortNum,
// DWORD dwBaudRate,
// BYTE byParity,
// BYTE byStopBits,
// BYTE byByteSize)
//
// Return value: BOOL TRUE or FALSE
//
BOOL CComAccess::Open(LPCSTR lpszPortNum,
DWORD dwBaudRate,
BYTE byParity,
BYTE byStopBits,
BYTE byByteSize)
{
DCB dcb; // structure that defines the control setting for a serial communications device
BOOL bSuccess;
m_hCom = CreateFile(lpszPortNum, // pointer to name of the file
GENERIC_READ|GENERIC_WRITE, // access mode
0, // comm devices must be opened w/exclusive-access
NULL, // no security attributs
OPEN_EXISTING, // comm devices must use OPEN_EXISTING
FILE_FLAG_OVERLAPPED, // overlapped I/O
NULL); // hTemplate must be NULL for comm devices
if ( m_hCom == INVALID_HANDLE_VALUE )
{
// handle the error
CComAccess::ErrorToString("Open(): CreateFile() failed, invalid handle value");
return FALSE;
}
//
// Omit the call to SetupComm to use the default queue sizes.
// Get the current configuration.
//
bSuccess = GetCommState(m_hCom, &dcb);
if ( ! bSuccess )
{
// Handle the error.
CComAccess::ErrorToString("Open(): GetCommState() failed");
CComAccess::Close();
return FALSE;
}
//
// Fill in the DCB: baud=9600, 8 data bits, no parity, 1 stop bit are default parameters
//
dcb.BaudRate = dwBaudRate;
dcb.ByteSize = byByteSize;
dcb.Parity = byParity;
dcb.StopBits = byStopBits;
bSuccess = SetCommState(m_hCom, &dcb);
if ( ! bSuccess )
{
// Handle the error.
CComAccess::ErrorToString("Open(): SetCommState() failed");
CComAccess::Close();
return FALSE;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////////
//
// Function: Close(VOID)
//
// Return value: VOID
//
VOID CComAccess::Close()
{
if ( m_hCom > 0 )
{
CloseHandle(m_hCom);
}
m_hCom = 0;
}
////////////////////////////////////////////////////////////////////////////////////////
//
// Function: WriteData(LPCVOID pdata,
// DWORD len)
//
// Return value: DWORD -1 failed, above, num written bytes
//
DWORD CComAccess::WriteData(LPCVOID pdata,
DWORD len)
{
BOOL bSuccess;
DWORD written = 0;
if ( len < 1 )
return(0);
// create event for overlapped I/O
m_ov.hEvent = CreateEvent(NULL, // pointer to security attributes
FALSE, // flag for manual-reset event
FALSE, // flag for initial state
""); // pointer to event-object name
if ( m_ov.hEvent == INVALID_HANDLE_VALUE )
{
// Handle the error.
CComAccess::ErrorToString("WriteData(): CreateEvent() failed");
return(-1);
}
bSuccess = WriteFile(m_hCom, // handle to file to write to
pdata, // pointer to data to write to file
len, // number of bytes to write
&written, // pointer to number of bytes written
&m_ov); // pointer to structure needed for overlapped I/O
if ( CComAccess::IsNT() )
{
bSuccess = GetOverlappedResult(m_hCom, &m_ov, &written, TRUE);
if ( ! bSuccess )
{
// Handle the error.
CloseHandle(m_ov.hEvent);
CComAccess::ErrorToString("WriteData(): GetOverlappedResult() failed");
return(-1);
}
}
else
if ( len != written )
{
// Handle the error.
CloseHandle(m_ov.hEvent);
CComAccess::ErrorToString("WriteData(): WriteFile() failed");
return(-1);
}
CloseHandle(m_ov.hEvent);
return written;
}
////////////////////////////////////////////////////////////////////////////////////////
//
// Function: ReadData(LPVOID pdest,
// DWORD len,
// DWORD dwMaxWait)
//
// Return value: DWORD -1 failed, above, num read bytes
//
DWORD CComAccess::ReadData(LPVOID pdest,
DWORD len,
DWORD dwMaxWait)
{
BOOL bSuccess;
DWORD result = 0,
read = 0, // num read bytes
mask = 0; // a 32-bit variable that receives a mask
// indicating the type of event that occurred
if ( len < 1 ) return(0);
// create event for overlapped I/O
m_ov.hEvent = CreateEvent(NULL, // pointer to security attributes
FALSE, // flag for manual-reset event
FALSE, // flag for initial state
""); // pointer to event-object name
if ( m_ov.hEvent == INVALID_HANDLE_VALUE )
{
// Handle the error.
CComAccess::ErrorToString("ReadData(): CreateEvent() failed");
return(-1);
}
// Specify here the event to be enabled
bSuccess = SetCommMask(m_hCom, EV_RXCHAR);
if ( ! bSuccess )
{
// Handle the error.
CloseHandle(m_ov.hEvent);
CComAccess::ErrorToString("ReadData(): SetCommMask() failed");
return(-1);
}
// WaitForSingleObject
bSuccess = WaitCommEvent(m_hCom, &mask, &m_ov);
if ( ! bSuccess )
{
int err = GetLastError();
if ( err == ERROR_IO_PENDING)
{
result = WaitForSingleObject(m_ov.hEvent, dwMaxWait); //wait dwMaxWait
// milli seconds before returning
if ( result == WAIT_FAILED )
{
// Handle the error.
CloseHandle(m_ov.hEvent);
CComAccess::ErrorToString("ReadData(): WaitForSingleObject() failed");
return(-1);
}
}
}
// The specified event occured?
if ( mask & EV_RXCHAR)
{
bSuccess = ReadFile(m_hCom, // handle of file to read
pdest, // address of buffer that receives data
len, // number of bytes to read
&read, // address of number of bytes read
&m_ov); // address of structure for data
if ( CComAccess::IsNT() )
{
bSuccess = GetOverlappedResult(m_hCom, &m_ov, &read, TRUE);
if ( ! bSuccess )
{
// Handle the error.
CloseHandle(m_ov.hEvent);
CComAccess::ErrorToString("WriteData(): GetOverlappedResult() failed");
return(-1);
}
}
else
if ( ! bSuccess )
{
// Handle the error.
CloseHandle(m_ov.hEvent);
CComAccess::ErrorToString("ReadData(): ReadFile() failed");
return(-1);
}
}
else
{
// Handle the error.
CloseHandle(m_ov.hEvent);
wsprintf(m_lpszErrorMessage, "Error ReadData(): No EV_RXCHAR occured/n");
return(-1);
}
CloseHandle(m_ov.hEvent);
return read;
}
////////////////////////////////////////////////////////////////////////////////////////
//
// Function: ErrorToString(LPCSTR lpszMessage)
//
// Return value: VOID
//
VOID CComAccess::ErrorToString(LPCSTR lpszMessage)
{
LPVOID lpMessageBuffer;
DWORD error = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM, // source and processing options
NULL, // pointer to message source
error, // requested message identifie
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // the user default language.
(LPTSTR) &lpMessageBuffer, // pointer to message buffer
0, // maximum size of message buffer
NULL); // address of array of message inserts
// and copy it in our error string
wsprintf(m_lpszErrorMessage,"%s: (%d) %s/n", lpszMessage, error, lpMessageBuffer);
LocalFree(lpMessageBuffer);
}
////////////////////////////////////////////////////////////////////////////////////////
//
// Function: IsNT(VOID)
//
// Return value: BOOL True or False
//
BOOL CComAccess::IsNT(VOID)
{
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
return TRUE;
}
else
{
return FALSE;
}
}