chatdlg.cpp
来自「仿造QQ聊天界面 超级相向 第一次作品 不足之处见谅」· C++ 代码 · 共 1,568 行 · 第 1/3 页
CPP
1,568 行
GetDlgItem(IDC_VSTATIC5)->ShowWindow(false);
}
else
{
SetWindowPos(NULL,0,0,m_small.Width(),m_small.Height(),
SWP_NOMOVE | SWP_NOZORDER);
SetDlgItemText(IDC_KEEP," 聊天记录>>");
m_keep1="";
UpdateData(FALSE);
GetDlgItem(IDC_GIFGIRL)->ShowWindow(true);
GetDlgItem(IDC_GIFBOY)->ShowWindow(true);
GetDlgItem(IDC_VSTATIC1)->ShowWindow(true);
GetDlgItem(IDC_VSTATIC2)->ShowWindow(true);
GetDlgItem(IDC_VSTATIC3)->ShowWindow(true);
GetDlgItem(IDC_VSTATIC4)->ShowWindow(true);
GetDlgItem(IDC_VSTATIC5)->ShowWindow(true);
}
GetDlgItem(IDC_RECORD)->SendMessage(WM_VSCROLL, MAKEWPARAM(SB_BOTTOM,0),0);
GetDlgItem(IDC_EDIT_RECV)->SendMessage(WM_VSCROLL, MAKEWPARAM(SB_BOTTOM,0),0);
}
void CChatDlg::OnShowWindow(BOOL bShow, UINT nStatus) //初始不显示聊天记录框
{
CDialog::OnShowWindow(bShow, nStatus);
// TODO: Add your message handler code here
//m_Progress.SendMessage(PBM_SETBKCOLOR, 0, RGB(255, 0, 0));//背景色
m_Progress.SendMessage(PBM_SETBARCOLOR, 0, RGB(47, 255, 99));//前景色
CString strpath;
static CRect rectLarge;
static CRect rectSmall;
if(rectLarge.IsRectNull())
{
CRect rectSeparator;
GetWindowRect(&rectLarge);
GetDlgItem(IDC_SEPARATOR)->GetWindowRect(&rectSeparator);
rectSmall.left=rectLarge.left;
rectSmall.top=rectLarge.top;
rectSmall.right=rectSeparator.right;
rectSmall.bottom=rectLarge.bottom;
m_small=rectSmall;
m_large=rectLarge;
}
GetDlgItemText(IDC_KEEP,strpath);
if(strpath==" 聊天记录>>")
{
SetWindowPos(NULL,0,0,rectSmall.Width(),rectSmall.Height(),
SWP_NOMOVE | SWP_NOZORDER);
}
else
{
SetWindowPos(NULL,0,0,rectLarge.Width(),rectLarge.Height(),
SWP_NOMOVE | SWP_NOZORDER);
}
m_connect.SetColor(CButtonST::BTNST_COLOR_BK_OUT, RGB(46, 199, 233));
m_voice.SetColor(CButtonST::BTNST_COLOR_BK_OUT, RGB(46, 199, 233));
m_send.SetColor(CButtonST::BTNST_COLOR_BK_OUT, RGB(46, 199, 233));
m_capture.SetColor(CButtonST::BTNST_COLOR_BK_OUT, RGB(46, 199, 233));
m_disconnect.SetColor(CButtonST::BTNST_COLOR_BK_OUT, RGB(46, 199, 233));
m_color.SetColor(CButtonST::BTNST_COLOR_BK_OUT, RGB(46, 199, 233));
m_fontcol.SetColor(CButtonST::BTNST_COLOR_BK_OUT, RGB(46, 199, 233));
m_keepcol.SetColor(CButtonST::BTNST_COLOR_BK_OUT, RGB(46, 199, 233));
m_mycapture.SetColor(CButtonST::BTNST_COLOR_BK_OUT, RGB(46, 199, 233));
m_sendfile.SetColor(CButtonST::BTNST_COLOR_BK_OUT, RGB(46, 199, 233));
m_stopfilesend.SetColor(CButtonST::BTNST_COLOR_BK_OUT, RGB(46, 199, 233));
m_cancle.SetColor(CButtonST::BTNST_COLOR_BK_OUT, RGB(46, 199, 233));
m_ok.SetColor(CButtonST::BTNST_COLOR_BK_OUT, RGB(46, 199, 233));
m_bkcolor.SetColor(CButtonST::BTNST_COLOR_BK_OUT, RGB(46, 199, 233));
((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP);
addrTo.sin_family=AF_INET;
addrTo.sin_port=htons(6060);
addrTo.sin_addr.S_un.S_addr=htonl(dwIP);
str2=inet_ntoa(addrTo.sin_addr);
GotoDlgCtrl(GetDlgItem(IDC_EDIT_SEND));
}
CString CChatDlg::GetError(DWORD error) //返回错误信息
{
CString strError;
switch(error)
{
case WSANOTINITIALISED:
strError="初始化错误";
break;
case WSAENOTCONN:
strError="对方没有启动";
break;
case WSAEWOULDBLOCK :
strError="对方已经关闭";
break;
case WSAECONNREFUSED:
strError="连接的尝试被拒绝";
break;
case WSAENOTSOCK:
strError="在一个非套接字上尝试了一个操作";
break;
case WSAEADDRINUSE:
strError="特定的地址已在使用中";
break;
case WSAECONNRESET:
strError="与主机的连接被关闭";
break;
default:
strError="一般错误";
}
return strError;
}
int CChatDlg::GetLocalHostName(CString &sHostName) //获得本地计算机名称
{
char szHostName[256];
int nRetCode;
nRetCode=gethostname(szHostName,sizeof(szHostName));
if(nRetCode!=0)
{
//产生错误
sHostName=_T("没有取得");
return GetLastError();
}
sHostName=szHostName;
return 0;
}
int CChatDlg::GetIpAddress(const CString &sHostName, CString &sIpAddress)//获得本地IP
{
struct hostent FAR * lpHostEnt=gethostbyname(sHostName);
if(lpHostEnt==NULL)
{
//产生错误
sIpAddress=_T("");
return GetLastError();
}
//获取IP
LPSTR lpAddr=lpHostEnt->h_addr_list[0];
if(lpAddr)
{
struct in_addr inAddr;
memmove(&inAddr,lpAddr,4);
//转换为标准格式
sIpAddress=inet_ntoa(inAddr);
if(sIpAddress.IsEmpty())
sIpAddress=_T("没有取得");
}
return 0;
}
int CChatDlg::GetNamebyAddress(const CString &IpAddress,CString &sYouName)//获得对方计算机名称
{
static unsigned long addr;
addr=inet_addr(IpAddress);
struct hostent FAR * lpHostEnt=gethostbyaddr((char *)&addr,4,AF_INET);
if(lpHostEnt==NULL)
{
//产生错误
sYouName=_T("");
AfxMessageBox("连接不上");//应该取得其错误
return -1;
}
CString name=lpHostEnt->h_name;
sYouName=name;
return 0;
}
UINT _SendFileThread(LPVOID lparam)
{
CChatDlg *pDlg=(CChatDlg *)lparam;
if(pDlg->StopServer==true) return -1;
CSocket sockClient;
sockClient.Create();
CString ip;
pDlg->m_ip.GetWindowText(ip);
sockClient.Connect(ip, PORT+pDlg->m_client);
//首先发送标记F为文件,2
int end=0;
end=sockClient.Send("F",FLAG);
///////////////////////////////////////////////////////////////////发送标志是否成功
if(end==SOCKET_ERROR)
{
AfxMessageBox("_SendFileThread Send错误!"+pDlg->GetError(GetLastError()));
return -1;
}
else if(end!=2)
{
AfxMessageBox("文件头错误");
return -1;
}
///////////////////////////////////////////////////////////////////
CFile myFile;
FILEINFO myFileInfo;
if(!myFile.Open(pDlg->m_fileName, CFile::modeRead | CFile::typeBinary))
return -1;
myFileInfo.fileLength=myFile.GetLength(); //得到文件大小
strcpy(myFileInfo.fileName,myFile.GetFileName());//得到文件名称
sockClient.Send(&myFileInfo,sizeof(myFileInfo)); //发送文件信息
pDlg->m_Progress.SetRange32(0,myFileInfo.fileLength);
myFile.Seek(0,CFile::begin);
char m_buf[SIZEFILE]={0};
CString strError;
int num=0;
end=0;
int temp=0;
pDlg->GetDlgItem(IDC_STOP_FILESEND)->EnableWindow(true);
for(;;)
{
if(pDlg->FileWork==false)
{
pDlg->FileWork=true;
pDlg->GetDlgItem(IDCANCEL)->EnableWindow(false);
pDlg->GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(false);
}
num=myFile.Read(m_buf, SIZEFILE);
if(num==0) break;
end=sockClient.Send(m_buf, num);
temp+=end;
pDlg->m_Progress.SetPos(temp);
if(pDlg->FileStop==true)
{
pDlg->FileStop=false;
pDlg->FileWork=false;
break;
}
if(end==SOCKET_ERROR)
{
AfxMessageBox("_SendFileThread Send错误!"+pDlg->GetError(GetLastError()));
break;
}
}
pDlg->m_Progress.SetPos(0);
CString strLocalName;
pDlg->GetLocalHostName(strLocalName);
CString strLocalIP;
pDlg->GetIpAddress(strLocalName,strLocalIP);
if(temp==myFileInfo.fileLength)
{
AfxMessageBox("文件发送成功!");
}
else
{
AfxMessageBox("文件发送失败!");
}
myFile.Close();
sockClient.Close();
pDlg->FileWork=false;
pDlg->GetDlgItem(IDC_PROGRESS_SEND_FILE)->ShowWindow(SW_HIDE);
pDlg->GetDlgItem(IDC_VOICE)->ShowWindow(SW_SHOW);
pDlg->GetDlgItem(IDOK)->ShowWindow(SW_SHOW);
pDlg->GetDlgItem(IDC_STOP_FILESEND)->EnableWindow(false);
pDlg->GetDlgItem(IDCANCEL)->EnableWindow(true);
pDlg->GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(true);
return 0;
}
void CChatDlg::OnSendFile()
{
// TODO: Add your control notification handler code here
CFileDialog dlg(true);
CString ip;
m_ip.GetWindowText(ip);
CString title="文件发往"+ip+"请选择";
dlg.m_ofn.lpstrTitle=title;//标题条
if(dlg.DoModal()==IDOK)
{
m_fileName=dlg.GetPathName();
GetDlgItem(IDC_VOICE)->ShowWindow(SW_HIDE);
GetDlgItem(IDOK)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_PROGRESS_SEND_FILE)->ShowWindow(SW_SHOW);
// GetDlgItem(IDCANCEL)->ShowWindow(SW_HIDE);
pThreadSendFile=::AfxBeginThread(_SendFileThread,this); //开始传送文件线程
}
}
int CChatDlg::SaveYouFile(CSocket &recSo, SOCKADDR_IN &client)//接受文件
{
CString fname;
CFileDialog dlg(false); //另存文件
FILEINFO myFileInfo;
recSo.Receive(&myFileInfo,sizeof(FILEINFO));
int fileLength=myFileInfo.fileLength;
CString strfileIp,strfileName,strfileLength;
strfileIp.Format(inet_ntoa(client.sin_addr));
strfileName.Format(myFileInfo.fileName);
strfileLength.Format("%f",myFileInfo.fileLength/1024.0);
CString title="文件"+strfileName+" 大小"+strfileLength+"KB "+"来在"+strfileIp+" 是否接受";
if(IDYES==MessageBox(title,"是否接收文件?",MB_YESNO))
{
dlg.m_ofn.lpstrTitle=title;//标题条
char fileme[500]={0};//必须足够大小
strcpy(fileme,/*strfileIp+*/strfileName);
dlg.m_ofn.lpstrFile=fileme; //文件名称
if(dlg.DoModal()==IDOK)
{
fname=dlg.GetPathName(); //得到文件名名称、路径
GetDlgItem(IDC_PROGRESS_SEND_FILE)->ShowWindow(SW_SHOW);
GetDlgItem(IDC_VOICE)->ShowWindow(SW_HIDE);
GetDlgItem(IDOK)->ShowWindow(SW_HIDE);
}
else
{
GetDlgItem(IDC_PROGRESS_SEND_FILE)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_STOP_FILESEND)->EnableWindow(false);
GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(true);
GetDlgItem(IDCANCEL)->EnableWindow(true);
recSo.Close();
return 0;
}
char buf[SIZEFILE]={0};
CFile f(fname,CFile::modeCreate|CFile::modeWrite); //存文件
m_Progress.SetRange32(0,fileLength);
int n=0; //接受的字节数 0表示结束
int temp=0;
GetDlgItem(IDC_STOP_FILESEND)->EnableWindow(true);
GetDlgItem(IDCANCEL)->EnableWindow(false);
GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(false);
for(;;)
{
n=recSo.Receive(buf,SIZEFILE); //接受
if(n==0) //0表示结束
break; //接受完毕
f.Write(buf,n);
temp+=n;
m_Progress.SetPos(temp);
if(FileWork==false)
FileWork=true;
if(FileStop==true)
{
FileStop=false;
FileWork=false;
break ;
}
}
f.Close();
m_Progress.SetPos(0);
if(temp==fileLength)
MessageBox("文件接收成功!");
else
MessageBox("文件接收失败!");
FileWork=false;
GetDlgItem(IDC_PROGRESS_SEND_FILE)->ShowWindow(SW_HIDE);
// GetDlgItem(IDCANCEL)->ShowWindow(SW_SHOW);
GetDlgItem(IDC_STOP_FILESEND)->EnableWindow(false);
GetDlgItem(IDCANCEL)->EnableWindow(true);
GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(true);
GetDlgItem(IDC_VOICE)->ShowWindow(SW_SHOW);
GetDlgItem(IDOK)->ShowWindow(SW_SHOW);
}
return 0;
}
//TCP监听线程
UINT _ListenTcpThread(LPVOID lparam)
{
CChatDlg *pDlg=(CChatDlg *)lparam;
if(pDlg->StopServer==true) return -1;
CSocket sockSrvr;
pDlg->m_Potr=PORT+pDlg->m_server;//保存当前使用端口,用于关闭
int createSucceed=sockSrvr.Create(pDlg->m_Potr);
if(createSucceed==0)
{
AfxMessageBox("_ListenTcpThread Create错误!"+pDlg->GetError(GetLastError()));
return -1;
}
int listenSucceed=sockSrvr.Listen(); //开始监听
if(listenSucceed==0)
{
AfxMessageBox("_ListenTcpThread Listen错误!"+pDlg->GetError(GetLastError()));
return -1;
}
CSocket recSo;
SOCKADDR_IN client;
int iAddrSize=sizeof(client);
int acceptSucceed=sockSrvr.Accept(recSo,(SOCKADDR *)&client,&iAddrSize); //接受连接并取得对方IP
if(acceptSucceed==0)
{
AfxMessageBox("_ListenTcpThread Accept错误!"+pDlg->GetError(GetLastError()));
return -1;
}
sockSrvr.Close();
char flag[FLAG]={0};
if(recSo.Receive(flag,FLAG)!=2)
{
return -1;
}
pDlg->m_type=flag[0];
if(pDlg->m_type=='D') return 0;
pThreadLisen=::AfxBeginThread(_ListenTcpThread,pDlg);
pDlg->ReceiveFileMsg(recSo,client);
return 0;
}
HBITMAP CChatDlg::CopyScreenToBitmap()
{
CRect rect(0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN));
HDC hScrDC,hMemDC; // 屏幕和内存设备描述表
HBITMAP hBitmap, hOldBitmap;// 位图句柄
int xScrn, yScrn; // 屏幕分辨率
hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL); //为屏幕创建设备描述表
hMemDC = CreateCompatibleDC(hScrDC);//为屏幕设备描述表创建兼容的内存设备描述表
xScrn = GetDeviceCaps(hScrDC, HORZRES);// 获得屏幕分辨率
yScrn = GetDeviceCaps(hScrDC, VERTRES);
hBitmap = CreateCompatibleBitmap(hScrDC, rect.Width(), rect.Height());// 创建一个与屏幕设备描述表兼容的位图
hOldBitmap =(HBITMAP)SelectObject(hMemDC, hBitmap);// 把新位图选到内存设备描述表中
BitBlt(hMemDC, 0, 0, rect.Width(), rect.Height(),hScrDC,rect.left,rect.top, SRCCOPY);// 把屏幕设备描述表拷贝到内存设备描述表中
hBitmap =(HBITMAP)SelectObject(hMemDC, hOldBitmap);//得到屏幕位图的句柄
DeleteDC(hScrDC);//清除
DeleteDC(hMemDC);
return hBitmap;// 返回位图句柄
}
void CChatDlg::SaveYouScreen(HBITMAP hBitmap,SOCKADDR_IN &client)//接受屏幕
{
OnGetCaputer();
CSocket sockClient;
sockClient.Create();
sockClient.Connect(inet_ntoa(client.sin_addr), PORT+m_client); //连接到申请方
//首先发送标记F为文件,2
FILEINFO myFileInfo;
myFileInfo.fileLength=sizeof(BITMAPFILEHEADER)+dwDIBSize;//得到文件大小
strcpy(myFileInfo.fileName,"对方屏幕.bmp");//得到文件名称
sockClient.Send("F",FLAG);
sockClient.Send(&myFileInfo,sizeof(FILEINFO));
sockClient.Send(&bmfHdr, sizeof(BITMAPFILEHEADER));
sockClient.Send(lpbi, dwDIBSize); //////////////////////////////////////
GlobalUnlock(hDib);
GlobalFree(hDib);
}
int CChatDlg::ReceiveFileMsg(CSocket &recSo,SOCKADDR_IN &client)//接受函数
{
// if(StopServer==true) return -1;
if(m_type=='C') //抓取
{
SaveYouScreen(CopyScreenToBitmap(),client);//发送地址
}
else if(m_type=='F') //文件
{
SaveYouFile(recSo,client);
}
else if(m_type=='M') //信息
{
char buff[100]={0};
CString msg;
int ret=0;
for(;;)
{
ret=recSo.Receive(buff,100);
if(ret==0)
break;
msg+=buff;
}
CString strOut,strIn;
m_ip.GetWindowText(strIn);
GetNamebyAddress(strIn,strOut);
CString youName;
youName.Format(inet_ntoa(client.sin_addr));
CString str=youName+"<-"+strOut;
}
recSo.Close();
return 0;
}
void CChatDlg::OnConnect()
{
// TODO: Add your control notification handler code here
CString str;
m_ip.GetWindowText(str);
CString strOut,strIn;
m_ip.GetWindowText(strIn);
if(GetNamebyAddress(strIn,strOut)==-1)
{
GetDlgItem(IDC_CONNECT)->EnableWindow(true);//连接不可用
return;
}
pThreadLisen=::AfxBeginThread(_ListenTcpThread,this); //开始TCP线程
GetDlgItem(IDC_SEND_FILE)->EnableWindow(true);//文件可用
GetDlgItem(IDC_BUTTON_CAPUTER)->EnableWindow(true);
GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(true);//断开可用
GetDlgItem(IDC_CONNECT)->EnableWindow(false);//连接不可用
GetDlgItem(IDC_IPADDRESS1)->EnableWindow(false);
}
void CChatDlg::OnButtonDisconnect()
{
// TODO: Add your control notification handler code here
FileStop=true;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?