www.pudn.com > messagerfairyfhfhfhgf.zip > ClientDlg.cpp
// ClientDlg.cpp : implementation file // #include "stdafx.h" #include "Client.h" #include "ClientDlg.h" #include#include #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// #define DISCONNECT_TIMER (WM_USER + 101) #define LOGINFAILED_TIMER (WM_USER + 102) ///////////////////////////////////////////////////////////////////////////// static void HandleClientNetEvent(IN SOCKET hSocket, IN ETransportEvent eEvent, IN void *pDataBuf, IN unsigned long nDataLen, IN int nError, IN void *pContext) { if( nError != TRANSPORT_OK ) return; CClientDlg *pDlg = (CClientDlg *)pContext; if( NULL == pDlg ) return; pDlg->ProcessNetEvent(eEvent, pDataBuf, nDataLen); } ///////////////////////////////////////////////////////////////////////////// // CClientDlg dialog CClientDlg::CClientDlg(CWnd* pParent /*=NULL*/) : CDialog(CClientDlg::IDD, pParent) { //{{AFX_DATA_INIT(CClientDlg) m_strServerAddress = _T(""); m_strChatMessage = _T(""); m_strUserName = _T(""); //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CClientDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CClientDlg) DDX_Control(pDX, IDC_CMB_USERNAME, m_cmbUserName); DDX_Control(pDX, IDC_CHAT_MESSAGE, m_editChatMessage); DDX_Control(pDX, IDC_CMB_CHATMESSAGE, m_cmbChatMessage); DDX_Control(pDX, IDC_MESSGAE_LIST, m_ctrlUserList); DDX_Control(pDX, IDC_CMB_SERVERADDRESS, m_cmbServerAddress); DDX_CBString(pDX, IDC_CMB_SERVERADDRESS, m_strServerAddress); DDV_MaxChars(pDX, m_strServerAddress, 16); DDX_CBString(pDX, IDC_CMB_CHATMESSAGE, m_strChatMessage); DDV_MaxChars(pDX, m_strChatMessage, 256); DDX_CBString(pDX, IDC_CMB_USERNAME, m_strUserName); DDV_MaxChars(pDX, m_strUserName, 30); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CClientDlg, CDialog) //{{AFX_MSG_MAP(CClientDlg) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_CONNECT, OnConnect) ON_BN_CLICKED(IDC_DISCONNECT, OnDisconnect) ON_WM_TIMER() ON_BN_CLICKED(IDC_SEND, OnSend) //}}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 // TODO: Add extra initialization here int nResult = Transport_Init(); if( TRANSPORT_OK != nResult) { PostMessage(WM_CLOSE); } /////////////////////////////////////////////// SetConnectionID(INVALID_SOCKET); /////////////////////////////////////////////// /*Get Local Address*/ const int nIpAddressLen = MAX_IPADDRESS_LEN; const int nHostNameLen = MAX_HOSTNAME_LEN; char pIpAddress[nIpAddressLen] = {0}; char pHostName[nHostNameLen] = {0}; unsigned long ulIpAddress = m_tClientTunnel.net_GetLocalHostIp(pIpAddress, pHostName); if( ulIpAddress != SOCKET_ERROR ) { CString strIpAddress = (CString)pIpAddress; m_cmbServerAddress.InsertString(0, strIpAddress); m_cmbServerAddress.SetCurSel(0); CString strUserName = (CString)pHostName; m_cmbUserName.InsertString(0, strUserName); m_cmbUserName.SetCurSel(0); } GetDlgItem(IDC_CONNECT)->EnableWindow(TRUE); GetDlgItem(IDC_DISCONNECT)->EnableWindow(FALSE); m_ctrlUserList.EnableWindow(FALSE); if(::IsWindow(m_editChatMessage.GetSafeHwnd())) { COLORREF clrBk = RGB(160, 180, 220); m_editChatMessage.SetBackgroundColor(FALSE, clrBk); } CString strWindowText = (CString)WINDOW_TITLE; SetWindowText(strWindowText); 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; } void CClientDlg::ShowMessageText(const char *szMessageText) { CString strLogInfo = (CString)szMessageText; if( strLogInfo.IsEmpty() ) return; HWND hWnd = m_editChatMessage.GetSafeHwnd(); if( (NULL == hWnd) || (!::IsWindow(hWnd)) ) return; COLORREF clrText = RGB(0, 0, 0); int nType = -1; switch(nType) { case MB_OK: //操作记录 { clrText = RGB(128, 0, 255); break; } case MB_ICONINFORMATION: //提示信息 { clrText = RGB(0, 0, 128); break; } case MB_ICONEXCLAMATION: //警告信息 { clrText = RGB(255, 0, 0); break; } default: { clrText = RGB(0, 0, 0); break; } } m_editChatMessage.AppendText(strLogInfo, clrText); } //////////////////////////////////////////////////////////////////// void CClientDlg::ProcessNetEvent(int nEventType, void *pRecvMsg, DWORD dwDataLen) { if( Transport_ReadEv == nEventType ) { if( NULL == pRecvMsg ) return; TMessageHeader* pHeader = (TMessageHeader *)pRecvMsg; char *pDataBuf = (char *)pRecvMsg + MESSAGE_HEADER_LEN; WORD dwMessageID = pHeader->wMessageId; switch(dwMessageID) { case MSG_LOGIN_RESP: { LOGIN_RESULT_STRU tLoginResult = {0}; memcpy(&tLoginResult, pDataBuf, sizeof(LOGIN_RESULT_STRU)); ProcessLoginResponse(&tLoginResult); break; } case MSG_USERINFO_RESP: { TUSERLIST_INFO_STRU tUserListInfo = {0}; memcpy(&tUserListInfo, pDataBuf, sizeof(TUSERLIST_INFO_STRU)); ProcessUserListInfoResponse(&tUserListInfo); break; } case MSG_LOGOUT_RESP: { TUSERLIST_INFO_STRU tUserListInfo = {0}; memcpy(&tUserListInfo, pDataBuf, sizeof(TUSERLIST_INFO_STRU)); ProcessLogoutResponse(&tUserListInfo); break; } case MSG_CHATMESSAGE_RESP: { TCHAT_MESSAGE_STRU *pChatMessage = (TCHAT_MESSAGE_STRU *)pDataBuf; ProcessChatMessageResponse((void *)pChatMessage); break; } default: { break; } } } else if( Transport_CloseEv == nEventType ) { SetTimer(DISCONNECT_TIMER, 0, NULL); } /////// } void CClientDlg::OnOK() { // TODO: Add extra validation here CWnd *pFocusWnd = GetFocus(); if( NULL == pFocusWnd ) return; CEdit *pEditWnd = (CEdit *)m_cmbChatMessage.GetWindow(GW_CHILD); if( NULL != pEditWnd ) { if( pFocusWnd->m_hWnd == pEditWnd->m_hWnd ) { OnSend(); return; } } return; pEditWnd = (CEdit *)m_cmbServerAddress.GetWindow(GW_CHILD); if( NULL != pEditWnd ) { if( pFocusWnd->m_hWnd == pEditWnd->m_hWnd ) { OnConnect(); return; } } pEditWnd = (CEdit *)m_cmbUserName.GetWindow(GW_CHILD); if( NULL != pEditWnd ) { if( pFocusWnd->m_hWnd == pEditWnd->m_hWnd ) { OnConnect(); return; } } return; CDialog::OnOK(); } void CClientDlg::OnCancel() { // TODO: Add extra cleanup here if( INVALID_SOCKET != GetConnectionID() ) { int nResult = MessageBox("你真的要退出吗?", "请确认退出", MB_YESNO|MB_ICONQUESTION); if( IDYES != nResult ) return; } OnDisconnect(); Transport_UnInit(); CDialog::OnCancel(); } void CClientDlg::OnConnect() { // TODO: Add your control notification handler code here CWaitCursor wait; if( !UpdateData() ) return; CString strServerAddress = m_strServerAddress; strServerAddress.TrimLeft(); strServerAddress.TrimRight(); if( strServerAddress.IsEmpty() ) { ShowMessageText("请填写服务器地址!"); return; } CString strUserName = m_strUserName; strUserName.TrimLeft(); strUserName.TrimRight(); if( strUserName.IsEmpty() ) { ShowMessageText("请填写用户名字!"); return; } char *szServerAddress = strServerAddress.GetBuffer(0); strServerAddress.ReleaseBuffer(); /*for Client, IP and Port can be 0, and for Server, IP is LocalIP, and Port is Listening Port*/ int nResult = m_tClientTunnel.net_OpenSocket(Transport_Client, 0, HandleClientNetEvent, this); if( TRANSPORT_OK != nResult ) { ShowMessageText("网络初始化失败!"); return; } DWORD dwRemoteIPValue = inet_addr(szServerAddress); WORD wPort = SERVER_PORT; nResult = m_tClientTunnel.net_Connect(dwRemoteIPValue, wPort); if( TRANSPORT_OK != nResult ) { m_tClientTunnel.net_CloseSocket(); ShowMessageText("连接服务器失败!"); //MessageBox("连接服务器失败!", "警告", MB_OK|MB_ICONSTOP); return; } m_cmbChatMessage.SetFocus(); CEdit *pEditWnd = (CEdit *)m_cmbServerAddress.GetWindow(GW_CHILD); if( NULL != pEditWnd ) { pEditWnd->SetReadOnly(TRUE); } pEditWnd = (CEdit *)m_cmbUserName.GetWindow(GW_CHILD); if( NULL != pEditWnd ) { pEditWnd->SetReadOnly(TRUE); } if( CB_ERR == (m_cmbServerAddress.FindString(-1, strServerAddress)) ) { m_cmbServerAddress.InsertString(0, strServerAddress); } if( CB_ERR == (m_cmbUserName.FindString(-1, strUserName)) ) { m_cmbUserName.InsertString(0, strUserName); } GetDlgItem(IDC_CONNECT)->EnableWindow(FALSE); GetDlgItem(IDC_DISCONNECT)->EnableWindow(TRUE); ShowMessageText("连接服务器成功!"); ProcessLoginRequest(); } void CClientDlg::OnDisconnect() { // TODO: Add your control notification handler code here CWaitCursor wait; m_tClientTunnel.net_CloseSocket(); SetConnectionID(INVALID_SOCKET); CEdit *pEditWnd = (CEdit *)m_cmbServerAddress.GetWindow(GW_CHILD); if( NULL != pEditWnd ) { pEditWnd->SetReadOnly(FALSE); } pEditWnd = (CEdit *)m_cmbUserName.GetWindow(GW_CHILD); if( NULL != pEditWnd ) { pEditWnd->SetReadOnly(FALSE); } GetDlgItem(IDC_CONNECT)->EnableWindow(TRUE); GetDlgItem(IDC_DISCONNECT)->EnableWindow(FALSE); ShowMessageText("断开与服务器的连接!"); m_ctrlUserList.ResetContent(); m_ctrlUserList.EnableWindow(FALSE); SetWindowText((CString)WINDOW_TITLE); } void CClientDlg::OnSend() { // TODO: Add your control notification handler code here if( !UpdateData() ) return; CString strChatMessage = m_strChatMessage; strChatMessage.TrimLeft(); strChatMessage.TrimRight(); if( strChatMessage.IsEmpty() ) { m_strChatMessage.Empty(); UpdateData(FALSE); m_cmbChatMessage.SetFocus(); return; } if( INVALID_SOCKET == GetConnectionID() ) { ShowMessageText("请先连接服务器!"); return; } const char *szDataBuf = strChatMessage.GetBuffer(0); strChatMessage.ReleaseBuffer(); ProcessChatMessageRequest(szDataBuf); m_cmbChatMessage.SetFocus(); } void CClientDlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default if( DISCONNECT_TIMER == nIDEvent ) { KillTimer(nIDEvent); ShowMessageText("服务器已经关闭!"); OnDisconnect(); } else if( LOGINFAILED_TIMER == nIDEvent ) { KillTimer(nIDEvent); OnDisconnect(); } CDialog::OnTimer(nIDEvent); } /////////////////////////////////////////////////////////////////////////////// DWORD CClientDlg::GetConnectionID() { return m_dwConnectionID; } void CClientDlg::SetConnectionID(DWORD dwConnection) { m_dwConnectionID = dwConnection; } /////////////////////////////////////////////////////////////////////////////// void CClientDlg::ProcessLoginRequest() { WORD wMessageId = MSG_LOGIN_REQ; TLOGIN_STRU tLogonInfo = {0}; tLogonInfo.tCommonMsg.dwConnectionID = GetConnectionID(); tLogonInfo.tCommonMsg.wMessageId = wMessageId; CString strUserName = m_strUserName; strUserName.TrimLeft(); strUserName.TrimRight(); strcpy(tLogonInfo.tUserInfo.szUserName, strUserName); DWORD dwDataLen = sizeof(TLOGIN_STRU); TMessageHeader tHeader = {0}; tHeader.wMessageId = wMessageId; tHeader.dwDataLen = dwDataLen; unsigned long ulSendLen = m_tClientTunnel.net_Send(&tHeader, (void *)&tLogonInfo, dwDataLen); if( ulSendLen == SOCKET_ERROR ) { ShowMessageText("发送登录请求失败!"); } } void CClientDlg::ProcessLoginResponse(void *pLoginResult) { if( NULL == pLoginResult ) return; LOGIN_RESULT_STRU *ptLoginResult = (LOGIN_RESULT_STRU *)pLoginResult; DWORD dwConnectionID = ptLoginResult->tCommonMsg.dwConnectionID; SetConnectionID(dwConnectionID); BYTE byResult = ptLoginResult->byResult; if(LOGIN_RESULT_SUC == byResult) { CString strWindowText(""); strWindowText.Format("%s -- %s", WINDOW_TITLE, m_strUserName); SetWindowText(strWindowText); m_ctrlUserList.EnableWindow(TRUE); int nIndex = m_ctrlUserList.InsertString(0, " 所有人"); if( (LB_ERR != nIndex) && (LB_ERRSPACE != nIndex) ) { m_ctrlUserList.SetItemData(nIndex, INVALID_SOCKET); m_ctrlUserList.SetCurSel(nIndex); } } else { SetTimer(LOGINFAILED_TIMER, 0, NULL); } CString strCommentInfo(""); strCommentInfo.Format("%s. 用户代号: %ld", ((LOGIN_RESULT_SUC == byResult) ? "登录成功" : (LOGIN_RESULT_MULTI == byResult) ? "重复登录" : (LOGIN_RESULT_NAMERROR == byResult) ? "名字不存在" : (LOGIN_RESULT_PWERROR == byResult) ? "密码错误" : "登录失败"), dwConnectionID); ShowMessageText((CString)strCommentInfo); } void CClientDlg::ProcessUserListInfoResponse(void *pUserListInfo) { if( NULL == pUserListInfo ) return; TUSERLIST_INFO_STRU *ptUserListInfo = (TUSERLIST_INFO_STRU *)pUserListInfo; DWORD dwConnectionID = ptUserListInfo->dwConnectionID; if( INVALID_SOCKET == dwConnectionID ) return; if( dwConnectionID == GetConnectionID() ) return; /*The owner*/ BYTE byStatus = ptUserListInfo->byStatus; if( USER_STATUS_ONLINE == byStatus ) { CString strUserName = ptUserListInfo->szUserName; int nIndex = m_ctrlUserList.AddString(strUserName); if( (LB_ERR != nIndex) && (LB_ERRSPACE != nIndex) ) { m_ctrlUserList.SetItemData(nIndex, dwConnectionID); } } } void CClientDlg::ProcessLogoutResponse(void *pLogoutInfo) { TUSERLIST_INFO_STRU *ptUserListInfo = (TUSERLIST_INFO_STRU *)pLogoutInfo; DWORD dwConnectionID = ptUserListInfo->dwConnectionID; if( INVALID_SOCKET == dwConnectionID ) return; if( dwConnectionID == GetConnectionID() ) return; /*The owner*/ BYTE byStatus = ptUserListInfo->byStatus; if( USER_STATUS_OFFLINE == byStatus ) { int nCount = m_ctrlUserList.GetCount(); for(int nIndex = 0; nIndex < nCount; nIndex++) { DWORD dwItemData = m_ctrlUserList.GetItemData(nIndex); if( dwConnectionID == dwItemData ) { m_ctrlUserList.DeleteString(nIndex); break; } } } } void CClientDlg::ProcessChatMessageRequest(const char *szChatMessage) { const char *szDataBuf = szChatMessage; int nDataLen = strlen(szDataBuf) + 1; //characters should +1 DWORD dwFromUserID = GetConnectionID(); int nSelIndex = m_ctrlUserList.GetCurSel(); if( LB_ERR == nSelIndex ) { ShowMessageText("请在用户列表中选择一个目标用户!"); return; } DWORD dwToUserID = m_ctrlUserList.GetItemData(nSelIndex); WORD wMessageId = MSG_CHATMESSAGE_REQ; DWORD dwDataLen = sizeof(TCHAT_MESSAGE_STRU) + nDataLen; TCHAT_MESSAGE_STRU *pChatMessage = new TCHAT_MESSAGE_STRU[dwDataLen]; memset(pChatMessage, 0x00, dwDataLen); pChatMessage->tCommonMsg.dwConnectionID = GetConnectionID(); pChatMessage->tCommonMsg.wMessageId = wMessageId; pChatMessage->dwFromUserID = dwFromUserID; pChatMessage->dwToUserID = dwToUserID; strcpy(pChatMessage->szFromUserName, m_strUserName); pChatMessage->wMessageLen = nDataLen; memcpy(pChatMessage->byFileContent, szDataBuf, nDataLen); TMessageHeader tHeader = {0}; tHeader.wMessageId = wMessageId; tHeader.dwDataLen = dwDataLen; unsigned long ulSendLen = m_tClientTunnel.net_Send(&tHeader, (void *)pChatMessage, dwDataLen); if( ulSendLen != SOCKET_ERROR ) { CString strChatMessage = (CString)szChatMessage; if( CB_ERR == (m_cmbChatMessage.FindString(-1, strChatMessage)) ) { m_cmbChatMessage.InsertString(0, strChatMessage); } m_strChatMessage.Empty(); UpdateData(FALSE); } else { ShowMessageText("发送信息失败!"); } delete [] pChatMessage; pChatMessage = NULL; } void CClientDlg::ProcessChatMessageResponse(void *pResponse) { if( NULL == pResponse ) return; TCHAT_MESSAGE_STRU *pChatMessage = (TCHAT_MESSAGE_STRU *)pResponse; int nMessageLen = pChatMessage->wMessageLen; if( nMessageLen > 0 ) { char *szChatMessage = new char[nMessageLen]; memset(szChatMessage, 0x00, nMessageLen); memcpy(szChatMessage, pChatMessage->byFileContent, nMessageLen); DWORD dwConnectionID = pChatMessage->tCommonMsg.dwConnectionID; CString strChatMessageInfo(""); strChatMessageInfo.Format("[%s] 说道: %s", pChatMessage->szFromUserName, szChatMessage); ShowMessageText(strChatMessageInfo); delete [] szChatMessage; szChatMessage = NULL; } }