chatclientdoc.cpp

来自「一个简易的聊天室程序」· C++ 代码 · 共 437 行

CPP
437
字号


#include "stdafx.h"
#include "ChatClient.h"

#include "ChatClientDoc.h"

#include "LogonDlg.h"

#include "LeftView.h"
#include "ChatViewRE.h"

#include "PrivateMsgDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

CString m_strHandle;

/////////////////////////////////////////////////////////////////////////////
// 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_UPDATE_COMMAND_UI(ID_DISCONNECT, OnUpdateDisconnect)
	ON_COMMAND(ID_DISCONNECT, OnDisconnect)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CChatClientDoc construction/destruction

CChatClientDoc::CChatClientDoc()
{
	bIsConnected = FALSE;
	m_pSocket = NULL;
	m_pFile = NULL;
	m_pArchiveOut = NULL;
	m_pArchiveIn = NULL;

	m_stdCF.cbSize = sizeof(CHARFORMAT);
	m_stdCF.dwMask = CFM_BOLD|CFM_SIZE|CFM_COLOR;
	m_stdCF.dwEffects = CFE_AUTOCOLOR | FW_NORMAL;
	m_stdCF.yHeight = 200;
	m_stdCF.yOffset = 0;
	m_stdCF.crTextColor = RGB(0,0,0);
	m_stdCF.bCharSet = 0;
	m_stdCF.bPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
	strcpy(m_stdCF.szFaceName , "Arial");

}

CChatClientDoc::~CChatClientDoc()
{
}

BOOL CChatClientDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;


	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CChatClientDoc serialization

void CChatClientDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		for(POSITION pos=GetFirstViewPosition();pos!=NULL;)
		{
			CView* pView = GetNextView(pos);
			CChatViewRE* pChatView = DYNAMIC_DOWNCAST(CChatViewRE, pView);

			if (pChatView != NULL)
				pChatView->Serialize(ar);

		}
	}
}

/////////////////////////////////////////////////////////////////////////////
// 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::DeleteContents()
{

	if ((m_pSocket != NULL) && (m_pFile != NULL) && (m_pArchiveOut != NULL))
	{
		CMsg msg;
		CString strTemp;

		if (strTemp.LoadString(IDS_DISCONNECT))
		{
			SendMsg(m_strHandle, LEAVING_CHAT, false , m_stdCF);

			msg.m_dwMask = m_stdCF.dwMask;
			msg.m_dwEffects = m_stdCF.dwEffects;
			msg.m_yHeight = m_stdCF.yHeight;
			msg.m_yOffset = m_stdCF.yOffset;
			msg.m_crTextColor = m_stdCF.crTextColor;
			msg.m_bCharSet = m_stdCF.bCharSet;
			msg.m_bPitchAndFamily = m_stdCF.bPitchAndFamily;
			msg.m_szFaceName = m_stdCF.szFaceName;
			
			msg.code = NORMAL_MESSAGE;
			msg.m_bClose = TRUE;
			msg.m_strText = m_strHandle + 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)
	{
		BYTE Buffer[50];
		m_pSocket->ShutDown();

		while(m_pSocket->Receive(Buffer,50) > 0);
	}

	delete m_pSocket;
	m_pSocket = NULL;

	for(POSITION pos=GetFirstViewPosition();pos!=NULL;)
	{
		CView* pView = GetNextView(pos);

		if (pView->IsKindOf(RUNTIME_CLASS(CChatViewRE)))
		{
			CChatViewRE* pChatView = (CChatViewRE*)pView;
			pChatView->GetRichEditCtrl().SetWindowText(_T(""));
		}
		if (pView->IsKindOf(RUNTIME_CLASS(CLeftView)))
		{
			CLeftView* pLeftView = (CLeftView*)pView;
			pLeftView->ClearChattersList();
		}
	}

	CDocument::DeleteContents();
}


BOOL CChatClientDoc::ConnectSocket(LPCTSTR lpszHandle, LPCTSTR lpszAddress, UINT nPort)
{
	m_strHandle = lpszHandle;

	m_pSocket = new CChatSocket(this);

	if (!m_pSocket->Create())
	{
		delete m_pSocket;
		m_pSocket = NULL;
		AfxMessageBox(IDS_CREATEFAILED);
		return FALSE;
	}

	while (!m_pSocket->Connect(lpszAddress, nPort + 1500)) // 700
	{
		if (AfxMessageBox(IDS_RETRYCONNECT,MB_YESNO) == IDNO)
		{
			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_strHandle, SENDING_NICKNAME, false, m_stdCF);
	
	CString strTemp;
	if (strTemp.LoadString(IDS_CONNECT))
		SendMsg(strTemp, NORMAL_MESSAGE, true, m_stdCF);

	return TRUE;
}

void CChatClientDoc::ProcessPendingRead()
{
	do
	{
		ReceiveMsg();
		if (m_pSocket == NULL)
			return;
	}
	while(!m_pArchiveIn->IsBufferEmpty());
}


void CChatClientDoc::ReceiveMsg()
{
	CMsg msg;
	CString temp;

	TRY
	{
		msg.Serialize(*m_pArchiveIn);

		if(msg.code == SENDING_CHATTERS_LIST)
		{
			UpdateChattersList(&msg);
		}
		if(msg.code == DUPLICATE_NICKNAME)
		{
			AfxMessageBox(msg.m_strText);
			msg.m_bClose = TRUE;
			OnDisconnect();
		}

		if(msg.code == PRIVATE_MESSAGE)
		{
			CWnd* wnd;
			for(POSITION pos=GetFirstViewPosition();pos!=NULL;)
			{
				CView* pView = GetNextView(pos);
				if (pView->IsKindOf(RUNTIME_CLASS(CLeftView)))
					wnd = (CWnd*)pView;
			}

			CPrivateMsgDlg* dlg = new CPrivateMsgDlg(wnd , TRUE , msg.m_strText);
			dlg->Create();
			dlg->ShowWindow(SW_SHOW);
		}
		
		if(msg.code == KICK_USER)
		{
			temp.LoadString(IDS_KICKED);
			msg.m_bClose = TRUE;
		}

		while(!msg.m_msgList.IsEmpty())
		{
			temp = msg.m_msgList.RemoveHead();

			CHARFORMAT cf;
			cf.cbSize = sizeof(CHARFORMAT);
			cf.dwMask = msg.m_dwMask;
			cf.dwEffects = msg.m_dwEffects;
			cf.yHeight = msg.m_yHeight;
			cf.yOffset = msg.m_yOffset;
			cf.crTextColor = msg.m_crTextColor;
			cf.bCharSet = msg.m_bCharSet;
			cf.bPitchAndFamily = msg.m_bPitchAndFamily;
			strcpy(cf.szFaceName , msg.m_szFaceName);
	
			DisplayMsg(temp, cf);
	
		}

	}
	CATCH(CFileException, e)
	{
		msg.m_bClose = TRUE;
		m_pArchiveOut->Abort();

		CString strTemp;
		if (strTemp.LoadString(IDS_SERVERRESET))
			DisplayMsg(strTemp, m_stdCF);
		if (strTemp.LoadString(IDS_CONNECTIONCLOSED))
			DisplayMsg(strTemp, m_stdCF);
	}
	END_CATCH

	if (msg.m_bClose)
	{
		AfxMessageBox(temp);
		OnDisconnect();
	}
}

void CChatClientDoc::DisplayMsg(LPCTSTR lpszText, CHARFORMAT cf)
{

	for(POSITION pos=GetFirstViewPosition();pos!=NULL;)
	{
		CView* pView = GetNextView(pos);
		CChatViewRE* pChatView = DYNAMIC_DOWNCAST(CChatViewRE, pView);

		if (pChatView != NULL)
			pChatView->message(lpszText, cf);
	}
}

void CChatClientDoc::SendMsg(CString& strText, UINT mCode, BOOL bSendHandle , CHARFORMAT cf)
{

	CMsg msg;

	msg.m_dwMask = cf.dwMask;
	msg.m_dwEffects = cf.dwEffects;
	msg.m_yHeight = cf.yHeight;
	msg.m_yOffset = cf.yOffset;
	msg.m_crTextColor = cf.crTextColor;
	msg.m_bCharSet = cf.bCharSet;
	msg.m_bPitchAndFamily = cf.bPitchAndFamily;
	msg.m_szFaceName = cf.szFaceName;

	msg.code = mCode;

	msg.m_strText = (bSendHandle ? m_strHandle + _T(": ") + strText : strText);

	DespatchMsg(msg);

}

void CChatClientDoc::DespatchMsg(CMsg& msg)
{
	if (m_pArchiveOut != NULL)
	{
		TRY
		{
			msg.Serialize(*m_pArchiveOut);
			m_pArchiveOut->Flush();
		}
		CATCH(CFileException, e)
		{
			m_pArchiveOut->Abort();
			delete m_pArchiveOut;
			m_pArchiveOut = NULL;

			CString strTemp;
			if (strTemp.LoadString(IDS_SERVERRESET))
				DisplayMsg(strTemp, m_stdCF);
		}
		END_CATCH
	}
}

void CChatClientDoc::UpdateChattersList(CMsg* pMsg)
{

	CLeftView* pLeftView;
	POSITION pos;

	for(pos=GetFirstViewPosition();pos!=NULL;)
	{
		CView* pView = GetNextView(pos);
		pLeftView = DYNAMIC_DOWNCAST(CLeftView, pView);

		if (pLeftView != NULL)
			pLeftView->ClearChattersList();
	}

	while(!pMsg->m_chattersList.IsEmpty())
	{
		CString sNameSock = pMsg->m_chattersList.RemoveHead();
		CString sName = sNameSock.Left(sNameSock.Find(":" , 0));
		CString cSocket = sNameSock.Mid(sNameSock.Find(":", 0)+2);
		if(pLeftView != NULL)
			pLeftView->AddToChattersList(sName, cSocket);
	}

}

void CChatClientDoc::OnConnect() 
{
	CLogonDlg dlg;
	dlg.m_NickName = _T("Barry");
	dlg.m_Port = 0;
	dlg.m_Server = _T("127.0.0.1");

	while(TRUE)
	{
		if (IDOK != dlg.DoModal())
			return;

		if (ConnectSocket(dlg.m_NickName, dlg.m_Server, dlg.m_Port))
		{
			bIsConnected = TRUE;
			return;
		}

		if (AfxMessageBox(IDS_CHANGEADDRESS,MB_YESNO) == IDNO)
			return ;
	}
		
}

void CChatClientDoc::OnUpdateConnect(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(!bIsConnected);
}

void CChatClientDoc::OnUpdateDisconnect(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(bIsConnected);	
}

void CChatClientDoc::OnDisconnect() 
{
	DeleteContents();
	bIsConnected = FALSE;
}

void CChatClientDoc::ClearMessages()
{

}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?