www.pudn.com > 组态软件的通信.rar > XSockClientCtl.cpp


///////////////////////////////////////////////////////////////////////////// 
//	Author				:	Bala Murali 
//	XSockClientCtl.cpp	:	Implementation of the CXSockClientCtrl ActiveX Control class. 
//	Creation Date		:	03/09/2000 
//	Version				:	Initial Release 
///////////////////////////////////////////////////////////////////////////// 
 
 
#include "stdafx.h" 
#include "XSockClient.h" 
#include "XSockClientCtl.h" 
#include "XSockClientPpg.h" 
 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
 
CXSockClientCtrl* m_pControl = NULL; 
 
IMPLEMENT_DYNCREATE(CXSockClientCtrl, COleControl) 
 
 
///////////////////////////////////////////////////////////////////////////// 
// Message map 
 
BEGIN_MESSAGE_MAP(CXSockClientCtrl, COleControl) 
	//{{AFX_MSG_MAP(CXSockClientCtrl) 
	//}}AFX_MSG_MAP 
	ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties) 
END_MESSAGE_MAP() 
 
 
///////////////////////////////////////////////////////////////////////////// 
// Dispatch map 
 
BEGIN_DISPATCH_MAP(CXSockClientCtrl, COleControl) 
	//{{AFX_DISPATCH_MAP(CXSockClientCtrl) 
	DISP_PROPERTY_EX(CXSockClientCtrl, "LocalAddress", GetLocalAddress, SetLocalAddress, VT_BSTR) 
	DISP_PROPERTY_EX(CXSockClientCtrl, "LocalPort", GetLocalPort, SetLocalPort, VT_I4) 
	DISP_PROPERTY_EX(CXSockClientCtrl, "ReceiveBufferCount", GetReceiveBufferCount, SetReceiveBufferCount, VT_I4) 
	DISP_PROPERTY_EX(CXSockClientCtrl, "NullTerminate", GetNullTerminate, SetNullTerminate, VT_BOOL) 
	DISP_FUNCTION(CXSockClientCtrl, "Connect", Connect, VT_BOOL, VTS_BSTR VTS_I4) 
	DISP_FUNCTION(CXSockClientCtrl, "Send", Send, VT_BOOL, VTS_BSTR VTS_I4) 
	DISP_FUNCTION(CXSockClientCtrl, "Close", Close, VT_EMPTY, VTS_NONE) 
	//}}AFX_DISPATCH_MAP 
	DISP_FUNCTION_ID(CXSockClientCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE) 
END_DISPATCH_MAP() 
 
 
///////////////////////////////////////////////////////////////////////////// 
// Event map 
 
BEGIN_EVENT_MAP(CXSockClientCtrl, COleControl) 
	//{{AFX_EVENT_MAP(CXSockClientCtrl) 
	EVENT_CUSTOM("OnConnect", FireOnConnect, VTS_NONE) 
	EVENT_CUSTOM("OnClose", FireOnClose, VTS_NONE) 
	EVENT_CUSTOM("OnSend", FireOnSend, VTS_NONE) 
	EVENT_CUSTOM("OnError", FireOnError, VTS_BSTR) 
	EVENT_CUSTOM("OnReceive", FireOnReceive, VTS_BSTR  VTS_I4) 
	//}}AFX_EVENT_MAP 
END_EVENT_MAP() 
 
 
///////////////////////////////////////////////////////////////////////////// 
// Property pages 
 
BEGIN_PROPPAGEIDS(CXSockClientCtrl, 1) 
	PROPPAGEID(CXSockClientPropPage::guid) 
END_PROPPAGEIDS(CXSockClientCtrl) 
 
 
///////////////////////////////////////////////////////////////////////////// 
// Initialize class factory and guid 
 
IMPLEMENT_OLECREATE_EX(CXSockClientCtrl, "XSOCKCLIENT.XSockClientCtrl.1", 
	0x2328f294, 0xdd85, 0x11d3, 0xb4, 0xaf, 0, 0xc0, 0x4f, 0x2b, 0x30, 0xe) 
 
 
///////////////////////////////////////////////////////////////////////////// 
// Type library ID and version 
 
IMPLEMENT_OLETYPELIB(CXSockClientCtrl, _tlid, _wVerMajor, _wVerMinor) 
 
 
///////////////////////////////////////////////////////////////////////////// 
// Interface IDs 
 
const IID BASED_CODE IID_DXSockClient = 
		{ 0x2328f292, 0xdd85, 0x11d3, { 0xb4, 0xaf, 0, 0xc0, 0x4f, 0x2b, 0x30, 0xe } }; 
const IID BASED_CODE IID_DXSockClientEvents = 
		{ 0x2328f293, 0xdd85, 0x11d3, { 0xb4, 0xaf, 0, 0xc0, 0x4f, 0x2b, 0x30, 0xe } }; 
 
 
///////////////////////////////////////////////////////////////////////////// 
// Control type information 
 
static const DWORD BASED_CODE _dwXSockClientOleMisc = 
	OLEMISC_ACTIVATEWHENVISIBLE | 
	OLEMISC_SETCLIENTSITEFIRST | 
	OLEMISC_INSIDEOUT | 
	OLEMISC_CANTLINKINSIDE | 
	OLEMISC_RECOMPOSEONRESIZE; 
 
IMPLEMENT_OLECTLTYPE(CXSockClientCtrl, IDS_XSOCKCLIENT, _dwXSockClientOleMisc) 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CXSockClientCtrl::CXSockClientCtrlFactory::UpdateRegistry - 
// Adds or removes system registry entries for CXSockClientCtrl 
 
BOOL CXSockClientCtrl::CXSockClientCtrlFactory::UpdateRegistry(BOOL bRegister) 
{ 
	// TODO: Verify that your control follows apartment-model threading rules. 
	// Refer to MFC TechNote 64 for more information. 
	// If your control does not conform to the apartment-model rules, then 
	// you must modify the code below, changing the 6th parameter from 
	// afxRegApartmentThreading to 0. 
 
	if (bRegister) 
		return AfxOleRegisterControlClass( 
			AfxGetInstanceHandle(), 
			m_clsid, 
			m_lpszProgID, 
			IDS_XSOCKCLIENT, 
			IDB_XSOCKCLIENT, 
			afxRegApartmentThreading, 
			_dwXSockClientOleMisc, 
			_tlid, 
			_wVerMajor, 
			_wVerMinor); 
	else 
		return AfxOleUnregisterClass(m_clsid, m_lpszProgID); 
} 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CXSockClientCtrl::CXSockClientCtrl - Constructor 
 
CXSockClientCtrl::CXSockClientCtrl():m_bConnect(FALSE),m_nBuffLen(4096), 
									 m_RemotePort(0),m_LocalPort(0),m_bNullTerminate(TRUE) 
{ 
	InitializeIIDs(&IID_DXSockClient, &IID_DXSockClientEvents); 
	m_pControl = this; 
	m_lpBuff = new char[m_nBuffLen+1]; // +1 is for NULL terminated strings 
	m_bitmap.LoadBitmap(IDB_XSOCKCLIENT); 
} 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CXSockClientCtrl::~CXSockClientCtrl - Destructor 
 
CXSockClientCtrl::~CXSockClientCtrl() 
{ 
	delete[] m_lpBuff; 
} 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CXSockClientCtrl::OnDraw - Drawing function 
 
void CXSockClientCtrl::OnDraw( 
			CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid) 
{ 
	BITMAP bm; 
	m_bitmap.GetObject (sizeof(BITMAP),&bm); 
	CPoint size(bm.bmWidth,bm.bmHeight); 
	pdc->DPtoLP(&size); 
 
	CPoint org(0,0); 
	pdc->DPtoLP(&org); 
 
	CDC dcMem; 
	dcMem.CreateCompatibleDC(pdc); 
	CBitmap* pOldBitmap = dcMem.SelectObject(&m_bitmap); 
	dcMem.SetMapMode (pdc->GetMapMode ()); 
 
//	pdc->StretchBlt(0, 0, rcBounds.Width(), rcBounds.Height(), &dcMem, org.x, org.y, size.x, size.y, SRCCOPY); 
	pdc->BitBlt (0, 0, size.x, size.y, &dcMem, org.x, org.y, SRCCOPY); 
 
	dcMem.SelectObject(pOldBitmap); 
 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CXSockClientCtrl::DoPropExchange - Persistence support 
 
void CXSockClientCtrl::DoPropExchange(CPropExchange* pPX) 
{ 
	ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor)); 
	COleControl::DoPropExchange(pPX); 
 
	PX_String(pPX, "LocalAddress", m_LocalAddress, _T("")); 
	PX_Long(pPX, "LocalPort", m_LocalPort,0); 
	PX_Bool(pPX,"NullTerminate",m_bNullTerminate); 
	PX_Long(pPX, "ReceiveBufferCount", m_nBuffLen,4096); 
} 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CXSockClientCtrl::OnResetState - Reset control to default state 
 
void CXSockClientCtrl::OnResetState() 
{ 
	COleControl::OnResetState();  // Resets defaults found in DoPropExchange 
} 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CXSockClientCtrl::AboutBox - Display an "About" box to the user 
 
void CXSockClientCtrl::AboutBox() 
{ 
	CDialog dlgAbout(IDD_ABOUTBOX_XSOCKCLIENT); 
	dlgAbout.DoModal(); 
} 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CXSockClientCtrl message handlers 
 
void CXSockClientCtrl::Close()  
{ 
	m_ConnectS.Close(); 
	m_bConnect = FALSE; 
} 
 
 
BOOL CXSockClientCtrl::Connect(LPCTSTR lpRemoteAddress, long nRemotePort )  
{ 
	if ( !m_bConnect ) 
	{ 
		if ( !m_ConnectS.Create(m_LocalPort, SOCK_STREAM,  
				FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE,  
				m_LocalAddress) ) { 
				if ( !SocketError() ) 
					return FALSE; 
			} 
		 
		m_bConnect = TRUE; 
 
		if ( !m_ConnectS.Connect(lpRemoteAddress,nRemotePort) ) { 
			return SocketError(); 
			} 
	} 
 
	return FALSE; 
} 
 
 
BOOL CXSockClientCtrl::Send(LPCTSTR lpData, long nDataLen)  
{ 
	long nTotalByteSent = 0; 
	long nByteSent = 0; 
	long nByteLen = nDataLen; 
 
	while ( nTotalByteSent < nDataLen ) 
	{ 
		if ( (nByteSent = m_ConnectS.Send(lpData, nByteLen)) == SOCKET_ERROR ) 
			return FALSE; 
 
		nTotalByteSent += nByteSent; 
		lpData += nByteSent;	// Discard the Buffer already sent 
		nByteLen -= nByteSent;	// Reduce the Buffer length by bytes sent 
	} 
 
	return TRUE; 
} 
 
 
BSTR CXSockClientCtrl::GetLocalAddress()  
{ 
	CString strResult = m_LocalAddress; 
	return strResult.AllocSysString(); 
} 
 
void CXSockClientCtrl::SetLocalAddress(LPCTSTR lpszNewValue)  
{ 
	m_LocalAddress = lpszNewValue; 
	SetModifiedFlag(); 
} 
 
long CXSockClientCtrl::GetLocalPort()  
{ 
	return m_LocalPort; 
} 
 
void CXSockClientCtrl::SetLocalPort(long nNewValue)  
{ 
	m_LocalPort = nNewValue; 
	SetModifiedFlag(); 
} 
 
 
BOOL CXSockClientCtrl::SocketError( ) 
{ 
	int nErrorCode = GetLastError( ); 
	if ( nErrorCode == WSAEWOULDBLOCK ) 
		return TRUE; 
 
	SocketError(nErrorCode); 
	return FALSE; 
} 
 
void CXSockClientCtrl::SocketError(int nErrorCode) 
{ 
	CString strError; 
	 
	switch(nErrorCode) 
	{ 
	case WSANOTINITIALISED: 
		strError = "A successful AfxSocketInit must occur before using this API"; 
		break; 
 
	case WSAENETDOWN: 
		strError = "The Windows Sockets implementation detected that the network subsystem failed"; 
		break; 
 
	case WSAEAFNOSUPPORT: 
		strError = "The specified address family is not supported"; 
		break; 
 
	case WSAEINPROGRESS: 
		strError = "A blocking Windows Sockets operation is in progress"; 
		break; 
 
	case WSAEPROTONOSUPPORT: 
		strError = "The specified port is not supported"; 
		break; 
 
	case WSAEPROTOTYPE: 
		strError = "The specified port is the wrong type for this socket"; 
		break; 
 
	case WSAESOCKTNOSUPPORT: 
		strError = "The specified socket type is not supported in this address family"; 
		break; 
 
	case WSAEACCES:  
		strError = "The requested address is a broadcast address, but the appropriate flag was not set"; 
		break; 
 
	case WSAEFAULT:  
		strError = "The lpBuf argument is not in a valid part of the user address space"; 
		break; 
 
	case WSAENETRESET: 
		strError = "The connection must be reset because the Windows Sockets implementation dropped it"; 
		break; 
 
	case WSAEOPNOTSUPP: 
		strError = "MSG_OOB was specified, but the socket is not of type SOCK_STREAM"; 
		break; 
 
	case WSAESHUTDOWN: 
		strError = "The socket has been shut down; it is not possible to call Send on a socket after ShutDown has been invoked with nHow set to 1 or 2"; 
		break; 
 
	case WSAEMSGSIZE: 
		strError = "The socket is of type SOCK_DGRAM, and the datagram is larger than the maximum supported by the Windows Sockets implementation"; 
		break; 
 
	case WSAEINVAL: 
		strError = "The socket has not been bound with Bind or The socket is already bound to an address"; 
		break; 
 
	case WSAECONNABORTED: 
		strError = "The virtual circuit was aborted due to timeout or other failure"; 
		break; 
 
	case WSAECONNRESET: 
		strError = "The virtual circuit was reset by the remote side"; 
		break; 
 
	case WSAEADDRINUSE:  
		strError = "The specified address is already in use"; 
		break; 
 
	case WSAEADDRNOTAVAIL:  
		strError = "The specified address is not available from the local machine"; 
		break; 
 
	case WSAECONNREFUSED:  
		strError = "The attempt to connect was forcefully rejected"; 
		break; 
 
	case WSAEDESTADDRREQ:  
		strError = "A destination address is required"; 
		break; 
 
	case WSAEISCONN:  
		strError = "The socket is already connected"; 
		break; 
 
	case WSAEMFILE:  
		strError = "No more file descriptors are available"; 
		break; 
 
	case WSAENETUNREACH:  
		strError = "The network cannot be reached from this host at this time"; 
		break; 
 
	case WSAENOBUFS:  
		strError = "No buffer space is available. The socket cannot be connected"; 
		break; 
 
	case WSAENOTCONN:  
		strError = "The socket is not connected"; 
		break; 
 
	case WSAENOTSOCK:  
		strError = "The descriptor is a file, not a socket"; 
		break; 
 
	case WSAETIMEDOUT:  
		strError = "The attempt to connect timed out without establishing a connection"; 
		break; 
 
	default: 
			break; 
	} 
 
	m_pControl->FireOnError(strError); 
} 
 
 
long CXSockClientCtrl::GetReceiveBufferCount()  
{ 
	return m_nBuffLen; 
} 
 
void CXSockClientCtrl::SetReceiveBufferCount(long nNewValue)  
{ 
	if ( nNewValue != 0 ) 
	{ 
		m_nBuffLen = nNewValue; 
		delete[] m_lpBuff; 
		m_lpBuff = new char[m_nBuffLen+1];// +1 is for NULL terminated strings 
		SetModifiedFlag(); 
	} 
} 
 
 
 
BOOL CXSockClientCtrl::GetNullTerminate()  
{ 
	return m_bNullTerminate ; 
} 
 
void CXSockClientCtrl::SetNullTerminate(BOOL bNewValue)  
{ 
	m_bNullTerminate = bNewValue; 
 
	SetModifiedFlag(); 
}