📄 clientdlg.cpp
字号:
// ClientDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Client.h"
#include "ClientDlg.h"
#include"MY_MSG.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CClientDlg dialog
CClientDlg::CClientDlg(CWnd* pParent /*=NULL*/)
: CDialog(CClientDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CClientDlg)
m_selected = _T("");
m_readymsg = _T("");
m_yourname = _T("");
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_psocket=NULL;
m_pin=NULL;
m_pout=NULL;
m_pfile=NULL;
}
void CClientDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CClientDlg)
DDX_Control(pDX, IDC_SEND, m_send);
DDX_Control(pDX, IDC_CHATMSG, m_chatcontent);
DDX_Control(pDX, IDC_ONLINE, m_namelist);
DDX_Control(pDX, IDC_CHAT, m_chat);
DDX_CBString(pDX, IDC_ONLINE, m_selected);
DDX_Text(pDX, IDC_READYMSG, m_readymsg);
DDX_Text(pDX, IDC_YOURNAME, m_yourname);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CClientDlg, CDialog)
//{{AFX_MSG_MAP(CClientDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_CBN_SELCHANGE(IDC_ONLINE, OnSelchangeOnline)
ON_BN_CLICKED(IDC_CHAT, OnChat)
ON_BN_CLICKED(IDC_QUIT, OnQuit)
ON_BN_CLICKED(IDC_SEND, OnSend)
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CClientDlg message handlers
BOOL CClientDlg::OnInitDialog()
{
CConnect connect;
//connect.DoModal();
//int connresult;
do{
connect.DoModal();//显示连接对话框
}while(!connect.quit&&!ConnectToServer(connect.m_username,connect.m_ipaddr));
if(connect.quit)
{
connected=false;
}
else
connected=true;
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
nIndex=-1;
if(!connected)
m_chat.EnableWindow(FALSE);//没连接服务器端,不能选中通讯对象
m_send.EnableWindow(FALSE);//没连接服务器端,不能发送数据
return TRUE; // return TRUE unless you set the focus to a control
}
void CClientDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CClientDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CClientDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
bool CClientDlg::ConnectToServer(LPCTSTR name, LPCSTR ipaddr)//向服务器发送连接消息
{
m_yourname=name;
m_pname=name;
m_psocket=new CChatSocket(this);
if(!m_psocket->Create())//创建套接字
{
delete m_psocket;
m_psocket=NULL;
MessageBox("Socket Created error!");
return false;
}
while(!m_psocket->Connect(ipaddr,5555))//连接服务器
{
CString strTemp;
strTemp.LoadString(IDS_CONNECTIONERROR);
if(AfxMessageBox("连接错误,重连?",MB_YESNO)==IDNO)
{
delete m_psocket;
m_psocket=NULL;
return false;
}
}
m_pfile=new CSocketFile(m_psocket);//连接成功,初始化文件对象
m_pin=new CArchive(m_pfile,CArchive::load);
m_pout=new CArchive(m_pfile,CArchive::store);
connected=true;
msg.msgtype=MSG_CTS_newclient;//消息格式:C->S 新上线客户端
msg.from=0;
msg.to=0;
msg.chatcontent=name;
sendmsg();//发送消息
return true;
}
void CClientDlg::sendmsg()//发送消息给服务端
{
if(m_pout&&connected)
{
TRY{
msg.Serialize(*m_pout);
m_pout->Flush();
}CATCH(CFileException,e){
m_pout->Abort();
delete m_pout;
m_pout=NULL;
}END_CATCH
}
}
void CClientDlg::receivemsg()//接收数据
{
if(m_pin&&connected)
{
TRY{
msg.Serialize(*m_pin);
msginterpreter();
}CATCH(CFileException,e){
m_pin->Abort();
delete m_pin;
m_pin=NULL;
}END_CATCH
}
}
//接收数据
void CClientDlg::readall()
{
do{
receivemsg();
if(m_psocket==NULL)
return;
}while(!m_pin->IsBufferEmpty());//缓冲区包含多个数据消息,需要循环直到所有的数据都被读出,并且缓冲区被清空
}
void CClientDlg::msginterpreter()//对消息进行处理
{
switch(msg.msgtype)
{
case MSG_CTC:
showmsg();
break;
case MSG_STC_newclient://客户端上线
addonline();
break;
case MSG_STC_alonline://已经在线的客户端
addonline();
break;
case MSG_STC_clientdown://客户端下线
delonline(msg.from);//客户端下线处理
break;
case MSG_STC_serverdown://服务器关闭
delconnection(); //释放连接
m_chat.EnableWindow(FALSE);//不允许再选中通讯对象
m_send.EnableWindow(FALSE);//不允许再发送数据
MessageBox(" 服务器关闭! ");
break;
case MSG_STC_yourmsg://服务端把客户端序号发给客户端
this->seq=msg.from;
break;
default:
MessageBox("Error!");
break;
}
}
void CClientDlg::showmsg()//显示通讯内容
{
for(POSITION pos=m_onlinelist.GetHeadPosition();pos!=NULL;)
{
OnlineNode* p=(OnlineNode*)m_onlinelist.GetNext(pos);
if(p->seq==msg.from)
{
m_chatcontent.AddString(p->username+" 说:");//通讯内容,显示发送端用户名
m_chatcontent.AddString(" "+msg.chatcontent);//msg.chatcontent代表发送的内容
break;
}
}
}
void CClientDlg::addonline()//客户端上线或在线处理
{
m_namelist.AddString(msg.chatcontent);//获得在线或新上线的用户名
OnlineNode* p=new OnlineNode;
p->username=msg.chatcontent;
p->seq=msg.from; //在线或新上线用户编号
m_onlinelist.AddTail(p);//保存客户端信息
}
void CClientDlg::delonline(int num)//客户端下线处理
{
bool found=false;
int i=0;
POSITION prepos;
for(POSITION pos=m_onlinelist.GetHeadPosition();pos!=NULL;i++)
{
prepos=pos;
OnlineNode* p=(OnlineNode*)m_onlinelist.GetNext(pos);
if(p->seq==num)
{
m_onlinelist.RemoveAt(prepos);//清除下线客户端信息
found=true;
break;
}
}
if(found)
{
if(num==destchatter.seq)//查找下线客户端通讯对象
{
m_send.EnableWindow(FALSE);//不允许再向下线用户发消息
MessageBox("用户"+destchatter.username+": 下线了!");
}
if(i==nIndex)
{
m_selected=_T("");
UpdateData(FALSE);
nIndex=-1;
}
m_namelist.DeleteString(i);//清除客户端用户名
}
}
void CClientDlg::delconnection()//释放连接
{
connected=false;
if(m_pin)
{
delete m_pin;
m_pin=NULL;
}
if(m_pout)
{
delete m_pout;
m_pout=NULL;
}
if(m_pfile)
{
delete m_pfile;
m_pfile=NULL;
}
if(m_psocket)
{
delete m_psocket;
m_psocket=NULL;
}
}
void CClientDlg::OnSelchangeOnline()//选中通讯对象
{
// TODO: Add your control notification handler code here
nIndex=m_namelist.GetCurSel();
m_namelist.GetLBText(nIndex,m_selected);
}
void CClientDlg::OnChat()//与被选中的客户端通讯
{
// TODO: Add your control notification handler code here
POSITION pos=m_onlinelist.FindIndex(nIndex);
if(pos)
{
OnlineNode* p=(OnlineNode*)m_onlinelist.GetNext(pos);
m_send.EnableWindow(TRUE);//允许发送数据
destchatter.seq=p->seq; //发送数据的目的端
m_namelist.GetLBText(nIndex,destchatter.username);//被选中的客户端通讯若下线,获得其用户名
}
else{
m_send.EnableWindow(FALSE);//不允许发送数据
MessageBox("请选中聊天对象!");
}
}
void CClientDlg::OnQuit() //退出
{
// TODO: Add your control notification handler code here
OnOK();
}
void CClientDlg::OnSend() //发送数据
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
m_chatcontent.AddString(m_yourname+" :");//通讯内容,显示发送端用户名
m_chatcontent.AddString(" "+m_readymsg);//通讯内容,显示发送数据内容
msg.msgtype=MSG_CTC;
msg.from=seq;
msg.chatcontent=m_readymsg;
msg.to=destchatter.seq;
sendmsg();
m_readymsg="";//清空通讯内容
UpdateData(FALSE);
}
void CClientDlg::OnDestroy()//关闭对话框
{
CDialog::OnDestroy();
// TODO: Add your message handler code here
if(m_psocket)
{
msg.msgtype=MSG_CTS_clientdown;
msg.from=seq;
msg.chatcontent=_T("");
sendmsg();
delconnection();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -