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

📄 chatdlg.cpp

📁 网络聊天工具原代码 VC源码(网络编程
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ChatDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Chat.h"
#include "ChatDlg.h"
#include "ProxyAuthDlg.h"
#include "CallDlg.h"
#include "OptionDlg.h"

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

#define ID_TIMER_SENDPROXY WM_USER+2000
#define ID_TIMER_CHAT	   WM_USER+2001

/////////////////////////////////////////////////////////////////////////////
// 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()

/////////////////////////////////////////////////////////////////////////////
// CChatDlg dialog

CChatDlg::CChatDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CChatDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CChatDlg)
	m_szChatSend = _T("");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_bType = IAM_NULL;
	m_pClientThread = NULL;
	m_pServerThread = NULL;
	m_lpReceiveBuffer = NULL;
	m_lpSendBuffer = NULL;
	m_bState = MY_ORIGIN;
	m_bHaveGotName = FALSE;

}

void CChatDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CChatDlg)
	DDX_Control(pDX, IDC_CHAT_LIST, m_ctrlChat);
	DDX_Text(pDX, IDC_CHAT, m_szChatSend);
	DDV_MaxChars(pDX, m_szChatSend, 160);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CChatDlg, CDialog)
	//{{AFX_MSG_MAP(CChatDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_COMMAND(ID_FILE_EXIT, OnFileExit)
	ON_COMMAND(ID_FILE_OPTION, OnFileOption)
	ON_COMMAND(ID_FILE_SAVE, OnFileSave)
	ON_BN_CLICKED(IDC_CONNECT, OnConnect)
	ON_BN_CLICKED(IDC_SEND, OnSend)
	ON_BN_CLICKED(IDC_DISCONNECT, OnDisconnect)
	ON_WM_TIMER()
	ON_MESSAGE( SOCKET_THREAD_ACCEPT, OnClientAccept )
	ON_MESSAGE( WM_THREAD_QUIT, OnThreadQuit )
	ON_MESSAGE( WM_THREAD_DATA, OnThreadData )
	ON_MESSAGE( SOCKET_THREAD_WRITE, OnThreadWrite )
	ON_MESSAGE( SOCKET_THREAD_TRANSFER, OnTransfer )
	ON_COMMAND(ID_FILE_ABOUT, OnFileAbout)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CChatDlg message handlers

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

	m_lpReceiveBuffer = (LPBYTE)GlobalAlloc( GPTR, MAX_PACKET_SIZE*4 );
	if( !m_lpReceiveBuffer )
	{
		MessageBox( "资源不足,不能分配存储空间。","错误", MB_OK|MB_ICONSTOP);
	}
	else
	{
		m_lpSendBuffer = (LPBYTE)GlobalAlloc( GPTR, MAX_PACKET_SIZE+1 );
		if( !m_lpSendBuffer )
		{
			MessageBox( "资源不足,不能分配存储空间。","错误", MB_OK|MB_ICONSTOP);
		}
	}


	InitProfile();

	// 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
	if( confChat.szLocalIP == _T("127.0.0.1") )GetLocalIP();

	//启动服务器
	ASSERT( m_pServerThread == NULL );
	m_pServerThread = new CServerThread( GetSafeHwnd(), confChat.nServicePort );
	if( m_pServerThread == NULL )
	{
		MessageBox("无法创建服务线程,请释放资源。", "错误", MB_OK|MB_ICONSTOP );
		return TRUE;
	}
	m_pServerThread->CreateThread();

	GetDlgItem(IDC_DISCONNECT)->EnableWindow( FALSE );
	GetDlgItem(IDC_CHAT )->EnableWindow(FALSE );
	GetDlgItem(IDC_SEND )->EnableWindow(FALSE );

	SetDefID( IDC_SEND );
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CChatDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else if( nID == SC_CLOSE)
	{
			OnFileExit();
	}
	else if( nID != SC_MAXIMIZE  )
	{
		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 CChatDlg::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 CChatDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CChatDlg::OnFileExit() 
{
	// TODO: Add your command handler code here
	int nResult;

	if( m_bType == IAM_CLIENT )
	{
		nResult =  MessageBox("您已经和对方连接好,确认退出吗?", "提问", MB_OKCANCEL|MB_ICONQUESTION );
		if( nResult != IDOK ) return;
	}
	else if( m_bType == IAM_SERVER )
	{
		nResult =  MessageBox("已经有人和您连接好,确认退出吗?", "提问", MB_OKCANCEL|MB_ICONQUESTION );
		if( nResult != IDOK ) return;
	}

	//如果仍然线程在活着
	if( m_bType != IAM_NULL )
		OnDisconnect();

	if( m_pServerThread != NULL )
	{
		m_pServerThread->KillThread();
		m_pServerThread = NULL;
	}

	WriteProfile();

	if( !m_lpReceiveBuffer ) GlobalFree( m_lpReceiveBuffer );
	if( !m_lpSendBuffer ) GlobalFree( m_lpSendBuffer );



	DestroyWindow();		
}

void CChatDlg::OnFileOption() 
{
	// TODO: Add your command handler code here
	COptionDlg *pDlg = new COptionDlg;
	if( pDlg )
	{
		//设置这些个参数
		pDlg->m_bUseProxy = confChat.bUseProxy;
		pDlg->m_nProxyPort = confChat.nProxyPort;
		pDlg->m_nProxyType = confChat.nProxyType;

		if( confChat.nWaitTime < 30 ) confChat.nWaitTime = 30;
		else if( confChat.nWaitTime >90 ) confChat.nWaitTime = 90;
		pDlg->m_nWaitTime = (int)((confChat.nWaitTime-30)/30);

		pDlg->m_szIP = confChat.szLocalIP;
		pDlg->m_szProxy = confChat.szProxyIP;
		pDlg->m_nServicePort = confChat.nServicePort;
		pDlg->m_szName = confChat.szUserName;

		if( pDlg->DoModal() == IDOK )
		{

			confChat.bUseProxy = pDlg->m_bUseProxy;
			confChat.nProxyPort = pDlg->m_nProxyPort;
			confChat.nProxyType = pDlg->m_nProxyType;
			confChat.nWaitTime = (pDlg->m_nWaitTime+1)*30;

			confChat.szLocalIP = pDlg->m_szIP;
			confChat.szProxyIP = pDlg->m_szProxy;
			confChat.nServicePort = pDlg->m_nServicePort;
			if( pDlg->m_szName.GetLength() == 0 ) pDlg->m_szName = _T("UNKNOWN");
			if( confChat.szUserName != pDlg->m_szName )
			{
				confChat.szUserName = pDlg->m_szName;
				if( m_bType != IAM_NULL )
				{
					SendCommand( CHAT_ACT_SEND_NAME );
				}
				m_ctrlChat.SetMyName( pDlg->m_szName );
			}
			else confChat.szUserName = pDlg->m_szName;
		}

		delete pDlg;
	}
}

void CChatDlg::OnFileSave() 
{
	// TODO: Add your command handler code here
	int nResult;
	CString szFileName;
	char pTemp[_MAX_PATH+1];
	FILE *fp;

	if( m_ctrlChat.GetBytes() == 0 ) 
	{
		MessageBox("没有内容,不能保存。", "错误", MB_OK|MB_ICONSTOP );
		return;
	}

	if( m_ctrlChat.GetBuffer() == NULL )
	{
		MessageBox("没有内容,不能保存。", "错误", MB_OK|MB_ICONSTOP );
		return;
	}

	GetCurrentDirectory( _MAX_PATH, pTemp );

	//选择保存路径
	CFileDialog *pDlg = new CFileDialog(FALSE, "txt",  NULL, 
									OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
									"聊天内容 (*.txt)|*.txt|", this );

	pDlg->m_ofn.lpstrInitialDir = pTemp;

	if( pDlg )
	{
		nResult = pDlg->DoModal();
		szFileName = pDlg->GetPathName();
		delete pDlg;
		if( nResult == IDOK )
		{
			fp = fopen( (LPCTSTR)szFileName, "wt");
			if( fp )
			{
				//写入数据
				fwrite( m_ctrlChat.GetBuffer(), m_ctrlChat.GetBytes(), 1, fp );
				fprintf(fp, "\n" );
				fclose(fp);
			}
		}
	}
}

void CChatDlg::InitProfile()
{
	CWinApp *pTheApp = AfxGetApp();

	//网络部分
	confChat.bUseProxy	= pTheApp->GetProfileInt( "Network", "UseProxy", FALSE );
	confChat.nProxyType	= pTheApp->GetProfileInt( "Network", "ProxyType", HTTP_PROXY );
	confChat.szProxyIP	= pTheApp->GetProfileString( "Network", "ProxyIP", "127.0.0.1" );
	confChat.nProxyPort	= pTheApp->GetProfileInt( "Network", "ProxyPort", 8080 );
	confChat.bProxyUsable	= PROXY_AUTH_UNSET;
	confChat.szProxyPass	= _T("UNKNOWN");
	confChat.szProxyUser	= _T("");

	//Server
	confChat.nServicePort	= pTheApp->GetProfileInt( "Server", "ServicePort", CHAT_PORT );
	confChat.szLocalIP	= pTheApp->GetProfileString( "Server", "LocalIP", "127.0.0.1" );

	//Client
	confChat.nWaitTime	= pTheApp->GetProfileInt( "Client", "WaitTime", 30 );
	confChat.szLastCallHost = pTheApp->GetProfileString( "Client", "LastCallHost", "");
	confChat.nLastCallPort = pTheApp->GetProfileInt( "Client", "LastCallPort", CHAT_PORT);
	

	//information
	confChat.szUserName	 = pTheApp->GetProfileString( "Information", "UserName", "Annoymous" );

	confChat.bWinsockReady = FALSE;

}

void CChatDlg::WriteProfile()
{
	CWinApp *pTheApp = AfxGetApp();

	UpdateData();

	//网络部分
	pTheApp->WriteProfileInt( "Network", "UseProxy",	confChat.bUseProxy );
	pTheApp->WriteProfileInt( "Network", "ProxyType",	confChat.nProxyType );
	pTheApp->WriteProfileString( "Network", "ProxyIP",	confChat.szProxyIP );
	pTheApp->WriteProfileInt( "Network", "ProxyPort",	confChat.nProxyPort );


	//Server
	pTheApp->WriteProfileInt( "Server", "ServicePort",	confChat.nServicePort );
	pTheApp->WriteProfileString( "Server", "LocalIP",	confChat.szLocalIP );

	//Client
	pTheApp->WriteProfileInt( "Client", "WaitTime",		confChat.nWaitTime );
	pTheApp->WriteProfileString( "Client", "LastCallHost",		confChat.szLastCallHost );
	pTheApp->WriteProfileInt( "Client", "LastCallPort",		confChat.nLastCallPort );

	//information
	pTheApp->WriteProfileString( "Information", "UserName", confChat.szUserName );
}

void CChatDlg::GetLocalIP()
{
	char buf[108];
	struct hostent *ip;
	if( confChat.bWinsockReady == TRUE )
	{
		if( gethostname( buf, 108 ) != 0 ) return;
		ip = gethostbyname( buf );
		if( ip != NULL )
		{
			confChat.szLocalIP.Format("%s", inet_ntoa(  *(LPIN_ADDR)(ip->h_addr_list[0]) ) );
		}
	}
}

void CChatDlg::OnOK() 
{
	// TODO: Add extra validation here
	OnFileExit();
}

void CChatDlg::OnCancel()
{

}


void CChatDlg::OnConnect() 
{
	// TODO: Add your control notification handler code here
		HWND hWnd;
	int nResult;

	if( m_bType == IAM_NULL )
	{

		hWnd = GetSafeHwnd();

		if( m_pClientThread != NULL )  
		{

			return;
		}

		CCallDlg *pDlg = new CCallDlg;
		if( pDlg )
		{
			pDlg->m_bUseProxy = confChat.bUseProxy;
			pDlg->m_nPort = confChat.nLastCallPort;;
			pDlg->m_szServer = confChat.szLastCallHost;
			nResult = pDlg->DoModal();
			if( nResult == IDOK )
			{
				//已经连接好了
				ASSERT( pDlg->m_pClientThread != NULL );
		
				GetDlgItem( IDC_CHAT_LIST )->SetWindowText(_T("") );
				GetDlgItem( IDC_CONNECT)->SetWindowText("测试" );				
				GetDlgItem(IDC_DISCONNECT)->EnableWindow( TRUE );
				

				confChat.nLastCallPort = pDlg->m_nPort;
				confChat.szLastCallHost = pDlg->m_szServer;

				m_pClientThread = pDlg->m_pClientThread;	
				

				m_bState = MY_CONNECTED;			
				m_bType = IAM_CLIENT;
				m_bCanWrite = TRUE;
				m_bHaveGotName = FALSE;

				if( pDlg->m_bUseProxy ) SetTimer( ID_TIMER_SENDPROXY, 30000, NULL);
				SendCommand( CHAT_ACT_SEND_NAME );

			}
			delete pDlg;
		}
		return;
	} // IAM_NULL
	
	//测试网络
	SendCommand( CHAT_ACT_ASK_TEST );
	m_bState = MY_ASKING;
}

void CChatDlg::OnSend() 
{
	// TODO: Add your control notification handler code here
	int nLen;
	UpdateData();

	if( m_bType == IAM_NULL ) return;
	nLen = m_szChatSend.GetLength();
	if( nLen == 0 ) 
	{
		GetDlgItem( IDC_CHAT )->SetFocus();
		return;
	}

	SendCommand( CHAT_ACT_ASK_SEND );
	m_bState = MY_ASKING;	
	GetDlgItem( IDC_SEND )->EnableWindow(FALSE );
	m_ctrlChat.PostChat( (LPSTR)(LPCTSTR)m_szChatSend, TRUE );
	GetDlgItem( IDC_CHAT )->SetWindowText(_T("") );
	GetDlgItem( IDC_CHAT )->SetFocus();
}

void CChatDlg::OnDisconnect() 
{
	// TODO: Add your control notification handler code here
	if( m_bState == MY_ORIGIN ) return;
	SendCommand( CHAT_ACT_QUIT );
	if( m_pClientThread )
	{
		m_pClientThread->KillThread();
		m_pClientThread = NULL;
	}
	else 
	{
		if( m_pServerThread )
			::PostThreadMessage( m_pServerThread->m_nThreadID,
					SOCKET_THREAD_SHUT, 0, 0 );
	}

	GetDlgItem(IDC_DISCONNECT)->EnableWindow( FALSE );
	GetDlgItem(IDC_CHAT )->EnableWindow(FALSE );
	GetDlgItem(IDC_SEND )->EnableWindow(FALSE );	
	GetDlgItem(IDC_CONNECT)->SetWindowText("呼叫");
	GetDlgItem(IDC_FROMIP )->SetWindowText( _T("") );
	GetDlgItem(IDC_YOUNAME)->SetWindowText( _T("") );
	GetDlgItem(IDC_TIME)->SetWindowText( _T("") );

	m_bState = MY_ORIGIN;
	m_bType = IAM_NULL;
	m_bHaveGotName = FALSE;

	KillTimer( ID_TIMER_SENDPROXY );
	KillTimer( ID_TIMER_CHAT );
}

void CChatDlg::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	if( nIDEvent == ID_TIMER_SENDPROXY )
	{
		if( m_bType == IAM_CLIENT )SendCommand( CHAT_ACT_NULL );
		else KillTimer( ID_TIMER_SENDPROXY );
	}
	else if( nIDEvent == ID_TIMER_CHAT )
	{
		if( m_bType == IAM_NULL ) 
			KillTimer( ID_TIMER_CHAT );
		//更新时间
		CTime cCurTime = CTime::GetCurrentTime();

⌨️ 快捷键说明

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