⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chatclientdoc.cpp

📁 基于winsock的聊天程序
💻 CPP
字号:
// ChatClientDoc.cpp : implementation of the CChatClientDoc class
//

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

#include "ChatClientDoc.h"
#include "CntrItem.h"
#include "ClientSocket.h"
#include "chatclientview.h"
#include "mainFrm.h"

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

#define SAFEDELETE(x) if(x!=NULL){delete x;x=NULL;}
#define WM_ADDLIST    WM_USER + 1001
#define WM_DELETELIST WM_USER+1002
/////////////////////////////////////////////////////////////////////////////
// CChatClientDoc

IMPLEMENT_DYNCREATE(CChatClientDoc, CRichEditDoc)

BEGIN_MESSAGE_MAP(CChatClientDoc, CRichEditDoc)
	//{{AFX_MSG_MAP(CChatClientDoc)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG_MAP
	// Enable default OLE container implementation
	ON_UPDATE_COMMAND_UI(ID_OLE_EDIT_LINKS, CRichEditDoc::OnUpdateEditLinksMenu)
	ON_COMMAND(ID_OLE_EDIT_LINKS, CRichEditDoc::OnEditLinks)
	ON_UPDATE_COMMAND_UI_RANGE(ID_OLE_VERB_FIRST, ID_OLE_VERB_LAST, CRichEditDoc::OnUpdateObjectVerbMenu)
END_MESSAGE_MAP()

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

CChatClientDoc::CChatClientDoc()
{
	// TODO: add one-time construction code here
	m_bConnected = FALSE;
	m_pSocket = NULL;
	m_pFile = NULL;
	m_pArchiveIn = NULL;
	m_pArchiveOut = NULL;
	m_bFilter = FALSE;
	m_number=0;
}

CChatClientDoc::~CChatClientDoc()
{
	//发送退出信息
	msg.m_nType=-2;
	msg.m_bClose = TRUE;
	msg.m_strFrom = m_strHandle;
	msg.m_strTo = "所有人";
	msg.m_bSecret = FALSE;
	msg.m_strText ="静静地离开了,孤单的背影显得格外潇洒";
	msg.m_color = RGB(0,136,255); 
	SendMsg();

	SAFEDELETE(m_pArchiveIn);
	SAFEDELETE(m_pArchiveOut);
	SAFEDELETE(m_pFile);
	SAFEDELETE(m_pSocket);
}

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

	// TODO: add reinitialization code here
	// (SDI documents will reuse this document)
	return TRUE;
}

CRichEditCntrItem* CChatClientDoc::CreateClientItem(REOBJECT* preo) const
{
	// cast away constness of this
	return new CChatClientCntrItem(preo, (CChatClientDoc*) this);
}



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

void CChatClientDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
	}
	else
	{
		// TODO: add loading code here
	}

	// Calling the base class CRichEditDoc enables serialization
	//  of the container document's COleClientItem objects.
	// TODO: set CRichEditDoc::m_bRTF = FALSE if you are serializing as text
	CRichEditDoc::Serialize(ar);
}

/////////////////////////////////////////////////////////////////////////////
// CChatClientDoc diagnostics

#ifdef _DEBUG
void CChatClientDoc::AssertValid() const
{
	CRichEditDoc::AssertValid();
}

void CChatClientDoc::Dump(CDumpContext& dc) const
{
	CRichEditDoc::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CChatClientDoc commands


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


BOOL CChatClientDoc::ConnectSocket(LPCTSTR lpszHandle, LPCTSTR lpszAddress, LPCTSTR m_strImage, UINT nPort)
{//连接服务器
	if(m_bConnected)
		return FALSE;
	m_strHandle = lpszHandle;

	SAFEDELETE(m_pArchiveIn);
	SAFEDELETE(m_pArchiveOut);
	SAFEDELETE(m_pFile);
	SAFEDELETE(m_pSocket);

	if(m_pSocket == NULL){
		m_pSocket = new CClientSocket(this);
		ASSERT(m_pSocket != NULL);
	}

	if (!m_pSocket->Create())
	{
		delete m_pSocket;
		m_pSocket = NULL;
		TRACE("Create Socket Error!\n");
		return FALSE;
	}

	while (!m_pSocket->Connect(lpszAddress, nPort))
	{
		if (AfxMessageBox("连接服务器失败!\n重试吗?",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);
	
	msg.m_nType =-1;
	msg.m_bClose = FALSE;
	msg.m_strFrom = m_strHandle;
	msg.m_strTo = "所有人";
	msg.m_bSecret = FALSE;
	msg.m_strText ="风尘仆仆地推门而入";
	msg.m_color = RGB(0,136,255); 
	msg.m_dImage = atoi(m_strImage);
//发送进入聊天室消息
	SendMsg();
	m_bConnected = TRUE;
	GetView()->GetParent()->SetWindowText(m_strHandle);
	return TRUE;
}

void CChatClientDoc::SendMsg()
{//发送消息
	msg.m_strFrom = m_strHandle;
	if (m_pArchiveOut != NULL)
	{
		TRY
		{
			msg.Serialize(*m_pArchiveOut);
			m_pArchiveOut->Flush();
		}
		CATCH(CFileException, e)
		{
			m_pArchiveOut->Abort();
			delete m_pArchiveOut;
			m_pArchiveOut = NULL;
		    DisplayMsg("服务器重置!");
		}
		END_CATCH
	}
}

void CChatClientDoc::DisplayMsg(LPCTSTR lpszText)
{
	//显示信息
	CChatClientView* pView = (CChatClientView*)GetView();

	if(pView != NULL)
		pView->Message(lpszText, RGB(128,0,0));
}

void CChatClientDoc::ReceiveMsg()
{
	//接收信息,并判断显示对应的信息
	TRY
	{
		msg.Serialize(*m_pArchiveIn);
		DisplayRecMsg(msg.m_nType, msg.m_strFrom, msg.m_strTo, msg.m_bSecret, 
				msg.m_strText, msg.m_color);
		if(msg.m_nType == -7 || msg.m_nType == -2 || msg.m_nType == -9||msg.m_nType==-5)
			m_bConnected = FALSE;
		if(msg.m_nType == -9)
			DisplayMsg("该用户名已经有人使用,请更名重新登录!\n");
	}
	CATCH(CFileException, e)
	{
		msg.m_bClose = TRUE;
		m_pArchiveOut->Abort();
		
		DisplayMsg("服务器重置!");
		DisplayMsg("断开连接!");
	}
	END_CATCH
		
	if(msg.m_bClose && (msg.m_strFrom == m_strHandle)){
		SAFEDELETE(m_pArchiveIn);
		SAFEDELETE(m_pArchiveOut);
		SAFEDELETE(m_pFile);
		SAFEDELETE(m_pSocket);
		m_bConnected = FALSE;
	}
	if((msg.m_nType ==-1 && msg.m_strFrom != m_strHandle)||(msg.m_nType == -8))
	{
		GetView()->GetParent()->SendMessage(WM_ADDLIST, (LPARAM)&(msg.m_strFrom), msg.m_dImage);
		m_number++;
	}
	if((msg.m_nType ==-7) || (msg.m_nType ==-2))
	{
		GetView()->GetParent()->SendMessage(WM_DELETELIST, (LPARAM)&(msg.m_strFrom), msg.m_dImage);
		m_number--;
	}
	UpdateConnects();
}

void CChatClientDoc::DisplayRecMsg(int type, CString from, CString to,
		BOOL sec, CString str, COLORREF clr)
{
	CChatClientView* pView = (CChatClientView*)GetView();

	if(type == -7){
		pView->Message(_T("系统信息:"),RGB(0,0,0));
		pView->Message(_T("聊天室掌门人以一招'佛山无影脚',将"),RGB(255,0,0));
		if(from == m_strHandle){
			pView->Message(_T("你"),RGB(0,0,255));
		}
		else
			pView->Message(from,RGB(0,0,255));
		pView->Message(_T("踢出门外\r\n"),RGB(0,0,0));
		return;
	} 
	if(type == -5){
		return;	
	}
	if(type==-10)
	{
		pView->Message("系统信息:",RGB(0,0,0));
		pView->Message(msg.m_strText,clr);
		pView->Message("\r\n",RGB(0,0,0));
	}
	if(type == -3)
	{
		pView->Message(_T("系统:服务器已关闭!\r\n"),RGB(0,0,0));
		return;
	}
	else if(type == -1 )
	{
		if(from==m_strHandle)
		{
			pView->Message(_TEXT("系统信息:"),RGB(0,0,0));
			pView->Message("欢迎",RGB(255,0,0));
			pView->Message("你",RGB(0,0,255));
			pView->Message("(",RGB(255,0,255));
			pView->Message(from, RGB(0,136,255));
			pView->Message(")",RGB(255,0,255));
			pView->Message(_TEXT("进入聊天室!\r\n"),RGB(255,0,0));
			return;
		}
		pView->Message(_TEXT("系统信息:"),RGB(0,0,0));
		pView->Message(from, RGB(0,0,255));
		pView->Message(_TEXT("风尘仆仆地推门而入\r\n"),RGB(255,0,0));
		return;
	}
	else if(type == -2)
	{
		pView->Message(_TEXT("系统信息:"),RGB(0,0,0));
		pView->Message(from, RGB(0,0,255));
		pView->Message(_TEXT("静静地离开了,孤单的背影显得格外潇洒\r\n"),RGB(255,0,0));
		return;
	}
	if(type>=0)
	{
		if(from == m_strHandle || to == m_strHandle || sec == FALSE || to =="所有人")
		{
			talk(type, from, to, str, clr);			
		}
	}
}

void CChatClientDoc::talk(int type, CString from, CString to,
						  CString str, COLORREF clr)
{
	//显示通用信息
	CChatClientView* pView = (CChatClientView*)GetView();
	
	if(from != m_strHandle && to != m_strHandle && m_bFilter)
		return;
	CString temp,to2,first,second;
	
	if(type > 32 || type < 0) 
		return;  
    if(from==to)
	{
		pView->Message(from,RGB(255,0,0));
		pView->Message("自言自语道:",RGB(0,0,255));
		pView->Message(str,clr);
		pView->Message("\r\n",RGB(0,0,0));
		return;
	}
	temp.LoadString(IDS_TALK0 + type);	
	int i=temp.Find(",");
	if(msg.m_bSecret==TRUE)
	{
		first = temp.Left(i);
		if(i != temp.GetLength() - 1)
		{
			second = temp.Mid(i + 1);
			second += ":";
		}
		else{
			second=":";
		}
		if(from==m_strHandle)
		{
			pView->Message("你", RGB(0,0,255));			
		}
		else
		{
			pView->Message((LPCTSTR)from,RGB(0,0,255));
		}
		pView->Message("悄悄地", RGB(0,0,0));
		pView->Message((LPCTSTR)first, RGB(0,0,0));
		if(to==m_strHandle)
		{
			pView->Message("你", RGB(255,0,0));			
		}
		else
		{
			pView->Message((LPCTSTR)to,RGB(255,0,0));
		}
		pView->Message((LPCTSTR)second, RGB(0,0,0));
		pView->Message((LPCTSTR)str,clr);
		pView->Message((LPCTSTR)"\r\n",clr);
		return;
	}
	if(i != -1)
	{
		first = temp.Left(i);
		if(i != temp.GetLength() - 1)
		{
			second = temp.Mid(i + 1);
			second += ":";
		}
		else{
			second=":";
		}
		if(from==m_strHandle)
		{
			pView->Message((LPCTSTR)"你", RGB(255,0,0));
		}
		else
		{
			pView->Message((LPCTSTR)from, RGB(0,0,255));
		}
		pView->Message((LPCTSTR)first, RGB(0,0,0));
		if(to==m_strHandle)
		{
			pView->Message((LPCTSTR)"你", RGB(255,0,0));
		}
		else
		{
			pView->Message((LPCTSTR)to, RGB(255,0,0));
		}
		pView->Message((LPCTSTR)second, RGB(0,0,0));
		pView->Message((LPCTSTR)str,clr);
		pView->Message((LPCTSTR)"\r\n",clr);
	}
	else{
		first=temp;
		second=": ";
		pView->Message(from,RGB(0,0,255));
		pView->Message(first,RGB(0,0,0));
		pView->Message(second,RGB(0,0,0));
		pView->Message(str,clr);
		pView->Message("\r\n",clr);
	}
}

void CChatClientDoc::Disconnect()//与服务器断开连接
{
	m_number=0;
	msg.m_nType =-2;
	msg.m_bClose = TRUE;
	msg.m_strFrom = m_strHandle;
	msg.m_strTo = "所有人";
	msg.m_bSecret = FALSE;
	msg.m_strText ="静静地离开了,孤单的背影显得格外潇洒";
	msg.m_color = RGB(0,136,255); 

	SendMsg();
	m_bConnected = FALSE;
	msg.m_strFrom = "DUMP";
	GetView()->GetParent()->SendMessage(WM_DELETELIST, (LPARAM)&(msg.m_strFrom), msg.m_dImage);
}

void CChatClientDoc::UpdateConnects()//在状态栏显示在线人数
{
	CString strTemp;
	CMainFrame *MFrame=(CMainFrame *)AfxGetMainWnd();
	wsprintf(strTemp.GetBuffer(50)," 在线人数: %d",m_number);
	
	MFrame->m_wndStatusBar.SetPaneText(1,strTemp);
	strTemp.ReleaseBuffer();
}

⌨️ 快捷键说明

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