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

📄 clientdlg.cpp

📁 面向软件工程的Visual C++网络程序开发
💻 CPP
字号:
// ClientDlg.cpp : implementation file
//

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

#include "LoginDlg.h"

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

/////////////////////////////////////////////////////////////////////////////
// CClientDlg dialog

CClientDlg::CClientDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CClientDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CClientDlg)
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_bConnected = FALSE;
	m_pSocket = NULL;
	m_pChatSock = NULL;
//	m_uChatPort = 4000;
}

CClientDlg::~CClientDlg() 
{
	if (m_pSocket != NULL)
		delete m_pSocket;
	if (m_pChatSock != NULL)
		delete m_pChatSock;
}

void CClientDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CClientDlg)
	DDX_Control(pDX, IDC_STATE_EDIT, m_edtState);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CClientDlg, CDialog)
	//{{AFX_MSG_MAP(CClientDlg)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_COMMAND(ID_NETWORK_LOGIN, OnNetworkLogin)
	ON_COMMAND(ID_NETWORK_LOGOUT, OnNetworkLogout)
	ON_COMMAND(ID_NETWORK_EXIT, OnNetworkExit)
	ON_CBN_SELCHANGE(IDC_NAMELIST_COMBO, OnSelchangeNamelistCombo)
	ON_WM_CLOSE()
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_SENDMESSAGE_BUTTON, OnSendmessageButton)
	ON_BN_CLICKED(IDC_CANCEL_BUTTON, OnCancelButton)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CClientDlg message handlers

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

	// 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
	
	CString strInfo;
	strInfo.Format(IDS_SERVINFO, "0.0.0.0", 0, "未");
	SetDlgItemText(IDC_SERVINFO_STATIC, strInfo);
	strInfo.Format(IDS_FRIENDINFO, "0.0.0.0", 0);
	SetDlgItemText(IDC_FRIENDINFO_STATIC, strInfo);
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

// 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::AddNameList()
{
	// Static 复位
	CString strMsg;
	strMsg.Format(IDS_FRIENDINFO, "0.0.0.0", 0);
	SetDlgItemText(IDC_FRIENDINFO_STATIC, strMsg);
	
	if (m_UserList.GetCount() == 0)
		return FALSE;

	CComboBox* pCombo = (CComboBox*)GetDlgItem(IDC_NAMELIST_COMBO);
	pCombo->ResetContent();
	//
	POSITION   pos = m_UserList.GetHeadPosition();
	USER_INFO* pFirst;
	//
	for (int i = 0; i < m_UserList.GetCount(); i++)
	{
		USER_INFO* pInfo = m_UserList.GetNext(pos);
		if (i == 0) {
			pFirst = pInfo;
		}
		pCombo->AddString(pInfo->name);
	}
	//
	pCombo->SetCurSel(0);
	OnSelchangeNamelistCombo();

	return TRUE;
}

//---------------------------------------------------------------------------
BOOL CClientDlg::DelUserInfo(USER_INFO* pInfo)
{
	// CComboBox* pCombo = (CComboBox*)GetDlgItem(IDC_NAMELIST_COMBO);

	POSITION pos = m_UserList.GetHeadPosition();
	//
	for (int i = 0; i < m_UserList.GetCount(); i++)
	{
		POSITION t = pos;
		USER_INFO* pTemp = m_UserList.GetNext(pos);
		if (strcmp(pInfo->name, pTemp->name) == 0 &&
			pInfo->addr == pTemp->addr &&
			pInfo->port == pTemp->port)  {// found it
			m_UserList.RemoveAt(t);
			delete pTemp;
			// pCombo->ResetContent();
			return TRUE;
		}
	}
	//
	return FALSE;
}

//--------------------------------------------------------------------------
void CClientDlg::AddMessage(CString& message)
{
	CTime t = CTime::GetCurrentTime();
	CString strTime = "%m月%d日%h时%M分%S秒";
	strTime = t.Format(strTime);
	//
	CString strEdit;
	m_edtState.GetWindowText(strEdit);
	
	if (strEdit.IsEmpty()) {
		m_edtState.SetWindowText(strEdit + strTime + ": " + message);
	}
	else {
		int len = strlen(strEdit);
		m_edtState.SetSel(len, len, TRUE);
		m_edtState.ReplaceSel("\r\n" + strTime + ": " + message);
		m_edtState.SetSel(len, len, TRUE);
	}
}

//--------------------------------------------------------------------------- 
void CClientDlg::OnNetworkLogin() 
{
	if (m_bConnected) // if connected, logout first
		OnNetworkLogout();
	//
	CLoginDlg dlgLogin;	
	//
	if (dlgLogin.DoModal() == IDCANCEL) {
		TRACE0("cancel login");
		return;
	}
	//
	m_strHostAddr = dlgLogin.m_strHostAddr;
	m_uHostPort   = dlgLogin.m_uHostPort;
	m_strUserName = dlgLogin.m_strUserName;
	m_strPassword = dlgLogin.m_strPassword;

	// 创建新的Socket并连接到服务器
	m_pSocket = new CClientSocket(this);
		
	if (!m_pSocket->Create()) {
		TRACE0("failed to create client socket");
		return;
	}
	// connect to server
	CString strMsg;

	m_pSocket->Connect(m_strHostAddr, m_uHostPort);
	//  TRACE0("failed to connected to server\n");
	//	strMsg.Format(IDS_DISCONNECTED, m_strHostAddr, m_uHostPort);
	//	strMsg.Format(IDS_CONNECTED, m_strHostAddr, m_uHostPort);
//	AddMessage(strMsg);
}

//--------------------------------------------------------------------------- 
void CClientDlg::OnNetworkLogout() 
{
	if (!m_bConnected)
		return;

	// 向服务器发送登出消息
	SOCKADDR_IN addr;
	int			len = sizeof(addr);
	m_pSocket->GetSockName((SOCKADDR*)&addr, &len);

	USER_INFO info;
	strcpy(info.name, m_strUserName);
	info.addr = addr.sin_addr.s_addr;
	info.port = addr.sin_port;

	// padding infomation
	const int bufLen = sizeof(WORD) + sizeof(USER_INFO);
	static char buffer[bufLen];
	*(WORD*)buffer = PACKAGE_LOGOUT;
	memcpy((void*)(buffer + sizeof(WORD)), (void*)&info, sizeof(info));

	// send it
	if (m_pSocket->Send((void*)buffer, bufLen, 0) <= 0) {
		TRACE0("Unable to send logout message.");
		return;
	}
	//
	// Sleep(5000);
}

//--------------------------------------------------------------------------- 
void CClientDlg::OnNetworkExit() 
{
	if (m_bConnected) {
		OnNetworkLogout();
	}
	
	PostQuitMessage(EXIT_SUCCESS);
}

//--------------------------------------------------------------------------- 
void CClientDlg::OnSelchangeNamelistCombo() 
{
	CString strSel;
	CComboBox* pCombo = (CComboBox*)GetDlgItem(IDC_NAMELIST_COMBO);
	pCombo->GetWindowText(strSel);
	//
	POSITION pos = m_UserList.GetHeadPosition();
	//
	for (int i = 0; i < m_UserList.GetCount(); i++)
	{
		USER_INFO* pInfo = m_UserList.GetNext(pos);
		if (strcmp(strSel, pInfo->name) == 0) {
			CString strLabel;
			strLabel.Format(IDS_FRIENDINFO, inet_ntoa(*(in_addr*)&pInfo->addr), ntohs(pInfo->port));
			SetDlgItemText(IDC_FRIENDINFO_STATIC, strLabel);
		}
	}
}

//--------------------------------------------------------------------------- 
void CClientDlg::OnClose() 
{
	CDialog::OnClose();
}

//--------------------------------------------------------------------------- 
void CClientDlg::OnDestroy() 
{
	OnNetworkLogout();	
	CDialog::OnDestroy();	
}

void CClientDlg::OnSendmessageButton() 
{
	// 得到欲发送的消息
	static char buffer[0x1002];
	*(WORD*)buffer = PACKAGE_MESSAGE;
	int length = GetDlgItemText(IDC_MESSAGE_EDIT, buffer + sizeof(WORD), 0x1000);

	if (length == 0) {
		return;
	}

	// 找到对方IP
	CString strUserName;
	GetDlgItemText(IDC_NAMELIST_COMBO, strUserName);
	if (strUserName.IsEmpty()) {
		return;
	}

	SOCKADDR_IN addrIn;
	addrIn.sin_family = AF_INET;
	// addrIn.sin_port = m_uChatPort;
	memset(addrIn.sin_zero, 0, 8);

	POSITION pos = m_UserList.GetHeadPosition();
	// 这里我们的数据报端口选择策略是: 
	//	   取该用户连接到服务器的端口 / 2 + 1024
	for (int i = 0; i < m_UserList.GetCount(); i++)
	{
		USER_INFO* pInfo = m_UserList.GetNext(pos);
		if (strcmp(strUserName, pInfo->name) == 0) {
			addrIn.sin_addr.s_addr = pInfo->addr;
			addrIn.sin_port = htons((ntohs(pInfo->port) << 1) + 1);
			break;
		} // if		
	} // for

	// 发送数据
	if (!m_pChatSock->SendTo(buffer, 
							 sizeof(WORD) + length + 1, 
							 (SOCKADDR*)&addrIn, 
							 sizeof(addrIn),
							 0)) {
							 
		TRACE0("faile to send messge.\n");
		return;
	}
	// 重置消息Edit
	SetDlgItemText(IDC_MESSAGE_EDIT, "");
}

void CClientDlg::OnCancelButton() 
{
	SetDlgItemText(IDC_MESSAGE_EDIT, "");
}

// 创建Chat Socket
void CClientDlg::CreateChatSocket()
{
	if (m_pChatSock != NULL) {
		delete m_pChatSock;
	}

	CString strOurAddr;
	UINT uOurPort;
	m_pSocket->GetSockName(strOurAddr, uOurPort);
	
	m_pChatSock = new CChatSocket(this);
	// 聊天端口号 = 服务器连接的端口号 * 2 + 1
	if (!m_pChatSock->Create((uOurPort << 1) + 1, 
			SOCK_DGRAM, 
			FD_READ | FD_WRITE |FD_CLOSE, NULL)) {
			TRACE0("failed to create chat socket.\n");
			CString strError;
			strError.Format(IDS_CREATE_CHAT_SOCKET_ERROR, 
							strOurAddr, 
							uOurPort);
			AddMessage(strError);
	}
	
}

void CClientDlg::ResetUserInfo()
{
	if (m_UserList.GetCount() == 0)
		return;
	// 删除用户列表
	POSITION pos = m_UserList.GetHeadPosition();

	while (pos != NULL) {
		delete m_UserList.GetNext(pos);
	}
	
	// 清除组合框内容
	CComboBox* pCombo = (CComboBox*)GetDlgItem(IDC_NAMELIST_COMBO);
	pCombo->ResetContent();
	
	// 重置Static的内容
	CString strMsg;
	strMsg.Format(IDS_FRIENDINFO, "0.0.0.0", 0);
	SetDlgItemText(IDC_FRIENDINFO_STATIC, strMsg);
}

USER_INFO* CClientDlg::FindUserInfo(SOCKADDR_IN &addr)
{
	POSITION pos = m_UserList.GetHeadPosition();
	
	while (pos != NULL) {
		USER_INFO* pInfo = m_UserList.GetNext(pos);
		if (pInfo->addr == addr.sin_addr.s_addr &&
			pInfo->port == addr.sin_port) {
			return pInfo;
		}
	}

	return NULL;
}


⌨️ 快捷键说明

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