📄 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();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -