chatdlg.cpp

来自「仿造QQ聊天界面 超级相向 第一次作品 不足之处见谅」· C++ 代码 · 共 1,568 行 · 第 1/3 页

CPP
1,568
字号
	FileWork=false;
	GetDlgItem(IDCANCEL)->EnableWindow(true);
	GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(false);
	GetDlgItem(IDC_CONNECT)->EnableWindow(true);//连接可用
	GetDlgItem(IDC_IPADDRESS1)->EnableWindow(true);
	GetDlgItem(IDC_SEND_FILE)->EnableWindow(false);
	GetDlgItem(IDC_BUTTON_CAPUTER)->EnableWindow(false);
	DWORD   dwStatus;
	if (pThreadLisen != NULL)
	{
		if(::GetExitCodeThread(pThreadLisen->m_hThread, &dwStatus)==0)
		{
			int errror=GetLastError();
			return;
		}
		if (dwStatus == STILL_ACTIVE)
		{
			CSocket sockClient;
			sockClient.Create();
			CString ip,strError;
			ip="127.0.0.1";
			int conn=sockClient.Connect(ip, m_Potr);
			if(conn==0)	
			{
				AfxMessageBox("关闭错误!"+GetError(GetLastError()));
				sockClient.ShutDown(2);
				sockClient.Close();
				return;
				
			}
			sockClient.Send("D",FLAG); //结束
			
		}
		else
		{
			delete pThreadLisen;
			pThreadLisen = NULL;
		}
	}	
}


UINT _ThreadCapture(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); 
	//首先发送标记C为抓取,2
	int end=0;
	end=sockClient.Send("C",FLAG);
	///////////////////////////////////////////////////////////////////发送标志是否成功
	if(end==SOCKET_ERROR)										
	{
		AfxMessageBox("_ThreadCapture Send错误!"+pDlg->GetError(GetLastError()));
		return -1;
	}
	
	else if(end!=2) 
	{
		AfxMessageBox("发送头错误");
		return -1;
	}
	return 0;
}

void CChatDlg::OnButtonCaputer() 
{
	// TODO: Add your control notification handler code here
	pThreadCaputre=::AfxBeginThread(_ThreadCapture,this);	//开始传送文件线程
}

void CChatDlg::OnMyCaputer() 
{
	// TODO: Add your control notification handler code here
	
	OnGetCaputer();
	CFileDialog dlg(false);   			/////存储文件
	dlg.m_ofn.lpstrFilter="*.bmp";
	CString filename;
	if (dlg.DoModal() == IDOK)
	{
		filename=dlg.GetFileName();

	}
	else
		return ;
	UpdateData(FALSE);
	CFile f(filename+".bmp",CFile::modeCreate|CFile::modeWrite);//存文件
	f.Write(&bmfHdr, sizeof(BITMAPFILEHEADER)); 
	f.Write(lpbi, dwDIBSize);
	GlobalUnlock(hDib);
	GlobalFree(hDib);	
	f.Close();

}

void CChatDlg::OnGetCaputer() 
{
	// TODO: Add your control notification handler code here
	HBITMAP hBitmap=CopyScreenToBitmap();
	dwPaletteSize=0;
	hOldPal=NULL;
	HDC hDC; //设备描述表
	hDC = CreateDC("DISPLAY",NULL,NULL,NULL);
	iBits = GetDeviceCaps(hDC, BITSPIXEL)*GetDeviceCaps(hDC, PLANES);//计算位图文件每个像素所占字节数
	DeleteDC(hDC);
	if (iBits <= 1)
		wBitCount = 1;
	else if (iBits <= 4)
		wBitCount = 4;
	else if (iBits <= 8)
		wBitCount = 8;
	else if (iBits <= 16)
		wBitCount = 16;
	else if (iBits <= 24)
		wBitCount = 24;
	else wBitCount=32;
	if (wBitCount <= 8)
		dwPaletteSize = (1<<wBitCount)*sizeof(RGBQUAD);//计算调色板大小
	
	//设置位图信息头结构
	GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
	bi.biSize            = sizeof(BITMAPINFOHEADER);
	bi.biWidth           = Bitmap.bmWidth;
	bi.biHeight          = Bitmap.bmHeight;
	bi.biPlanes          = 1;
	bi.biBitCount         = wBitCount;
	bi.biCompression      = BI_RGB;
	bi.biSizeImage        = 0;
	bi.biXPelsPerMeter     = 0;
	bi.biYPelsPerMeter     = 0;
	bi.biClrUsed         = 0;
	bi.biClrImportant      = 0;
	
	dwBmBitsSize = ((Bitmap.bmWidth * wBitCount+31)/32)* 4 *Bitmap.bmHeight ;
	//为位图内容分配内存
	hDib  = GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER));
	lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
	*lpbi=bi;					/////////////////////////////////////////
	// 处理调色板   
	hPal = GetStockObject(DEFAULT_PALETTE);
	if (hPal)
	{
		hDC=::GetDC(NULL);
		hOldPal = SelectPalette(hDC,(HPALETTE)hPal, FALSE);
		RealizePalette(hDC);
	}
	// 获取该调色板下新的像素值
	GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,
		(LPSTR)lpbi + sizeof(BITMAPINFOHEADER)+dwPaletteSize,
		(BITMAPINFO*)lpbi, DIB_RGB_COLORS);
	//恢复调色板   
	if (hOldPal)
	{
		SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
		RealizePalette(hDC);
		::ReleaseDC(NULL, hDC);
	}
	// 设置位图文件头
	bmfHdr.bfType = 0x4D42;  // "BM"
	dwDIBSize    = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+ dwPaletteSize + dwBmBitsSize;  
	bmfHdr.bfSize = dwDIBSize;
	bmfHdr.bfReserved1 = 0;
	bmfHdr.bfReserved2 = 0;
	bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER)+ dwPaletteSize;
	
	//首先发送标记F为文件,2
	FILEINFO myFileInfo;
	myFileInfo.fileLength=sizeof(BITMAPFILEHEADER)+dwDIBSize;//得到文件大小
}

void CChatDlg::OnStopFilesend() 
{
	// TODO: Add your control notification handler code here
	FileStop=true;
	FileWork=false;
	GetDlgItem(IDCANCEL)->EnableWindow(true);
	GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(true);
}
/////////////////////////////////////////////////
//////////////////////////////////////////////////
UINT Audio_Listen_Thread(LPVOID lParam)
{
	CChatDlg *pdlg = (CChatDlg*)lParam;
    CSocket m_Server;
	DWORD 	length;
	if(!m_Server.Create(6060))
	     AfxMessageBox("Listen Socket create error"+pdlg->GetError(GetLastError()));//不可单个运行,重复产生同一端口显然是错误的
	if(!m_Server.Listen()) 
		AfxMessageBox("m_server.Listen ERROR"+pdlg->GetError(GetLastError()));
	CSocket recSo;
   if(! m_Server.Accept(recSo))
	   AfxMessageBox("m_server.Accept() error"+pdlg->GetError(GetLastError()));
	m_Server.Close();	
	int sendcount=0;//just for test
	int ret ;
	while(1)
	{   //开始循环接收声音文件,首先接收文件长度
		
	    ret = recSo.Receive(&length,sizeof(DWORD));		
		if(ret== SOCKET_ERROR )
		AfxMessageBox("服务器端接收声音文件长度出错,原因: "+pdlg->GetError(GetLastError()));
		if(ret!=sizeof(DWORD))
		{
			AfxMessageBox("接收文件头错误,将关闭该线程");
        	recSo.Close();
	        return -1;
		}//接下来开辟length长的内存空间
		pdlg->m_AudioDataOut[pdlg->nReceive].lpdata =(PBYTE)realloc (0,length);
	    if (pdlg->m_AudioDataOut[pdlg->nReceive].lpdata == NULL)
		{
			MessageBeep (MB_ICONEXCLAMATION) ;
			AfxMessageBox("erro memory_ReceiveAudio");
//            pdlg->OnOK();
			recSo.Close();
	        return -1;
		}
		else//内存申请成功,可以进行循环检测接受
		{
			
			DWORD dwReceived = 0,dwret;
			while(length>dwReceived)
			{
				
				dwret = recSo.Receive((pdlg->m_AudioDataOut[pdlg->nReceive].lpdata+dwReceived),(length-dwReceived));
			    dwReceived +=dwret;
				if(dwReceived ==length)
				{
                    pdlg->m_AudioDataOut[pdlg->nReceive].dwLength = length;
					break;
				}
				
			}
		}//本轮声音文件接收完毕	
	    pdlg->nReceive=(pdlg->nReceive+1)%OutBlocks;
	}
	recSo.Close();
//	pdlg->OnOK();
	return 0;
}
UINT Audio_Send_Thread(LPVOID lParam)//专职的声音文件发送线程
{                                    // 端口也是专用的
	
	CChatDlg *pdlg = (CChatDlg*)lParam;
	CSocket m_Client;
	m_Client.Create();
	if( m_Client.Connect(pdlg->str2,6060))
	{		
		DWORD ret, length;
		int count=0;
		while(1)//循环使用指针nSend
		{
		    	
			length =pdlg->m_AudioDataIn[pdlg->nSend].dwLength;
        	if(length !=0)
			{   //首先发送块的长度
                if(((ret = m_Client.Send(&length,sizeof(DWORD)))!=sizeof(DWORD))||(ret==SOCKET_ERROR))
				{   
				   AfxMessageBox("声音文件头传输错误!"+pdlg->GetError(GetLastError()));
//				   pdlg->OnOK();
			       break;	
				}//其次发送块的内容	,循环检测发送
				DWORD dwSent = 0;//已经发送掉的字节数
				while(1)//==============================发送声音文件开始
				{
					ret = m_Client.Send((pdlg->m_AudioDataIn[pdlg->nSend].lpdata+dwSent),(length-dwSent));
					if(ret==SOCKET_ERROR)//检错
					{
					   AfxMessageBox("声音文件传输错误!"+pdlg->GetError(GetLastError()));
//					   pdlg->OnOK();
					   break;			
					}
					else //发送未发送完的
					{
						dwSent += ret;
						if(dwSent ==length)
						{   
    					free(pdlg->m_AudioDataIn[pdlg->nSend].lpdata);
						pdlg->m_AudioDataIn[pdlg->nSend].dwLength = 0;
						break;
						}
					}	
				}  //======================================发送声音文件结束
			}
			pdlg->nSend = (pdlg->nSend +1)% InBlocks;
			}
			
	}
	else 
		AfxMessageBox("Socket连接失败"+pdlg->GetError(GetLastError()));
	m_Client.Close();
	return 0;
}

void CChatDlg::OnVoice() 
{
	
	// TODO: Add your control notification handler code here
	((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);

	GetDlgItem(IDC_VOICE)->EnableWindow(false);
	GetDlgItem(IDOK)->EnableWindow(true);
	//allocate buffer memory
	pBuffer1=(PBYTE)malloc(INP_BUFFER_SIZE);
	pBuffer2=(PBYTE)malloc(INP_BUFFER_SIZE);
	if (!pBuffer1||!pBuffer2) 
	{
		if (pBuffer1) free(pBuffer1);
		if (pBuffer2) free(pBuffer2);
		MessageBeep(MB_ICONEXCLAMATION);
		AfxMessageBox("Memory erro!");
		return ;
	}
	
	//open waveform audio for input
	
	m_waveformin.wFormatTag=WAVE_FORMAT_PCM;
	m_waveformin.nChannels=1;
	m_waveformin.nSamplesPerSec=11025;//采样频率
	m_waveformin.nAvgBytesPerSec=11025;
	m_waveformin.nBlockAlign=1;
	m_waveformin.wBitsPerSample=8;
	m_waveformin.cbSize=0;
	
	if (waveInOpen(&hWaveIn,WAVE_MAPPER,&m_waveformin,(DWORD)this->m_hWnd,NULL,CALLBACK_WINDOW))
	{   //打开录音设备函数 
		free(pBuffer1);
		free(pBuffer2);
		MessageBeep(MB_ICONEXCLAMATION);
		AfxMessageBox("Audio can not be open!");
	}
	pWaveHdr1->lpData=(LPTSTR)pBuffer1;
	pWaveHdr1->dwBufferLength=INP_BUFFER_SIZE;
	pWaveHdr1->dwBytesRecorded=0;
	pWaveHdr1->dwUser=0;
	pWaveHdr1->dwFlags=0;
	pWaveHdr1->dwLoops=1;
	pWaveHdr1->lpNext=NULL;
	pWaveHdr1->reserved=0;
	waveInPrepareHeader(hWaveIn,pWaveHdr1,sizeof(WAVEHDR));
	
	pWaveHdr2->lpData=(LPTSTR)pBuffer2;
	pWaveHdr2->dwBufferLength=INP_BUFFER_SIZE;
	pWaveHdr2->dwBytesRecorded=0;
	pWaveHdr2->dwUser=0;
	pWaveHdr2->dwFlags=0;
	pWaveHdr2->dwLoops=1;
	pWaveHdr2->lpNext=NULL;
	pWaveHdr2->reserved=0;
	
	waveInPrepareHeader(hWaveIn,pWaveHdr2,sizeof(WAVEHDR));
	
	// Add the buffers
	
	waveInAddBuffer (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ;
	waveInAddBuffer (hWaveIn, pWaveHdr2, sizeof (WAVEHDR)) ;
	
	// Begin sampling
	waveInStart (hWaveIn) ;
	
	::AfxBeginThread(Audio_Listen_Thread,this);
	::AfxBeginThread(Audio_Send_Thread,this);
	m_waveformout.wFormatTag		=	WAVE_FORMAT_PCM;
	m_waveformout.nChannels		    =1;
	m_waveformout.nSamplesPerSec	=11025;
	m_waveformout.nAvgBytesPerSec   =11025;
	m_waveformout.nBlockAlign	    =1;
	m_waveformout.wBitsPerSample	=8;
	m_waveformout.cbSize			=0;
	
	
	if (waveOutOpen(&hWaveOut,WAVE_MAPPER,&m_waveformout,(DWORD)this->m_hWnd,NULL,CALLBACK_WINDOW)) {
		MessageBeep(MB_ICONEXCLAMATION);
		AfxMessageBox("Audio output erro");
	}
	
	return ;
}

void CChatDlg::OnMM_WIM_DATA(UINT wParam,LONG lParam)
{
   
    int nextBlock = (nAudioIn+1)% InBlocks;	
	if(m_AudioDataIn[nextBlock].dwLength!=0)//下一“块”没发走
	{  //把PWAVEHDR(即pBUfferi)里的数据拷贝到当前“块”中
        
	 	m_AudioDataIn[nAudioIn].lpdata  
		= (PBYTE)realloc (m_AudioDataIn[nAudioIn].lpdata , (((PWAVEHDR) lParam)->dwBytesRecorded+m_AudioDataIn[nAudioIn].dwLength)) ;
		if (m_AudioDataIn[nAudioIn].lpdata == NULL)
		{
			waveInClose (hWaveIn) ;
			MessageBeep (MB_ICONEXCLAMATION) ;
			AfxMessageBox("erro memory OnMM_WIM_DATA");
			return ;
		}
	    CopyMemory ((m_AudioDataIn[nAudioIn].lpdata+m_AudioDataIn[nAudioIn].dwLength), 
				   ((PWAVEHDR) lParam)->lpData,
				   ((PWAVEHDR) lParam)->dwBytesRecorded) ;//(*destination,*resource,nLen);
		
		m_AudioDataIn[nAudioIn].dwLength +=((PWAVEHDR) lParam)->dwBytesRecorded;
        
	}
	else //把PWAVEHDR(即pBUfferi)里的数据拷贝到下一“块”中
	{
		nAudioIn = (nAudioIn+1)% InBlocks;
		m_AudioDataIn[nAudioIn].lpdata = (PBYTE)realloc
			(0,((PWAVEHDR) lParam)->dwBytesRecorded);
		CopyMemory(m_AudioDataIn[nAudioIn].lpdata,
			    ((PWAVEHDR) lParam)->lpData,
				((PWAVEHDR) lParam)->dwBytesRecorded) ;
	   m_AudioDataIn[nAudioIn].dwLength =((PWAVEHDR) lParam)->dwBytesRecorded;

	}
  	// Send out a new buffer	
	waveInAddBuffer (hWaveIn, (PWAVEHDR) lParam, sizeof (WAVEHDR)) ;
	return ;
}

void CChatDlg::OnMM_WIM_CLOSE(UINT wParam,LONG lParam)
{

	waveInUnprepareHeader (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ;
	waveInUnprepareHeader (hWaveIn, pWaveHdr2, sizeof (WAVEHDR)) ;
	
	free (pBuffer1) ;
	free (pBuffer2) ;

	return ;
}
void CChatDlg::OnMM_WOM_OPEN(UINT wParam,LONG lParam)
{   
	// Set up header    
	pWaveHdrOut->lpData          = (LPTSTR)m_AudioDataOut[nAudioOut].lpdata ;
	pWaveHdrOut->dwBufferLength  = m_AudioDataOut[nAudioOut].dwLength ;
    pWaveHdrOut->dwBytesRecorded = 0 ;
	pWaveHdrOut->dwUser          = 0 ;
	pWaveHdrOut->dwFlags         = WHDR_BEGINLOOP ;
	pWaveHdrOut->dwLoops         = 1 ;
	pWaveHdrOut->lpNext          = NULL ;
	pWaveHdrOut->reserved        = 0 ;

    // Prepare and write
	waveOutPrepareHeader (hWaveOut, pWaveHdrOut, sizeof (WAVEHDR)) ;
	waveOutWrite (hWaveOut, pWaveHdrOut, sizeof (WAVEHDR)) ;

  return;
	
}
void CChatDlg::OnMM_WOM_DONE(UINT wParam,LONG lParam)
{  
	free(m_AudioDataOut[nAudioOut].lpdata);
	m_AudioDataOut[nAudioOut].lpdata = reinterpret_cast<PBYTE>(malloc(1));
	m_AudioDataOut[nAudioOut].dwLength = 0;
 
    nAudioOut= (nAudioOut+1)%OutBlocks;
	((PWAVEHDR)lParam)->lpData          = (LPTSTR)m_AudioDataOut[nAudioOut].lpdata ;
	((PWAVEHDR)lParam)->dwBufferLength  = m_AudioDataOut[nAudioOut].dwLength ;
    TRACE("the next length %d\n",((PWAVEHDR)lParam)->dwBufferLength);
	waveOutPrepareHeader (hWaveOut,(PWAVEHDR)lParam,sizeof(WAVEHDR));
    waveOutWrite(hWaveOut,(PWAVEHDR)lParam,sizeof(WAVEHDR));//cut
   return;

}
void CChatDlg::OnMM_WOM_CLOSE(UINT wParam,LONG lParam)
{
	waveOutUnprepareHeader (hWaveOut, pWaveHdrOut, sizeof (WAVEHDR)) ;
		
	//release all the memory of the AudioData
	for(int i=0;i<InBlocks;i++)
	{
		if(m_AudioDataIn[i].dwLength != 0)
			free(m_AudioDataIn[i].lpdata);
		
	}
	for(i=0;i<OutBlocks;i++)
	{
		if(m_AudioDataOut[i].dwLength != 0)
			free(m_AudioDataOut[i].lpdata);
	}
}
void CChatDlg::OnOK() 
{
	// TODO: Add extra validation here
	waveInReset(hWaveIn);
    waveInClose(hWaveIn);
	
	waveOutReset(hWaveOut);
	waveOutClose (hWaveOut);
	GetDlgItem(IDC_VOICE)->EnableWindow(true);
	GetDlgItem(IDOK)->EnableWindow(false);
}

void CChatDlg::OnSize(UINT nType, int cx, int cy) 
{
	CDialog::OnSize(nType, cx, cy);
	
	// TODO: Add your message handler code here


}

void CChatDlg::OnDestroy() 
{
	CDialog::OnDestroy();
	
	// TODO: Add your message handler code here
//	CAboutDlg dlg;
//	dlg.DoModal();
}


⌨️ 快捷键说明

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