📄 clientdlg.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 + -