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

📄 clientdlg.cpp

📁 关于ACE的书籍,对于学习ACE很有帮助,这里只有上册,下册过些时候在传.
💻 CPP
字号:
// ClientDlg.cpp : 实现文件
//


#include "stdafx.h"
#include "Client.h"
#include "ClientDlg.h"



#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// 对话框数据
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CClientDlg 对话框




CClientDlg::CClientDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CClientDlg::IDD, pParent)
	, m_dwBytesRECV(0)
	,m_RecvBuff(512)
	,m_SendBuff(512)
	, m_isConnect(false)
	, m_szName(_T(""))
	, m_Timer(0)
	, m_ePort(27015)
{
	ConnectSocket = INVALID_SOCKET;
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CClientDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Text(pDX, IDE_PORT, m_ePort);
}

BEGIN_MESSAGE_MAP(CClientDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_SOCKET,&CClientDlg::OnSocketEvent)
	ON_BN_CLICKED(IDB_CONNECT, &CClientDlg::OnBnConnect)
	ON_BN_CLICKED(IDB_SEND, &CClientDlg::OnBnSend)
	ON_WM_TIMER()
END_MESSAGE_MAP()


// CClientDlg 消息处理程序

BOOL CClientDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	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);
		}
	}

	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	//SetDlgItemInt(IDE_PORT,27015);
	SetDlgItemText(IDI_ADDRESS,L"127.0.0.1");

	((CListCtrl*)GetDlgItem(IDL_USER))->InsertColumn(0,L"Members",LVCFMT_LEFT,80,-1);
	((CListCtrl*)GetDlgItem(IDL_USER))->InsertColumn(1,L"Messages",LVCFMT_LEFT,100,-1);

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CClientDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CClientDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		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;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}


HCURSOR CClientDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void CClientDlg::OnBnConnect()
{
	int iResult;
	CString strErr;
	WSADATA wsaData;
	ADDRINFOW *result = NULL,*ptr = NULL;
	ADDRINFOW hints;
	CString ServerPort;
	CString ServerIP;

	GetDlgItemText(IDE_NAME,m_szName);
	if (m_szName.GetLength() <= 0)return ;

	if (m_isConnect)
	{
		closesocket(ConnectSocket);
		WSACleanup();
		m_isConnect = false;
		//KillTimer(m_Timer);
		GetDlgItem(IDE_NAME)->EnableWindow(TRUE);
		GetDlgItem(IDE_PORT)->EnableWindow(TRUE);
		GetDlgItem(IDI_ADDRESS)->EnableWindow(TRUE);
		SetDlgItemText(IDB_CONNECT,L"Connect");
		while ( ((CListCtrl*)GetDlgItem(IDL_USER))->DeleteItem (1));
		return ;
	}
	GetDlgItemText(IDE_PORT,ServerPort);
	GetDlgItemText(IDI_ADDRESS,ServerIP);
	((CListCtrl*)GetDlgItem(IDL_USER))->InsertColumn(0,L"Members",LVCFMT_LEFT,80,-1);
	((CListCtrl*)GetDlgItem(IDL_USER))->InsertColumn(1,L"Messages",LVCFMT_LEFT,100,-1);

	iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
	if (iResult != 0) {
		strErr.Format(L"WSAStartup failed: %d\n", iResult);
		MessageBox(strErr);
		return ;
	}

	ZeroMemory( &hints, sizeof(hints) );
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	iResult = GetAddrInfo(ServerIP,ServerPort, &hints, &result);
	if ( iResult != 0 ) {
		strErr.Format(L"getaddrinfo failed: %d\n", iResult);
		MessageBox(strErr);
		WSACleanup();
		return ;
	}

	for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
		// Create a SOCKET for connecting to server
		ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, 
			ptr->ai_protocol);
		if (ConnectSocket == INVALID_SOCKET) {
			strErr.Format(L"Error at socket(): %ld\n", WSAGetLastError());
			MessageBox(strErr);
			FreeAddrInfo(result);
			WSACleanup();
			return ;
		}
		// Connect to server.
		iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
		if (iResult == SOCKET_ERROR) {
			closesocket(ConnectSocket);
			ConnectSocket = INVALID_SOCKET;
			continue;
		}
		break;
	}
	FreeAddrInfo(result);

	if (ConnectSocket == INVALID_SOCKET) {
		MessageBox(L"Unable to connect to server!\n");
		WSACleanup();
		return ;
	}

	if((WSAAsyncSelect(ConnectSocket, this->m_hWnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE))==SOCKET_ERROR){
		MessageBox(L"WSAAsyncSelect error");
		return ;
	}

	CMsg loginMsg;
	ZeroMemory(&loginMsg,sizeof loginMsg);
	loginMsg.MsgHead.eCmdID = CMD_LOGIN;
	loginMsg.MsgHead.dwToken = 0;
	loginMsg.MsgHead.dwLength = sizeof CMD_ID+2*sizeof DWORD+NAME_LEN*4;
	memcpy(loginMsg.MsgLogin.szUsername,m_szName,(m_szName.GetLength()+1)*2);
	SendMsg(&loginMsg);


	m_isConnect = true;
	GetDlgItem(IDE_NAME)->EnableWindow(FALSE);
	GetDlgItem(IDE_PORT)->EnableWindow(FALSE);
	GetDlgItem(IDI_ADDRESS)->EnableWindow(FALSE);
	SetDlgItemText(IDB_CONNECT,L"Disconnect");
	//m_Timer = SetTimer(1,1000,NULL);

}
#define DATA_BUFSIZE 512
LRESULT CClientDlg::OnSocketEvent(WPARAM   wParam,LPARAM   lParam){
	CString strErr;
	CString strMsg;
	LVFINDINFO FindInfo;

	if (WSAGETSELECTERROR(lParam))
	{
		PostMessage(WM_SOCKET,wParam,FD_CLOSE);
		//FreeSocketInformation(wParam);
	} 
	else
	{
		switch(WSAGETSELECTEVENT(lParam)){
			case FD_READ:
				if(RecvMsg()){
					CMsg * ptrMsg = new CMsg;
					if(!DecodingBuff(ptrMsg)){
						delete ptrMsg;
						m_RecvBuff.ReSet();
						break;
					}
					if(ptrMsg->MsgHead.eCmdID == CMD_MSG_CHAT){
						FindInfo.flags = LVFI_STRING;
						FindInfo.psz = ptrMsg->MsgNew.szUsername;
						int iIndex = ((CListCtrl*)GetDlgItem(IDL_USER))->FindItem(&FindInfo);
						int iMsgs=_wtoi(((CListCtrl*)GetDlgItem(IDL_USER))->GetItemText(iIndex,1));
						strMsg.Format(L"%d",++iMsgs);
						((CListCtrl*)GetDlgItem(IDL_USER))->SetItemText(iIndex,1,strMsg);
						strMsg.Format(L"%s Say:\n%s\n",ptrMsg->MsgChat.szSender,ptrMsg->MsgChat.szContent);
						


					}
					else if (ptrMsg->MsgHead.eCmdID == CMD_NEW)
					{
						strMsg.Format(L"%s Login\n",ptrMsg->MsgNew.szUsername);
						((CListCtrl*)GetDlgItem(IDL_USER))->InsertItem(0,ptrMsg->MsgNew.szUsername);
						((CListCtrl*)GetDlgItem(IDL_USER))->SetItemText(0,1,L"0");
					}
					else if(ptrMsg->MsgHead.eCmdID == CMD_LOGOUT){
						strMsg.Format(L"%s Logout\n",ptrMsg->MsgNew.szUsername);
						FindInfo.flags = LVFI_STRING;
						FindInfo.psz = ptrMsg->MsgNew.szUsername;
						((CListCtrl*)GetDlgItem(IDL_USER))->DeleteItem(
							((CListCtrl*)GetDlgItem(IDL_USER))->FindItem(&FindInfo));
					}
					m_RecvBuff.ReSet();
					delete ptrMsg;
					((CEdit*)GetDlgItem(IDE_RECV_MSG))->SetSel(-1);
					((CEdit*)GetDlgItem(IDE_RECV_MSG))->ReplaceSel(strMsg);
				}
			break;
			// DO NOT BREAK HERE SINCE WE GOT A SUCCESSFUL RECV. Go ahead
			// and begin writing data to the client.

		case FD_WRITE:
			//GetDlgItemText(IDE_SEND_MSG,strMsg);
			
			break;

		case FD_CLOSE:
			GetDlgItem(IDE_NAME)->EnableWindow(TRUE);
			GetDlgItem(IDE_PORT)->EnableWindow(TRUE);
			GetDlgItem(IDI_ADDRESS)->EnableWindow(TRUE);
			while ( ((CListCtrl*)GetDlgItem(IDL_USER))->DeleteItem (1));

			SetDlgItemText(IDB_CONNECT,L"Connect");
			m_isConnect = FALSE;
			closesocket(ConnectSocket);
			WSACleanup();
			break;
		}
	}
	return 0;
}
void CClientDlg::OnBnSend()
{
	CString		strMsg;
	DWORD		strLen = 0;
	CMD_ID		MsgType = CMD_MSG_CHAT;
	DWORD		dwLen = 0;
	
	GetDlgItemText(IDE_SEND_MSG,strMsg);
	strLen = strMsg.GetLength();
	if (strLen <= 0)
	{
		//do not send empty msg
		return ;
	}

	CMsg newMsg;
	newMsg.MsgHead.eCmdID = CMD_MSG_CHAT;
	newMsg.MsgHead.dwToken = 0;
	newMsg.MsgHead.dwLength = sizeof CMD_ID+3*sizeof DWORD+NAME_LEN*2+(strLen+1)*2;

	memcpy(newMsg.MsgChat.szSender,m_szName,(m_szName.GetLength()+1)*2);
	newMsg.MsgChat.dwLength = (strLen+1)*2;
	newMsg.MsgChat.szContent = new wchar_t[strLen+1];
	memcpy(newMsg.MsgChat.szContent,strMsg,newMsg.MsgChat.dwLength);
	SendMsg(&newMsg);

	strMsg = m_szName + L"Say:"+strMsg;
	strMsg+=L"\n";
	((CEdit*)GetDlgItem(IDE_RECV_MSG))->SetSel(-1);
	((CEdit*)GetDlgItem(IDE_RECV_MSG))->ReplaceSel(strMsg);
	SetDlgItemText(IDE_SEND_MSG,L"");
}


bool CClientDlg::DecodingBuff(CMsg* ptrMsg)
{
	if (!ptrMsg)return FALSE;
	DWORD dwPos = 0;

	m_RecvBuff.GetFromBuffer((char*)(&(ptrMsg->MsgHead.dwLength)),dwPos,sizeof DWORD);
	dwPos += sizeof DWORD;
	m_RecvBuff.GetFromBuffer((char*)(&(ptrMsg->MsgHead.eCmdID)),dwPos,sizeof CMD_ID);
	dwPos += sizeof CMD_ID;
	m_RecvBuff.GetFromBuffer((char*)(&(ptrMsg->MsgHead.dwToken)),dwPos,sizeof DWORD);
	dwPos += sizeof DWORD;

	if(ptrMsg->MsgHead.eCmdID == CMD_MSG_CHAT){
		m_RecvBuff.GetFromBuffer((char*)ptrMsg->MsgChat.szSender,dwPos,sizeof ptrMsg->MsgChat.szSender);
		dwPos += sizeof ptrMsg->MsgChat.szSender;
		m_RecvBuff.GetFromBuffer((char*)(&(ptrMsg->MsgChat.dwLength)),dwPos,sizeof DWORD);
		dwPos += sizeof DWORD;
		ptrMsg->MsgChat.szContent = new wchar_t [ptrMsg->MsgChat.dwLength/2];
		m_RecvBuff.GetFromBuffer((char*)ptrMsg->MsgChat.szContent,dwPos,ptrMsg->MsgChat.dwLength);
	}
	else if(ptrMsg->MsgHead.eCmdID == CMD_NEW){
		m_RecvBuff.GetFromBuffer((char*)ptrMsg->MsgNew.szUsername,dwPos,sizeof ptrMsg->MsgNew.szUsername);
	}
	else if(ptrMsg->MsgHead.eCmdID == CMD_LOGOUT){
		m_RecvBuff.GetFromBuffer((char*)ptrMsg->MsgNew.szUsername,dwPos,sizeof ptrMsg->MsgNew.szUsername);
	}
	return TRUE;
}

void CClientDlg::CodingBuff(CMsg* ptrMsg){
	m_SendBuff.AddToBuffer((char*)(&(ptrMsg->MsgHead.dwLength)),sizeof DWORD);
	m_SendBuff.AddToBuffer((char*)(&(ptrMsg->MsgHead.eCmdID)),sizeof CMD_ID);
	m_SendBuff.AddToBuffer((char*)(&(ptrMsg->MsgHead.dwToken)),sizeof DWORD);

	if(ptrMsg->MsgHead.eCmdID == CMD_MSG_CHAT){
		m_SendBuff.AddToBuffer((char*)ptrMsg->MsgChat.szSender,sizeof ptrMsg->MsgChat.szSender);
		m_SendBuff.AddToBuffer((char*)(&(ptrMsg->MsgChat.dwLength)),sizeof DWORD);
		m_SendBuff.AddToBuffer((char*)ptrMsg->MsgChat.szContent,ptrMsg->MsgChat.dwLength);
	}
	else if(ptrMsg->MsgHead.eCmdID == CMD_LOGIN){
		m_SendBuff.AddToBuffer((char*)ptrMsg->MsgLogin.szUsername,sizeof ptrMsg->MsgLogin.szUsername);
		m_SendBuff.AddToBuffer((char*)ptrMsg->MsgLogin.szPassWord,sizeof ptrMsg->MsgLogin.szPassWord);
	}
}

void CClientDlg::SendMsg(CMsg* ptrMsg)
{
	WSABUF		wsaBuf;
	DWORD		SendBytes = 0;

	CodingBuff(ptrMsg);
	//CMsg msg;
	//DecodingBuff(&msg);
	wsaBuf.buf = m_SendBuff.GetBuffer();
	wsaBuf.len = m_SendBuff.GetLength();

	while(SendBytes < wsaBuf.len){
		if (WSASend(ConnectSocket, &wsaBuf, 1, &SendBytes, 0,
			NULL, NULL) == SOCKET_ERROR)
		{
			if (WSAGetLastError() != WSAEWOULDBLOCK)
			{
				printf("WSASend() failed with error %d\n", WSAGetLastError());
				//FreeSocketInformation(wParam);
				return ;
			}
		}
	}
	m_SendBuff.ReSet();
}

bool CClientDlg::RecvMsg()
{
	DWORD	Flags=0;
	char	szBuff[DATA_BUFSIZE];
	WSABUF  wsaBuf;
	DWORD	RecvBytes;
	DWORD   BytesRECV=0;

	while(BytesRECV != sizeof DWORD){
		wsaBuf.buf = szBuff;
		wsaBuf.len = sizeof DWORD-BytesRECV;
		if (WSARecv(ConnectSocket, &wsaBuf, 1, &RecvBytes,
			&Flags, NULL, NULL) == SOCKET_ERROR)
		{
			if (WSAGetLastError() != WSAEWOULDBLOCK)return FALSE;
		} 
		BytesRECV += RecvBytes;
		m_RecvBuff.AddToBuffer(szBuff,RecvBytes);
	}
	DWORD dwLength;
	m_RecvBuff.GetFromBuffer((char*)(&dwLength),0,sizeof DWORD);
	while(BytesRECV != dwLength){
		wsaBuf.buf = szBuff;
		wsaBuf.len = (dwLength-BytesRECV)/DATA_BUFSIZE ? DATA_BUFSIZE:dwLength-BytesRECV;
		if (WSARecv(ConnectSocket, &wsaBuf, 1, &RecvBytes,
			&Flags, NULL, NULL) == SOCKET_ERROR)
		{
			if (WSAGetLastError() != WSAEWOULDBLOCK)return FALSE;
		} 
		BytesRECV += RecvBytes;
		m_RecvBuff.AddToBuffer(szBuff,RecvBytes);
	}
	BytesRECV = 0;
	return TRUE;
}

void CClientDlg::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: Add your message handler code here and/or call default

	CString strErr;
	CString strMsg;


	if(RecvMsg()){
		CMsg * ptrMsg = new CMsg;
		if(!DecodingBuff(ptrMsg)){
			delete ptrMsg;
			m_RecvBuff.ReSet();
			return ;
		}
		if(ptrMsg->MsgHead.eCmdID == CMD_MSG_CHAT){
			strMsg.Format(L"%s Say:\n%s\n",ptrMsg->MsgChat.szSender,ptrMsg->MsgChat.szContent);
		}
		else if (ptrMsg->MsgHead.eCmdID == CMD_NEW)
		{
			strMsg.Format(L"%s Login\n",ptrMsg->MsgNew.szUsername);
		}
		m_RecvBuff.ReSet();
		((CEdit*)GetDlgItem(IDE_RECV_MSG))->SetSel(-1);
		((CEdit*)GetDlgItem(IDE_RECV_MSG))->ReplaceSel(strMsg);
	}


	CDialog::OnTimer(nIDEvent);
}

⌨️ 快捷键说明

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