📄 prichatdlg.cpp
字号:
// PriChatDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Chat.h"
#include "PriChatDlg.h"
#include "ChatDlg.h"
#include "FileInfo.h"
#include <afxsock.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CPriChatDlg dialog
UINT FileRecvProc(LPVOID lParam);
//私聊对话框构造函数
CPriChatDlg::CPriChatDlg(CString m_host_IP,CString m_host_name,CWnd* pParent /*=NULL*/)
: CDialog(CPriChatDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CPriChatDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
this->m_host_IP=m_host_IP; //保存与此私聊对话框对应的用户主机名
this->m_host_name=m_host_name; //保存与此私聊对话框对应的用户IP
this->m_ptrDlg=(CChatDlg*)pParent; //保存主对话框的指针
}
void CPriChatDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CPriChatDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CPriChatDlg, CDialog)
//{{AFX_MSG_MAP(CPriChatDlg)
ON_BN_CLICKED(IDC_BTN_SEND, OnSend)
ON_BN_CLICKED(IDC_BTN_FILE_SEND, OnBtnFileSend)
ON_BN_CLICKED(IDC_BTN_FILE_RECV, OnBtnFileRecv)
ON_BN_CLICKED(IDC_BTN_FILE_REFUSE, OnBtnFileRefuse)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPriChatDlg message handlers
//发送私聊信息函数(私聊对话框发送按钮消息响应函数)
void CPriChatDlg::OnSend()
{
// TODO: Add your control notification handler code here
SOCKADDR_IN priChatSock; //定义地址结构体
WSABUF wsabuf; //定义数据发送缓冲
DWORD dwSend; //实际发送字节数
int len;
CString str,strTemp;
GetDlgItemText(IDC_EDIT_SEND,str);
if(""==str)
{
MessageBox("不能发送空消息!");
return;
}
SetDlgItemText(IDC_EDIT_SEND,"");
//GetDlgItemText(IDC_EDIT_RECV,strTemp);
//显示你自己发送的信息
strTemp=m_ptrDlg->m_ownHost+":\r\n"+str+"\r\n\r\n";
//SetDlgItemText(IDC_EDIT_RECV,strTemp);
SetRecvText(&strTemp);
priChatSock.sin_family=AF_INET;
//priChatSock.sin_addr.s_addr=m_addr.sin_addr.S_un.S_addr;
priChatSock.sin_addr.s_addr=inet_addr(m_host_IP);
//目的地址为与此对话框相应的用户IP地址(正在与谁聊天则为谁的IP地址)
priChatSock.sin_port=htons(55176); //私聊端口
//设定数据发送缓冲
len=str.GetLength();
wsabuf.buf=str.GetBuffer(len);
wsabuf.len=len+1;
//sendto(m_bSocket,smsg,256,0,(sockaddr*)&broadSock,sizeof(SOCKADDR));
WSASendTo(m_ptrDlg->m_priSocket,&wsabuf,1,&dwSend,0,(SOCKADDR*)&priChatSock,sizeof(SOCKADDR),NULL,NULL);
//发送私聊数据
}
//将数据显示到接收编辑框的函数
void CPriChatDlg::SetRecvText(CString *pStr)
{
CString str;
GetDlgItemText(IDC_EDIT_RECV,str); //取得编辑框文本
str+=*pStr; //加上新文本
SetDlgItemText(IDC_EDIT_RECV,str); //显示文本
//使编辑框得滚动条自动滚动到最下面
int nLen=((CEdit*)GetDlgItem(IDC_EDIT_RECV))->SendMessage(WM_GETTEXTLENGTH);
((CEdit*)GetDlgItem(IDC_EDIT_RECV))->SetSel(nLen,nLen,FALSE);
}
//“传输文件”按钮的消息响应函数
void CPriChatDlg::OnBtnFileSend()
{
// TODO: Add your control notification handler code here
CFileDialog FileDlg(TRUE); //建立打开文件对话框,让用户选择要发送的文件
if(FileDlg.DoModal()!=IDOK)
return;
//CFile myFile;
m_pathName=FileDlg.GetPathName(); //获取文件完整路径
if(!m_myFile.Open(FileDlg.GetPathName(), CFile::modeRead | CFile::typeBinary))
{
AfxMessageBox("文件不存在!",MB_OK|MB_ICONERROR);
return;
}
CString strTemp,m_fileTitle=FileDlg.GetFileName(); //保存文件名
SOCKADDR_IN fileCtrlSendSock; //定义地址结构体
WSABUF wsabuf; //定义数据发送缓冲
DWORD dwSend; //实际发送字节数
int len;
fileCtrlSendSock.sin_family=AF_INET;
//priChatSock.sin_addr.s_addr=m_addr.sin_addr.S_un.S_addr;
fileCtrlSendSock.sin_addr.s_addr=inet_addr(m_host_IP);
//目的地址为与此对话框相应的用户IP地址(正在与谁聊天则为谁的IP地址)
fileCtrlSendSock.sin_port=htons(55178); //文件传输控制命令端口
//设定数据发送缓冲,为将要发送文件名
len=m_fileTitle.GetLength();
wsabuf.buf=m_fileTitle.GetBuffer(len);
wsabuf.len=len+1;
WSASendTo(m_ptrDlg->m_fileSocket,&wsabuf,1,&dwSend,0,(SOCKADDR*)&fileCtrlSendSock,sizeof(SOCKADDR),NULL,NULL);
//发送文件传输控制命令,请求对方接收文件
//显示相关信息
//GetDlgItemText(IDC_EDIT_RECV,strTemp);
strTemp="你向"+m_host_name+"发送此文件:"+m_fileTitle+"\r\n\r\n";
//SetDlgItemText(IDC_EDIT_RECV,strTemp);
SetRecvText(&strTemp);
FileButtonCtrl(0x00);
//Disable“传输文件”、“接收文件”、“拒绝接收”和“退出”按钮
}
//控制“传输文件”按钮,“接收文件”和“拒绝接收”按钮的Enable和Disable
void CPriChatDlg::FileButtonCtrl(short ch)
{
switch(ch)
{
case 0x60:
((CButton*)GetDlgItem(IDC_BTN_FILE_SEND))->EnableWindow(FALSE);
((CButton*)GetDlgItem(IDC_BTN_FILE_RECV))->EnableWindow(TRUE);
((CButton*)GetDlgItem(IDC_BTN_FILE_REFUSE))->EnableWindow(TRUE);
((CButton*)GetDlgItem(IDCANCEL))->EnableWindow(FALSE);
break;
case 0x90:
((CButton*)GetDlgItem(IDC_BTN_FILE_SEND))->EnableWindow(TRUE);
((CButton*)GetDlgItem(IDC_BTN_FILE_RECV))->EnableWindow(FALSE);
((CButton*)GetDlgItem(IDC_BTN_FILE_REFUSE))->EnableWindow(FALSE);
((CButton*)GetDlgItem(IDCANCEL))->EnableWindow(TRUE);
break;
case 0x00:
((CButton*)GetDlgItem(IDC_BTN_FILE_SEND))->EnableWindow(FALSE);
((CButton*)GetDlgItem(IDC_BTN_FILE_RECV))->EnableWindow(FALSE);
((CButton*)GetDlgItem(IDC_BTN_FILE_REFUSE))->EnableWindow(FALSE);
((CButton*)GetDlgItem(IDCANCEL))->EnableWindow(FALSE);
break;
}
}
//“接收文件”按钮的消息响应函数
void CPriChatDlg::OnBtnFileRecv()
{
// TODO: Add your control notification handler code here
CFileDialog Dlg(FALSE,NULL,m_fileTitle,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,NULL,this);
//建立另存为对话框,让用户选择保存路径和文件名
if(Dlg.DoModal()!=IDOK)
return;
m_savePathName=Dlg.GetPathName();
/*FileButtonCtrl(0x00);
CString strTemp;
GetDlgItemText(IDC_EDIT_RECV,strTemp);
strTemp+="文件传送中,请稍候。\r\n\r\n";
SetDlgItemText(IDC_EDIT_RECV,strTemp);*/
SOCKADDR_IN fileCtrlSendSock; //定义地址结构体
WSABUF wsabuf; //定义数据发送缓冲
DWORD dwSend; //实际发送字节数
int len;
fileCtrlSendSock.sin_family=AF_INET;
//priChatSock.sin_addr.s_addr=m_addr.sin_addr.S_un.S_addr;
fileCtrlSendSock.sin_addr.s_addr=inet_addr(m_host_IP);
//目的地址为与此对话框相应的用户IP地址(正在与谁聊天则为谁的IP地址)
fileCtrlSendSock.sin_port=htons(55178); //文件传输控制命令端口
//设定数据发送缓冲,为“go”信息
CString str="go";
len=str.GetLength();
wsabuf.buf=str.GetBuffer(len);
wsabuf.len=len+1;
WSASendTo(m_ptrDlg->m_fileSocket,&wsabuf,1,&dwSend,0,(SOCKADDR*)&fileCtrlSendSock,sizeof(SOCKADDR),NULL,NULL);
//发送文件传输控制命令,同意接收文件
AfxBeginThread(FileRecvProc,this); //启动文件接收线程
/*注释部分为单线程模式
Sleep(1000);
//AfxSocketInit(NULL);
CSocket sockClient;
sockClient.Create();
//CString szIP;
//GetDlgItemText(IDC_EDIT_IPADDRESS,szIP);
if(!sockClient.Connect(m_host_IP, 800))
{
AfxMessageBox("连接到对方机器失败!");
return;
}
SOCKET_STREAM_FILE_INFO StreamFileInfo;
sockClient.Receive(&StreamFileInfo,sizeof(SOCKET_STREAM_FILE_INFO));
CFile destFile(Dlg.GetPathName(), CFile::modeCreate | CFile::modeWrite | CFile::typeBinary);
UINT dwRead = 0;
while(dwRead<StreamFileInfo.nFileSizeLow)
{
byte* data = new byte[1024];
memset(data,0,1024);
UINT dw=sockClient.Receive(data, 1024);
destFile.Write(data, dw);
dwRead+=dw;
}
SetFileTime((HANDLE)destFile.m_hFile,&StreamFileInfo.ftCreationTime,
&StreamFileInfo.ftLastAccessTime,&StreamFileInfo.ftLastWriteTime);
destFile.Close();
SetFileAttributes(StreamFileInfo.szFileTitle,StreamFileInfo.dwFileAttributes);
sockClient.Close();
GetDlgItemText(IDC_EDIT_RECV,strTemp);
strTemp+="文件接收完毕!\r\n\r\n";
SetDlgItemText(IDC_EDIT_RECV,strTemp);
AfxMessageBox("接收完毕!");
FileButtonCtrl(0x90);*/
}
//“拒绝接收”按钮的消息响应函数
void CPriChatDlg::OnBtnFileRefuse()
{
// TODO: Add your control notification handler code here
SOCKADDR_IN fileCtrlSendSock; //定义地址结构体
WSABUF wsabuf; //定义数据发送缓冲
DWORD dwSend; //实际发送字节数
int len;
fileCtrlSendSock.sin_family=AF_INET;
//priChatSock.sin_addr.s_addr=m_addr.sin_addr.S_un.S_addr;
fileCtrlSendSock.sin_addr.s_addr=inet_addr(m_host_IP);
//目的地址为与此对话框相应的用户IP地址(正在与谁聊天则为谁的IP地址)
fileCtrlSendSock.sin_port=htons(55178); //文件传输控制命令端口
//设定数据发送缓冲,为“stop”
CString str="stop";
len=str.GetLength();
wsabuf.buf=str.GetBuffer(len);
wsabuf.len=len+1;
WSASendTo(m_ptrDlg->m_fileSocket,&wsabuf,1,&dwSend,0,(SOCKADDR*)&fileCtrlSendSock,sizeof(SOCKADDR),NULL,NULL);
//发送文件传输控制命令,拒绝接收文件
//显示相关信息
str="你拒绝接收该文件\r\n\r\n";
SetRecvText(&str);
FileButtonCtrl(0x90);
//Enable“传输文件”和“退出”按钮,Disable“接收文件”和“拒绝接收”按钮
}
//文件接收线程函数
UINT FileRecvProc(LPVOID lParam)
{
CPriChatDlg *ptrPriChatDlg=(CPriChatDlg *)lParam;
//取出收到的信息(指向保存接收方信息的CChatUser实例的指针)
//显示相关信息
CString strTemp;
strTemp="文件接收中,请稍候。\r\n\r\n";
ptrPriChatDlg->SetRecvText(&strTemp);
ptrPriChatDlg->FileButtonCtrl(0x00);
CSocket sockClient; //建立异步套接字
sockClient.Create();
if(!sockClient.Connect(ptrPriChatDlg->m_host_IP, 55180)) //与发送方连接
{
AfxMessageBox("连接到对方机器失败!");
return -1;
}
SOCKET_STREAM_FILE_INFO StreamFileInfo; //定义描述文件信息结构体
sockClient.Receive(&StreamFileInfo,sizeof(SOCKET_STREAM_FILE_INFO));//接收文件信息
CFile destFile(ptrPriChatDlg->m_savePathName, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary);
//定义文件类,指明保存路径和操作方式
DWORD dwReadlo=0; //已发送大小的低双字
DWORD dwReadhi=0; //已发送大小的高双字
DWORD present=0; //已发送百分比
unsigned __int64 temp1=(StreamFileInfo.nFileSizeHigh*2^32+StreamFileInfo.nFileSizeLow)/100;
//文件大小的1/100
unsigned __int64 temp2;
//接收文件
while(dwReadhi<=StreamFileInfo.nFileSizeHigh)
{
while(dwReadlo<StreamFileInfo.nFileSizeLow)
{
byte* data = new byte[1024];
memset(data,0,1024);
UINT dw=sockClient.Receive(data, 1024); //接收1KB
destFile.Write(data, dw); //保存
free(data); //释放内存
//ptrPriChatDlg->SetProgress(dwReadhi,dwReadlo,StreamFileInfo.nFileSizeHigh,StreamFileInfo.nFileSizeLow);
dwReadlo+=dw;
//更新文件接收进度
if(0==StreamFileInfo.nFileSizeHigh) //如果文件小于4GB
{
if(dwReadlo>=present*temp1) //如果多传了1%
{
strTemp.Format("%d",present);
ptrPriChatDlg->SetProgress(&strTemp,TRUE); //更新进度
present++;
}
}
else //如果文件大于4GB
{
temp2=dwReadhi*2^32+dwReadlo; //已接收文件大小
if(temp2>=present*temp1) //如果多传了1%
{
strTemp.Format("%d",present);
ptrPriChatDlg->SetProgress(&strTemp,TRUE); //更新进度
present++;
}
}
}
dwReadlo=0;
dwReadhi++;
}
strTemp.Format("%d",100); //接收完毕,将进度置为100%
ptrPriChatDlg->SetProgress(&strTemp,TRUE);//更新进度
SetFileTime((HANDLE)destFile.m_hFile,&StreamFileInfo.ftCreationTime,
&StreamFileInfo.ftLastAccessTime,&StreamFileInfo.ftLastWriteTime);
//设置文件时间
destFile.Close(); //关闭文件
SetFileAttributes(StreamFileInfo.szFileTitle,StreamFileInfo.dwFileAttributes);
//设置文件属性
sockClient.Close(); //关闭套接字
//显示提示信息
strTemp="文件接收完毕!\r\n\r\n";
ptrPriChatDlg->SetRecvText(&strTemp);
//AfxMessageBox("接收完毕!");
ptrPriChatDlg->FileButtonCtrl(0x90);
//Enable“传输文件”和“退出”按钮,Disable“接收文件”和“拒绝接收”按钮
ptrPriChatDlg->SetProgress(&strTemp,FALSE); //清除文件进度显示
return 0;
}
//显示文件传输进度函数
void CPriChatDlg::SetProgress(CString *str,BOOL b)
{
if(b)
{
*str="已传送"+(*str)+"%";
SetDlgItemText(IDC_PROGRESS,*str);
}
else
SetDlgItemText(IDC_PROGRESS,"");
}
//关闭对话框(提供外部程序关闭对话框的方法)
void CPriChatDlg::CloseDlg()
{
OnCancel();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -