www.pudn.com > 3.rar > ChatClientDoc.cpp


// ChatClientDoc.cpp : implementation of the CChatClientDoc class 
// 
 
#include "stdafx.h" 
#include "ChatClient.h" 
 
#include "ChatClientDoc.h" 
#include "Msg.h" 
#include "ChatSocket.h" 
#include "MessageView.h" 
#include "ChattersView.h" 
#include "LogDlg.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
#define LEAVING_CHAT          1 
#define SENDING_CHATTERS_LIST 2 
#define SENDING_NICKNAME      3 
#define NORMAL_MESSAGE        4 
#define USED_NAME			  5 
///////////////////////////////////////////////////////////////////////////// 
// CChatClientDoc 
 
IMPLEMENT_DYNCREATE(CChatClientDoc, CDocument) 
 
BEGIN_MESSAGE_MAP(CChatClientDoc, CDocument) 
	//{{AFX_MSG_MAP(CChatClientDoc) 
	ON_COMMAND(ID_CONNECT, OnConnect) 
	ON_UPDATE_COMMAND_UI(ID_CONNECT, OnUpdateConnect) 
	ON_COMMAND(ID_DISCONNECT, OnDisconnect) 
	ON_UPDATE_COMMAND_UI(ID_DISCONNECT, OnUpdateDisconnect) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CChatClientDoc construction/destruction 
 
CChatClientDoc::CChatClientDoc() 
{ 
	// TODO: add one-time construction code here 
	bIsConnected = FALSE; 
	m_pSocket = NULL; 
	m_pFile = NULL; 
	m_pArchiveOut = NULL; 
	m_pArchiveIn = NULL; 
} 
 
CChatClientDoc::~CChatClientDoc() 
{ 
} 
 
BOOL CChatClientDoc::OnNewDocument() 
{ 
	if (!CDocument::OnNewDocument()) 
		return FALSE; 
 
	// TODO: add reinitialization code here 
	// (SDI documents will reuse this document) 
 
	return TRUE; 
} 
 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CChatClientDoc serialization 
 
void CChatClientDoc::Serialize(CArchive& ar) 
{ 
	if (ar.IsStoring()) 
	{ 
		// TODO: add storing code here 
	} 
	else 
	{ 
		// TODO: add loading code here 
	} 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CChatClientDoc diagnostics 
 
#ifdef _DEBUG 
void CChatClientDoc::AssertValid() const 
{ 
	CDocument::AssertValid(); 
} 
 
void CChatClientDoc::Dump(CDumpContext& dc) const 
{ 
	CDocument::Dump(dc); 
} 
#endif //_DEBUG 
 
///////////////////////////////////////////////////////////////////////////// 
// CChatClientDoc commands 
 
void CChatClientDoc::OnConnect()  
{ 
	// TODO: Add your command handler code here 
	CLogDlg dlg; 
	if(dlg.DoModal() == IDOK) 
	{ 
		if(ConnectSocket(dlg.m_Name, dlg.m_Server, dlg.m_Port)) 
			bIsConnected = TRUE; 
		else 
			AfxMessageBox("连接服务器失败!"); 
			 
	} 
} 
 
 
void CChatClientDoc::OnUpdateConnect(CCmdUI* pCmdUI)  
{ 
	// TODO: Add your command update UI handler code here 
	pCmdUI->Enable(!bIsConnected); 
} 
 
void CChatClientDoc::OnDisconnect()  
{ 
	// TODO: Add your command handler code here 
	DeleteContents(); 
	bIsConnected = FALSE; 
} 
 
void CChatClientDoc::OnUpdateDisconnect(CCmdUI* pCmdUI)  
{ 
	// TODO: Add your command update UI handler code here 
	pCmdUI->Enable(bIsConnected); 
} 
 
BOOL CChatClientDoc::ConnectSocket(LPCTSTR lpszHandle, LPCTSTR lpszAddress, int nPort) 
{ 
	m_strName = lpszHandle; 
	m_pSocket = new CChatSocket(this); 
	//创建socket失败 
	if (!m_pSocket->Create()) 
	{ 
		delete m_pSocket; 
		m_pSocket = NULL; 
		AfxMessageBox("创建socket失败!"); 
		return FALSE; 
	} 
	//连接失败 
	if(!m_pSocket->Connect(lpszAddress, nPort)) 
	{ 
		delete m_pSocket; 
		m_pSocket = NULL; 
		return FALSE; 
	} 
 
	m_pFile = new CSocketFile(m_pSocket); 
	//用于数据接收和发送 
	m_pArchiveIn = new CArchive(m_pFile,CArchive::load); 
	m_pArchiveOut = new CArchive(m_pFile,CArchive::store); 
	//将用户名发送给服务器 
	SendMsg(m_strName, SENDING_NICKNAME, false); 
	 
	CString strTemp; 
	strTemp.Format("进入聊天室"); 
	//作为普通消息发送给服务器 
	SendMsg(strTemp, NORMAL_MESSAGE, true); 
	return TRUE; 
} 
 
void CChatClientDoc::SendMsg(CString& strText, int mCode, BOOL bSendHandle) 
{ 
	if (m_pArchiveOut != NULL) 
	{ 
		CMsg msg; 
		msg.code = mCode; 
		msg.m_strText = (bSendHandle ? m_strName + _T(": ") + strText : strText); 
		TRY 
		{ 
			msg.Serialize(*m_pArchiveOut); 
			m_pArchiveOut->Flush(); 
		} 
		CATCH(CFileException, e) 
		{ 
			m_pArchiveOut->Abort(); 
			delete m_pArchiveOut; 
			m_pArchiveOut = NULL; 
			CString strTemp; 
			strTemp.Format("发送失败"); 
			DisplayMsg(strTemp); 
		} 
		END_CATCH 
	} 
} 
 
void CChatClientDoc::ProcessReceive() 
{ 
	do 
	{ 
		ReceiveMsg(); 
		if (m_pSocket == NULL) 
			return; 
	} 
	while(!m_pArchiveIn->IsBufferEmpty()); 
} 
 
void CChatClientDoc::ReceiveMsg() 
{ 
	CMsg msg; 
	TRY 
	{ 
		msg.Serialize(*m_pArchiveIn); 
		if(msg.code == SENDING_CHATTERS_LIST) 
		{ 
			//更新用户列表 
			UpdateChattersList(&msg); 
			return; 
		} 
		if(msg.code == USED_NAME) 
		{ 
			//如果是用户名已存在信息则关闭连接,退出 
			AfxMessageBox(msg.m_strText); 
			msg.m_bClose = TRUE; 
			OnDisconnect(); 
			return; 
		} 
		//显示消息 
		DisplayMsg(msg.m_strText); 
	} 
	CATCH(CFileException, e) 
	{ 
		msg.m_bClose = TRUE; 
		m_pArchiveOut->Abort(); 
		CString strTemp; 
		strTemp.Format("接收数据失败"); 
		DisplayMsg(strTemp); 
	} 
	END_CATCH 
	//如果连接已关闭则删除各对象 
	if (msg.m_bClose) 
	{ 
		delete m_pArchiveIn; 
		m_pArchiveIn = NULL; 
		delete m_pArchiveOut; 
		m_pArchiveOut = NULL; 
		delete m_pFile; 
		m_pFile = NULL; 
		delete m_pSocket; 
		m_pSocket = NULL; 
	} 
} 
 
void CChatClientDoc::DisplayMsg(LPCTSTR lpszText) 
{ 
	for(POSITION pos=GetFirstViewPosition();pos!=NULL;) 
	{ 
		CView* pView = GetNextView(pos); 
		CMessageView* pChatView = DYNAMIC_DOWNCAST(CMessageView, pView); 
		if (pChatView != NULL) 
			pChatView->ShowMessage(lpszText); 
	} 
} 
 
void CChatClientDoc::UpdateChattersList(CMsg* pMsg) 
{ 
	CChattersView* pChattersView; 
	for(POSITION pos=GetFirstViewPosition();pos!=NULL;) 
	{ 
		CView* pView = GetNextView(pos); 
		pChattersView = DYNAMIC_DOWNCAST(CChattersView, pView); 
		//首先清空用户列表视图 
		if (pChattersView != NULL) 
			pChattersView->ClearChattersList(); 
	}	 
	CString strTemp = pMsg->m_strText; 
	//得到所有的用户名并加入到用户列表中 
	do 
	{ 
		CString sName = strTemp.Left(strTemp.Find(":",0)); 
		pChattersView->AddToChattersList(sName); 
		strTemp = strTemp.Mid(strTemp.Find(":" , 0)+1); 
	}while(strTemp.Find(":",0) != -1); 
} 
 
void CChatClientDoc::DeleteContents() 
{ 
	if ((m_pSocket != NULL) && (m_pFile != NULL) && (m_pArchiveOut != NULL)) 
	{ 
		//首先发送用户名 
		SendMsg(m_strName, LEAVING_CHAT, false); 
		CMsg msg; 
		CString strTemp; 
		//发送普通消息 
		strTemp.Format(":离开了聊天室"); 
		msg.code = NORMAL_MESSAGE; 
		msg.m_bClose = TRUE; 
		msg.m_strText = m_strName + strTemp; 
		msg.Serialize(*m_pArchiveOut); 
		m_pArchiveOut->Flush();	 
	} 
	//删除各对象 
	delete m_pArchiveOut; 
	m_pArchiveOut = NULL; 
	delete m_pArchiveIn; 
	m_pArchiveIn = NULL; 
	delete m_pFile; 
	m_pFile = NULL; 
	//关闭连接 
	if (m_pSocket != NULL) 
	{ 
		m_pSocket->ShutDown(2); 
		delete m_pSocket; 
		m_pSocket = NULL; 
	} 
	//更新视图 
	for(POSITION pos=GetFirstViewPosition();pos!=NULL;) 
	{ 
		CView* pView = GetNextView(pos); 
 
		if (pView->IsKindOf(RUNTIME_CLASS(CMessageView))) 
		{ 
			CMessageView* pChatView = (CMessageView*)pView; 
			pChatView->GetEditCtrl().SetWindowText(_T("")); 
		} 
		if (pView->IsKindOf(RUNTIME_CLASS(CChattersView))) 
		{ 
			CChattersView* pCChattersView = (CChattersView*)pView; 
			pCChattersView->ClearChattersList(); 
		} 
	} 
	CDocument::DeleteContents(); 
}