www.pudn.com > mischat.rar > mischatDoc.cpp


// mischatDoc.cpp : implementation of the CmischatDoc class 
// 
 
#include "stdafx.h" 
#include "mischat.h" 
#include "mischatDoc.h" 
#include "mischatView.h" 
#include "Draw.h" 
#include "DrawTypeId.h" 
#include ".\mischatdoc.h" 
#include "NDKMessage.h" 
#include "ChatMessage.h" 
#include "MainFrm.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#endif 
// CmischatDoc 
#define WM_REFRESHCAPTIONBAR WM_USER + 0x7FFF 
#define WM_APPENDOUTPUTBARINFO WM_USER + 0x7FFE 
#define WM_REFRESHIPBAR WM_USER + 0x7FFD 
#define WM_PANEGROGRESSBAR WM_USER + 0x7FFC 
 
#define FILEBLOCKSIZE 2048 
extern CMainFrame* pMainWnd; 
 
IMPLEMENT_DYNCREATE(CmischatDoc, CDocument) 
 
BEGIN_MESSAGE_MAP(CmischatDoc, CDocument) 
	ON_COMMAND(IDM_SERVERSTART, OnServerStart) 
	ON_COMMAND(IDM_SERVERSTOP, OnServerStop) 
	ON_COMMAND(IDM_CLIENTSTART, OnClientStart) 
	ON_COMMAND(IDM_CLIENTSTOP, OnClientStop) 
	ON_UPDATE_COMMAND_UI(IDM_CLIENTSTOP, OnUpdateClientStop) 
	ON_UPDATE_COMMAND_UI(IDM_CLIENTSTART, OnUpdateClientStart) 
	ON_UPDATE_COMMAND_UI(IDM_SERVERSTOP, OnUpdateServerStop) 
	ON_UPDATE_COMMAND_UI(IDM_SERVERSTART, OnUpdateServerStart) 
END_MESSAGE_MAP() 
 
 
// CmischatDoc construction/destruction 
CmischatDoc* pDoc; 
 
CmischatDoc::CmischatDoc() 
{ 
	// TODO: add one-time construction code here 
	flag=NOTHING; 
	pDoc=this; 
	pView=NULL; 
	outputInfo.SetSize (500,50); 
	outInfoIndex=0; 
	CanTransmitFile=FALSE; 
	 
	TCHAR szPath[MAX_PATH]; 
	memset(szPath,'\0',sizeof(szPath)); 
	::GetModuleFileName(NULL,szPath,sizeof(szPath)/sizeof(TCHAR)); 
	strModulePath=szPath; 
	int index=strModulePath.ReverseFind(_T('\\')); 
	ASSERT(index!=-1); 
	strModulePath=strModulePath.Left(index+1); 
 
	if(!ReadIniFile(strModulePath+"chat.env")) 
	{ 
		widthPen=3; 
		corPen=RGB(255,0,0),corBrush=RGB(0,0,255),corText=RGB(0,0,0); 
		m_strIP="127.0.0.1"; 
		strName=_T("无名氏"); 
		m_ServerPort=m_ClientPort=6000; 
		m_ConnectMax=10; 
		ChatPrivilege=_T("禁止"); 
		CFont::FromHandle ((HFONT) GetStockObject (DEFAULT_GUI_FONT))->GetLogFont (&lf); 
	} 
} 
 
CmischatDoc::~CmischatDoc() 
{ 
	while(!drawList.IsEmpty ()) delete drawList.RemoveHead(); 
	ip_socket_map.RemoveAll (); 
	AllIPList.RemoveAll (); 
	DenyIPList.RemoveAll (); 
	server.UnInit (); 
	client.UnInit (); 
} 
 
BOOL CmischatDoc::OnNewDocument() 
{ 
	if (!CDocument::OnNewDocument()) 
		return FALSE; 
 
	// TODO: add reinitialization code here 
	// (SDI documents will reuse this document) 
	if(strModulePath.IsEmpty ()) return FALSE; 
 
	TCHAR env[MAX_PATH]; 
	memset(env,'\0',sizeof(env)); 
	if(::GetEnvironmentVariable(_T("TEMP"),env,sizeof(env)/sizeof(TCHAR))==0) return FALSE; 
	strTempFileS.Format ("%s\\updates.chat",env); 
	strTempFileC.Format ("%s\\updatec.chat",env); 
	TRACE("strTempFileS=%s\n",strTempFileS); 
 
	POSITION pos = GetFirstViewPosition(); 
    if(pos != NULL) 
    { 
      pView = static_cast(GetNextView(pos)); 
    } 
	return pView!=NULL; 
} 
 
bool CmischatDoc::ReadIniFile(CString& str) 
{ 
	HANDLE hSearch; 
	WIN32_FIND_DATA fd; 
	hSearch = FindFirstFile(str, &fd);  
	if (hSearch != INVALID_HANDLE_VALUE)  
	{  
		CFile myFile; 
		CFileException e; 
 
		try{   
			myFile.Open(str, CFile::modeRead|CFile::typeBinary, &e); 
			CArchive ar(&myFile, CArchive::load); 
			Serialize(ar); 
			ar.Close(); 
			myFile.Close(); 
		} 
		catch(CFileException * e){ 
			e->ReportError(); 
			e->Delete(); 
		} 
		return true;		 
	}else return false; 
} 
 
void CmischatDoc::SaveIniFile(CString& str) 
{ 
	CFile myFile; 
	CFileException e; 
 
	try{   
		myFile.Open(str, CFile::modeWrite|CFile::modeCreate|CFile::typeBinary, &e); 
		CArchive ar(&myFile, CArchive::store); 
		Serialize(ar); 
		ar.Close(); 
		myFile.Close(); 
	} 
	catch(CFileException * e){ 
		e->ReportError(); 
		e->Delete(); 
	} 
 
} 
 
void CmischatDoc::OpenWhiteBroad() 
{ 
	CString strFilter=_T("白板文件(*.chat)|*.chat||"); 
	CFileDialog dlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST,strFilter); 
	if(dlg.DoModal() ==IDOK) 
	{	 
		CFile myFile; 
		CFileException e; 
 
		try{   
			myFile.Open(dlg.GetPathName (), CFile::modeRead|CFile::typeBinary, &e); 
			CArchive ar(&myFile, CArchive::load); 
			csDrawInfo.Lock (); 
			while(!drawList.IsEmpty ()) delete drawList.RemoveHead(); 
			drawList.Serialize(ar); 
			csDrawInfo.Unlock (); 
			ar.Close(); 
			myFile.Close(); 
			pView->Invalidate (); 
		} 
		catch(CFileException * e){ 
			e->ReportError(); 
			e->Delete(); 
		} 
	} 
} 
 
void CmischatDoc::SaveWhiteBroad() 
{ 
	HRESULT hResult; 
	TCHAR strFilter[]=_T("白板文件(*.chat)|*.chat||"); 
	CFileDialog dlg(FALSE,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER,strFilter); 
	hResult = (int)dlg.DoModal(); 
	if (hResult != IDOK) { 
		return; 
	} 
    // Add the appropriate extension if the user didn't type one 
	CString strFileName; 
	strFileName = dlg.m_ofn.lpstrFile; 
	// add the file extension if the user didn't supply one 
	if (dlg.m_ofn.nFileExtension == 0)  
	{ 
		strFileName = strFileName + ".chat"; 
	} 
 
	CFile myFile; 
	CFileException e; 
 
	try{   
		myFile.Open(strFileName,CFile::modeWrite|CFile::modeCreate|CFile::typeBinary, &e); 
		CArchive ar(&myFile, CArchive::store); 
		csDrawInfo.Lock (); 
		drawList.Serialize(ar); 
		csDrawInfo.Unlock (); 
		ar.Close(); 
		myFile.Close(); 
	} 
	catch(CFileException * e){ 
		e->ReportError(); 
		e->Delete(); 
	} 
 
} 
 
// CmischatDoc serialization 
 
void CmischatDoc::Serialize(CArchive& ar) 
{ 
	if (ar.IsStoring()) 
	{ 
		// TODO: add storing code here 
		ar<>widthPen>>corPen>>corBrush>>corText>>m_strIP>>strName>>m_ServerPort>>m_ClientPort>>m_ConnectMax>>ChatPrivilege; 
		ar.Read (&lf,sizeof(LOGFONT)); 
	} 
	DenyIPList.Serialize (ar); 
} 
 
 
// CmischatDoc diagnostics 
 
#ifdef _DEBUG 
void CmischatDoc::AssertValid() const 
{ 
	CDocument::AssertValid(); 
} 
 
void CmischatDoc::Dump(CDumpContext& dc) const 
{ 
	CDocument::Dump(dc); 
} 
#endif //_DEBUG 
// CmischatDoc commands 
 
void CmischatDoc::AppendAndDispOutputBarInfo(CString strInfo) 
{ 
	pDoc->csOutputInfo.Lock (); 
	pDoc->outputInfo.SetAtGrow (pDoc->outInfoIndex,strInfo); 
	pDoc->outInfoIndex++; 
	LPTSTR p=strInfo.LockBuffer (); 
	pMainWnd->SendMessage (WM_APPENDOUTPUTBARINFO,0,(LPARAM)p); 
	strInfo.UnlockBuffer(); 
	pDoc->csOutputInfo.Unlock(); 
} 
 
void  CmischatDoc::AddToTailAndDraw(CDraw* pdw) 
{ 
	pDoc->csDrawInfo.Lock (); 
	pDoc->drawList.AddTail (pdw); 
	pView->Draw(pdw); 
	pDoc->csDrawInfo.Unlock(); 
} 
 
void CmischatDoc::SProcessRecvData(unsigned long sIP,SOCKET sClient,char * pData,unsigned long DataLength,BOOL hint) 
{ 
	CString str; 
	if(pData!=NULL) 
	{ 
		if(hint)//WriteLogString发来的数据:连接、断开、SOCKET函数调用错误 
		{ 
			str=pData; 
			pDoc->AppendAndDispOutputBarInfo(str); 
			if(sIP!=0 && str.Find (_T("断开"))!=-1){//断开 
				pDoc->csAllIPList .Lock (); 
				pDoc->RemoveFromIPList(pDoc->AllIPList,sIP); 
				pDoc->SendUserList(); 
				pMainWnd->SendMessage (WM_REFRESHIPBAR); 
				pDoc->csAllIPList .Unlock (); 
			} 
			return; 
		} 
		CNDKMessage mg; 
		pDoc->PCharToCNDKMessage(mg,pData,DataLength); 
		switch(mg.GetId ()) 
		{ 
		case ChatUserJoin: 
			pDoc->csAllIPList .Lock (); 
			pDoc->ProcessUserJoin(mg,sIP,sClient); 
			pDoc->csAllIPList .Unlock (); 
			break; 
 
		case ChatText: 
			if(pDoc->ChatPrivilege==_T("文本") || pDoc->ChatPrivilege==_T("全部")) 
			{ 
				mg.GetAt (0,str); 
				pDoc->AppendAndDispOutputBarInfo(str); 
			} 
			break; 
 
		case ChatClear: 
			if(pDoc->ChatPrivilege==_T("白板") || pDoc->ChatPrivilege==_T("全部")) 
			{ 
				pDoc->csDrawInfo.Lock (); 
				while(!pDoc->drawList.IsEmpty ()) delete pDoc->drawList.RemoveHead(); 
				pDoc->pView->Invalidate (); 
				pDoc->csDrawInfo.Unlock(); 
			} 
			break; 
 
		case ChatSendFileQuery: 
			pDoc->ProcessSendFileQuery(sIP,mg); 
			break; 
 
		case ChatSendFileOk: 
			pDoc->BeginTransmitFile(); 
			pDoc->AppendAndDispOutputBarInfo(_T("开始发送文件")); 
			break; 
 
		case ChatSendFileNo: 
			pDoc->TransmitFile.Close (); 
			pDoc->CanTransmitFile=TRUE; 
			pDoc->AppendAndDispOutputBarInfo(_T("对方拒绝接收")); 
			break; 
 
		case ChatNextFileBlock: 
			pDoc->BeginTransmitFile(); 
			break; 
 
		case ChatSendFileData: 
			pDoc->BeginReceiveFile(mg); 
			break; 
 
		case ChatSendFileEnd: 
			pDoc->ReceiveFile.Close (); 
			if(pDoc->TotalReceiveLength==pDoc->FileHaveReceiveLength) 
			{ 
				::MessageBox(pMainWnd->GetSafeHwnd(),_T("已成功接收"),_T("信息"),MB_OK); 
				mg.Clear (); 
				mg.SetId (ChatReceiveFileOk); 
				if(!pDoc->SendMsg (sClient,mg)) pDoc->PrecessSendFileError(ChatReceiveFileOk); 
			} 
			else ::MessageBox(pMainWnd->GetSafeHwnd(),_T("文件传送失败"),_T("信息"),MB_OK); 
			pDoc->CanTransmitFile=TRUE; 
			break; 
 
		case ChatReceiveFileOk: 
			::MessageBox(pMainWnd->GetSafeHwnd(),_T("已成功发送"),_T("信息"),MB_OK); 
			break; 
 
		case ChatNextUpdateBlock:			 
			mg.Clear (); 
			if(pDoc->finishLen==pDoc->totalDrawLen) 
			{ 
				mg.SetId (ChatUpdateEnd); 
				pDoc->SendMsgToAll(mg); 
				pDoc->AllDrawFile.Close (); 
				break; 
			} 
			else mg.SetId (ChatUpdateData); 
			{ 
				BYTE buf[FILEBLOCKSIZE]; 
				ULONG len=pDoc->AllDrawFile.Read (buf,FILEBLOCKSIZE); 
				mg.SetAt (0,len); 
				mg.SetAt (1,buf,len); 
				pDoc->finishLen+=len; 
				pDoc->SendMsgToAll(mg);				 
			} 
			break; 
 
		case ChatCCurve: case ChatCLine: case ChatCText: case ChatCRectangle: case ChatCEllipse: 
			if(pDoc->ChatPrivilege==_T("白板") || pDoc->ChatPrivilege==_T("全部")) 
			{ 
				CDraw* pdw=pDoc->CNDKMessageToCDraw(mg); 
				if(pdw!=NULL) pDoc->AddToTailAndDraw(pdw); 
			} 
			break; 
		} 
	} 
 
} 
void CmischatDoc::CProcessRecvData(char * pData,unsigned long DataLength,BOOL hint) 
{ 
	CString str; 
	if(pData==NULL) 
	{ 
		pDoc->OnClientStop(); 
		return; 
	} 
	else 
	{ 
		if(hint){//WriteLogString发来的数据:连接、断开、SOCKET函数调用错误 
			str=pData; 
			pDoc->AppendAndDispOutputBarInfo(str); 
			return; 
		} 
		CNDKMessage mg; 
		pDoc->PCharToCNDKMessage(mg,pData,DataLength); 
		switch(mg.GetId ()) 
		{ 
		case ChatUserOnline: 
			pDoc->csAllIPList .Lock (); 
			pDoc->ReceiveUserList(mg); 
			pMainWnd->SendMessage (WM_REFRESHIPBAR); 
			pDoc->csAllIPList .Unlock (); 
			break; 
		case ChatText: 
			mg.GetAt (0,str); 
			pDoc->AppendAndDispOutputBarInfo(str); 
			break; 
 
		case ChatClear: 
			pDoc->csDrawInfo.Lock (); 
			while(!pDoc->drawList.IsEmpty ()) delete pDoc->drawList.RemoveHead(); 
			pDoc->pView->Invalidate (); 
			pDoc->csDrawInfo.Unlock(); 
			break; 
 
		case ChatSendFileQuery: 
			pDoc->ProcessSendFileQuery(mg); 
			break; 
 
		case ChatSendFileOk: 
			pDoc->BeginTransmitFile(); 
			pDoc->AppendAndDispOutputBarInfo(_T("开始发送文件")); 
			break; 
 
		case ChatSendFileNo: 
			pDoc->TransmitFile.Close (); 
			pDoc->CanTransmitFile=TRUE; 
			pDoc->AppendAndDispOutputBarInfo(_T("对方拒绝接收")); 
			break; 
 
		case ChatNextFileBlock: 
			pDoc->BeginTransmitFile(); 
			break; 
 
		case ChatSendFileData: 
			pDoc->BeginReceiveFile(mg); 
			break; 
 
		case ChatSendFileEnd: 
			pDoc->ReceiveFile.Close (); 
			if(pDoc->TotalReceiveLength==pDoc->FileHaveReceiveLength) 
			{ 
				::MessageBox(pMainWnd->GetSafeHwnd(),_T("已成功接收"),_T("信息"),MB_OK); 
				mg.Clear (); 
				mg.SetId (ChatReceiveFileOk); 
				if(!pDoc->SendMsg (mg)) pDoc->PrecessSendFileError(ChatReceiveFileOk); 
			} 
			else ::MessageBox(pMainWnd->GetSafeHwnd(),_T("文件传送失败"),_T("信息"),MB_OK); 
			pDoc->CanTransmitFile=TRUE; 
			break; 
 
		case ChatReceiveFileOk: 
			::MessageBox(pMainWnd->GetSafeHwnd(),_T("已成功发送"),_T("信息"),MB_OK); 
			break; 
 
		case ChatUpdate: 
			if(pDoc->AllDrawFile.m_hFile != CFile::hFileNull) pDoc->AllDrawFile.Close (); 
			pDoc->AllDrawFile.Open(pDoc->strTempFileC, CFile::modeWrite|CFile::modeCreate|CFile::typeBinary); 
			mg.GetAt (0,pDoc->totalDrawLen ); 
			pDoc->finishLen =0; 
			mg.Clear (); 
			mg.SetId (ChatNextUpdateBlock); 
			pDoc->SendMsg(mg); 
			break; 
 
		case ChatUpdateData: 
			{ 
				BYTE buf[FILEBLOCKSIZE]; 
				ULONG len; 
				mg.GetAt (0,len); 
				mg.GetAt (1,buf,len); 
				pDoc->finishLen+=len; 
				pDoc->AllDrawFile.Write (buf,len); 
				mg.Clear (); 
				mg.SetId (ChatNextUpdateBlock); 
				pDoc->SendMsg(mg); 
			} 
			break; 
 
		case ChatUpdateEnd: 
			pDoc->AllDrawFile.Close (); 
			if(pDoc->finishLen==pDoc->totalDrawLen) 
			{ 
				CFileException  e; 
				try{ 
					pDoc->AllDrawFile.Open(pDoc->strTempFileC, CFile::modeRead|CFile::typeBinary,&e); 
					CArchive ar(&pDoc->AllDrawFile,CArchive::load ); 
					pDoc->csDrawInfo.Lock (); 
					while(!pDoc->drawList.IsEmpty ()) delete pDoc->drawList.RemoveHead(); 
					pDoc->drawList.Serialize (ar); 
					ar.Close (); 
					pDoc->csDrawInfo.Unlock(); 
					pDoc->AllDrawFile.Close (); 
				} 
				catch(CFileException * e){ 
					e->ReportError(); 
					e->Delete(); 
				} 
			} 
			pDoc->pView->Invalidate (); 
			break; 
 
		case ChatCCurve: case ChatCLine: case ChatCText: case ChatCRectangle: case ChatCEllipse: 
			CDraw* pdw=pDoc->CNDKMessageToCDraw(mg); 
			if(pdw!=NULL) pDoc->AddToTailAndDraw(pdw); 
			break; 
		} 
	} 
 
} 
 
int CmischatDoc::ConditionFunc( 
								IN LPWSABUF lpCallerId, 
								IN LPWSABUF lpCallerData, 
								IN OUT LPQOS lpSQOS, 
								IN OUT LPQOS lpGQOS, 
								IN LPWSABUF lpCalleeId, 
								OUT LPWSABUF lpCalleeData, 
								OUT GROUP FAR *g, 
								IN DWORD_PTR dwCallbackData 
								) 
{ 
	sockaddr addr; 
	char buf[50]; 
	DWORD len=50; 
	memcpy(&addr,lpCallerId->buf,lpCallerId->len ); 
	if(::WSAAddressToString (&addr,sizeof(sockaddr),NULL,buf,&len)==0) 
	{ 
		CString str=buf; 
		int index=str.Find (':'); 
 
		bool found=false; 
		POSITION ps=pDoc->DenyIPList.GetHeadPosition (); 
		while(ps) 
		{ 
			found=pDoc->DenyIPList.GetNext (ps).Find (str.Left(index))!=-1; 
			if(found) break; 
		} 
		if(!found && pDoc->AllIPList.GetCount ()m_ConnectMax) 
		return CF_ACCEPT; 
	} 
	::Sleep (5000); 
	return CF_REJECT; 
} 
 
void CmischatDoc::OnServerStart() 
{ 
	// TODO: 在此添加命令处理程序代码 
	CString str; 
	if(server.Init (SProcessRecvData,ConditionFunc,m_ServerPort)) 
	{ 
		str.Format (_T("服务器启动成功  本地IP:%s  监听端口:%d"),server.GetLocalIpAdd (),m_ServerPort); 
		CanTransmitFile=TRUE; 
	} 
	else str=_T("服务器启动失败"); 
	AppendAndDispOutputBarInfo(str); 
 
	LPTSTR p=str.LockBuffer (); 
	pMainWnd->SendMessage (WM_REFRESHCAPTIONBAR,0,(LPARAM)p); 
	str.UnlockBuffer (); 
} 
 
void CmischatDoc::OnServerStop() 
{ 
	// TODO: 在此添加命令处理程序代码 
	CString str; 
	str=_T("服务器已关闭"); 
	server.UnInit (); 
	if(TransmitFile.m_hFile != CFile::hFileNull) TransmitFile.Close (); 
	if(ReceiveFile.m_hFile != CFile::hFileNull) ReceiveFile.Close (); 
	if(AllDrawFile.m_hFile != CFile::hFileNull) AllDrawFile.Close (); 
	CanTransmitFile=FALSE; 
	AppendAndDispOutputBarInfo(str); 
 
	LPTSTR p=str.LockBuffer (); 
	pMainWnd->SendMessage (WM_REFRESHCAPTIONBAR,0,(LPARAM)p); 
	str.UnlockBuffer (); 
} 
 
void CmischatDoc::OnClientStart() 
{ 
	// TODO: 在此添加命令处理程序代码 
	CString str; 
	if(client.Init (CProcessRecvData,m_strIP,m_ClientPort)) 
	{ 
		str.Format (_T("连接服务器成功  本地IP:%s 服务器IP:%s  连接端口:%d"),client.GetLocalIP(),m_strIP,m_ClientPort); 
		CNDKMessage mg; 
		mg.SetId (ChatUserJoin); 
		mg.Add (strName); 
		SendMsg(mg); 
		CanTransmitFile=TRUE; 
	} 
	else str=_T("连接服务器失败"); 
	AppendAndDispOutputBarInfo(str); 
 
	LPTSTR p=str.LockBuffer (); 
	pMainWnd->SendMessage (WM_REFRESHCAPTIONBAR,0,(LPARAM)p); 
	str.UnlockBuffer (); 
} 
 
void CmischatDoc::OnClientStop() 
{ 
	// TODO: 在此添加命令处理程序代码 
	CString str; 
	str=_T("已断开与服务器的连接"); 
	client.UnInit (); 
	if(TransmitFile.m_hFile != CFile::hFileNull) TransmitFile.Close (); 
	if(ReceiveFile.m_hFile != CFile::hFileNull) ReceiveFile.Close (); 
	if(AllDrawFile.m_hFile != CFile::hFileNull) AllDrawFile.Close (); 
	CanTransmitFile=FALSE; 
	AppendAndDispOutputBarInfo(str); 
	AllIPList.RemoveAll (); 
	pMainWnd->SendMessage(WM_REFRESHIPBAR); 
 
	LPTSTR p=str.LockBuffer (); 
	pMainWnd->SendMessage (WM_REFRESHCAPTIONBAR,0,(LPARAM)p); 
	str.UnlockBuffer (); 
} 
 
void CmischatDoc::OnUpdateClientStop(CCmdUI *pCmdUI) 
{ 
	// TODO: 在此添加命令更新用户界面处理程序代码 
	pCmdUI->Enable(client.isStart()); 
} 
 
void CmischatDoc::OnUpdateClientStart(CCmdUI *pCmdUI) 
{ 
	// TODO: 在此添加命令更新用户界面处理程序代码 
	pCmdUI->SetCheck (client.isStart()); 
	pCmdUI->Enable(!client.isStart() && !server.isStart()); 
} 
 
void CmischatDoc::OnUpdateServerStop(CCmdUI *pCmdUI) 
{ 
	// TODO: 在此添加命令更新用户界面处理程序代码 
	pCmdUI->Enable(server.isStart()); 
} 
 
void CmischatDoc::OnUpdateServerStart(CCmdUI *pCmdUI) 
{ 
	// TODO: 在此添加命令更新用户界面处理程序代码 
	pCmdUI->SetCheck (server.isStart()); 
	pCmdUI->Enable(!client.isStart() && !server.isStart()); 
 
} 
 
char* CmischatDoc::CNDKMessageToPChar(CNDKMessage& mg,ULONG& len) 
{ 
	char* pchar=NULL; 
	//if(mg.GetNbElements ()==0) return pchar; 
 
	CMemFile mf; 
	CArchive ar(&mf,CArchive::store); 
	mg.Serialize (ar); 
	ar.Close (); 
	len=(ULONG)mf.GetLength (); 
	pchar=(char*)mf.Detach (); 
	return pchar; 
} 
 
void CmischatDoc::PCharToCNDKMessage(CNDKMessage& mg,char* pchar,ULONG len) 
{ 
	if(pchar==NULL || len==0) return; 
	CMemFile mf; 
	mf.Attach ((BYTE*)pchar,len); 
	CArchive ar(&mf,CArchive::load); 
	mg.Serialize (ar); 
	ar.Close (); 
	mf.Detach (); 
} 
 
void  CmischatDoc::CDrawToCNDKMessage(CNDKMessage& mg,CDraw* pdw) 
{ 
	if(!pdw->IsKindOf (RUNTIME_CLASS(CDraw))) return; 
	if(pdw->IsKindOf (RUNTIME_CLASS(CCurve))) mg.SetId (ChatCCurve); 
	if(pdw->IsKindOf (RUNTIME_CLASS(CLine))) mg.SetId (ChatCLine); 
	if(pdw->IsKindOf (RUNTIME_CLASS(CText))) mg.SetId (ChatCText); 
	if(pdw->IsKindOf (RUNTIME_CLASS(CRectangle))) mg.SetId (ChatCRectangle); 
	if(pdw->IsKindOf (RUNTIME_CLASS(CEllipse))) mg.SetId (ChatCEllipse); 
 
	CMemFile mf; 
	CArchive ar(&mf,CArchive::store); 
	pdw->Serialize (ar); 
	ar.Close (); 
	ULONG len=(ULONG)mf.GetLength (); 
	BYTE* p=mf.Detach (); 
	mg.Add (len); 
	mg.Add (p,(UINT)len); 
	delete p; 
} 
 
CDraw* CmischatDoc::CNDKMessageToCDraw(CNDKMessage& mg) 
{ 
	CDraw * pdw=NULL; 
	ULONG len; 
	if(mg.GetNbElements ()==0) return pdw; 
	switch(mg.GetId ()) 
	{ 
	case ChatCCurve: 
		pdw=new CCurve(); 
		break; 
	case ChatCLine: 
		pdw=new CLine(); 
		break; 
	case ChatCText: 
		pdw=new CText(); 
		break; 
	case ChatCRectangle: 
		pdw=new CRectangle(); 
		break; 
	case ChatCEllipse: 
		pdw=new CEllipse(); 
		break; 
	} 
	if(pdw!=NULL) 
	{ 
		mg.GetAt (0,len); 
		BYTE* p=new BYTE[len]; 
		mg.GetAt (1,p,(UINT)len); 
		CMemFile mf; 
		mf.Attach (p,(UINT)len); 
		CArchive ar(&mf,CArchive::load); 
		pdw->Serialize (ar); 
		ar.Close (); 
		mf.Detach (); 
		delete[] p; 
	} 
	return pdw; 
} 
 
bool CmischatDoc::SendMsg(LPCTSTR TargetIp,CNDKMessage& mg) 
{ 
	unsigned long tIP=inet_addr(TargetIp); 
	SOCKET sClient; 
	if(ip_socket_map.Lookup (tIP,sClient)==0) return false; 
 
	char* pch; 
	ULONG len; 
	pch=CNDKMessageToPChar(mg,len); 
	bool result=false; 
	if(pch!=NULL){ 
		result=server.SendMsg(sClient,pch,len); 
		delete pch; 
	} 
	return result; 
} 
 
bool CmischatDoc::SendMsg(SOCKET sClient,CNDKMessage& mg) 
{ 
	char* pch; 
	ULONG len; 
	pch=CNDKMessageToPChar(mg,len); 
	bool result=false; 
	if(pch!=NULL){ 
		result=server.SendMsg(sClient,pch,len); 
		delete pch; 
	} 
	return result; 
} 
 
bool CmischatDoc::SendMsgToAll(CNDKMessage& mg) 
{ 
	char* pch; 
	ULONG len; 
	pch=CNDKMessageToPChar(mg,len); 
	bool result=false; 
	if(pch!=NULL){ 
		result=server.SendMsgToAll (pch,len); 
		delete pch; 
	} 
	return result; 
} 
 
bool CmischatDoc::SendMsgToOther(LPCTSTR ExceptIp,CNDKMessage& mg) 
{ 
	unsigned long tIP=inet_addr(ExceptIp); 
	SOCKET sClient; 
	if(ip_socket_map.Lookup (tIP,sClient)==0) return false; 
 
	char* pch; 
	ULONG len; 
	pch=CNDKMessageToPChar(mg,len); 
	bool result=false; 
	if(pch!=NULL){ 
		result=server.SendMsgToOther (sClient,pch,len); 
		delete pch; 
	} 
	return result; 
 
} 
 
bool CmischatDoc::SendMsgToOther(SOCKET ExceptSocket,CNDKMessage& mg) 
{ 
	char* pch; 
	ULONG len; 
	pch=CNDKMessageToPChar(mg,len); 
	bool result=false; 
	if(pch!=NULL){ 
		result=server.SendMsgToOther (ExceptSocket,pch,len); 
		delete pch; 
	} 
	return result;	 
 
} 
 
bool CmischatDoc::SendMsg(CNDKMessage& mg) 
{ 
	char* pch; 
	ULONG len; 
	pch=CNDKMessageToPChar(mg,len); 
	bool result=false; 
	if(pch!=NULL){ 
		result=client.SendMsg(pch,len); 
		delete pch; 
	} 
	return result;	 
} 
 
bool CmischatDoc::SendMsgToAll(CDraw* pdw) 
{ 
	CNDKMessage mg; 
	if(pdw!=NULL) 
	{ 
		CDrawToCNDKMessage(mg,pdw); 
	} 
	else 
	{ 
		mg.SetId (ChatClear); 
		CString str="SERVERCLEAR"; 
		mg.Add (str); 
	} 
	return SendMsgToAll(mg); 
} 
 
bool CmischatDoc::SendMsg(CDraw* pdw) 
{ 
	CNDKMessage mg; 
	if(pdw!=NULL) 
	{ 
		CDrawToCNDKMessage(mg,pdw); 
	} 
	else 
	{ 
		mg.SetId (ChatClear); 
		CString str="CLIENTCLEAR"; 
		mg.Add (str); 
	} 
	return SendMsg(mg); 
} 
 
void CmischatDoc::AddToIPList(CStringList& list,unsigned long sIP,CString& strName) 
{ 
	CString str; 
	str.Format ("%d.%d.%d.%d",LOBYTE(LOWORD(sIP)),HIBYTE(LOWORD(sIP)),LOBYTE(HIWORD(sIP)),HIBYTE(HIWORD(sIP))); 
	list.AddTail (str+"#"+strName); 
} 
 
void CmischatDoc::AddToIPList(CStringList& list,CString& sIP,CString& strName) 
{ 
	list.AddTail (sIP+"#"+strName); 
} 
 
void CmischatDoc::RemoveFromIPList(CStringList& list,unsigned long sIP) 
{ 
 
	POSITION ps,psTemp; 
	ps=list.GetHeadPosition (); 
	CString str; 
	str.Format ("%d.%d.%d.%d",LOBYTE(LOWORD(sIP)),HIBYTE(LOWORD(sIP)),LOBYTE(HIWORD(sIP)),HIBYTE(HIWORD(sIP))); 
 
	while(ps!=NULL) 
	{ 
		psTemp=ps; 
		if(list.GetNext (ps).Find (str)!=-1){ 
			list.RemoveAt (psTemp); 
			break; 
		} 
	} 
 
} 
 
void CmischatDoc::RemoveFromIPList(CStringList& list,CString& sIP) 
{ 
	POSITION ps,psTemp; 
	ps=list.GetHeadPosition (); 
 
	while(ps!=NULL) 
	{ 
		psTemp=ps; 
		if(list.GetNext (ps).Find (sIP)!=-1){ 
			list.RemoveAt (psTemp); 
			break; 
		} 
	} 
} 
 
bool CmischatDoc::SendUserList() 
{ 
	CNDKMessage mg; 
	mg.SetId (ChatUserOnline); 
	POSITION ps; 
	ps=AllIPList.GetHeadPosition (); 
	while(ps) 
	{ 
		mg.Add (AllIPList.GetNext (ps)); 
	} 
	return SendMsgToAll(mg); 
} 
//客户机端用 
void CmischatDoc::ReceiveUserList(CNDKMessage& mg) 
{ 
	CString str; 
	AllIPList.RemoveAll (); 
 
	for(int i=0;iAddToIPList(pDoc->AllIPList,sIP,str); 
	ip_socket_map.SetAt (sIP,socket); 
	pDoc->SendUserList(); 
	pMainWnd->SendMessage (WM_REFRESHIPBAR); 
} 
void CmischatDoc::OnCloseDocument() 
{ 
	// TODO: 在此添加专用代码和/或调用基类 
	SaveIniFile(strModulePath+"chat.env"); 
	if(TransmitFile.m_hFile != CFile::hFileNull) TransmitFile.Close (); 
	if(ReceiveFile.m_hFile != CFile::hFileNull) ReceiveFile.Close (); 
	if(AllDrawFile.m_hFile != CFile::hFileNull) AllDrawFile.Close (); 
 
	CDocument::OnCloseDocument(); 
} 
void CmischatDoc::PreTransmitFile(CString strIP,CString strFile) 
{ 
	try{ 
		if(TransmitFile.Open(strFile, CFile::modeRead|CFile::typeBinary)) 
		{ 
			CNDKMessage mg; 
			strFileName=strFile; 
			strIPFile=strIP; 
 
			TotalFileLength=(ULONG)TransmitFile.GetLength (); 
			FileHaveTransmitLength=0; 
			mg.SetId (ChatSendFileQuery); 
			mg.Add (TransmitFile.GetFileName ()); 
			mg.Add (TotalFileLength); 
			if(SendMsg(strIP,mg)) CanTransmitFile=FALSE; 
			else PrecessSendFileError(ChatSendFileQuery); 
		} 
	} 
	catch (CFileException* pEx) 
	{ 
		// if an error occurs, just make a message box 
		pEx->ReportError(); 
		pEx->Delete(); 
	}	 
 
} 
 
void CmischatDoc::PreTransmitFile(CString strFile) 
{ 
	try{ 
		if(TransmitFile.Open(strFile, CFile::modeRead|CFile::typeBinary)) 
		{ 
			CNDKMessage mg; 
			strFileName=strFile; 
			strIPFile=""; 
 
			TotalFileLength=(ULONG)TransmitFile.GetLength (); 
			FileHaveTransmitLength=0; 
			mg.SetId (ChatSendFileQuery); 
			mg.Add (TransmitFile.GetFileName ()); 
			mg.Add (TotalFileLength); 
			if(SendMsg(mg)) CanTransmitFile=FALSE; 
			else PrecessSendFileError(ChatSendFileQuery); 
		} 
	} 
	catch (CFileException* pEx) 
	{ 
		// if an error occurs, just make a message box 
		pEx->ReportError(); 
		pEx->Delete(); 
	}	 
 
} 
 
void CmischatDoc::BeginTransmitFile() 
{ 
	bool rel=false; 
	CNDKMessage mg; 
	if(FileHaveTransmitLength==TotalFileLength) 
	{ 
		TransmitFile.Close (); 
		CanTransmitFile=TRUE; 
		mg.SetId (ChatSendFileEnd); 
		TRACE("ChatSendFileEnd\n"); 
		goto label; 
	} 
	ULONG len; 
	mg.SetId (ChatSendFileData); 
	BYTE buf[FILEBLOCKSIZE]; 
	len=TransmitFile.Read (buf,FILEBLOCKSIZE); 
	FileHaveTransmitLength+=len; 
	mg.Add (len); 
	mg.Add (buf,len); 
	TRACE("ChatSendFileData\n"); 
label: 
	if(server.isStart()) rel=SendMsg(strIPFile,mg); 
	if(client.isStart()) rel=SendMsg(mg); 
	if(!rel) PrecessSendFileError(mg.GetId ()); 
	TRACE("TotalFileLength=%d FileHaveTransmitLength=%d\n",TotalFileLength,FileHaveTransmitLength); 
	pMainWnd->SendMessage (WM_PANEGROGRESSBAR,0,(LPARAM)(FileHaveTransmitLength*100/TotalFileLength)); 
} 
 
void CmischatDoc::BeginReceiveFile(CNDKMessage& mg) 
{ 
	bool rel=false; 
	BYTE buf[FILEBLOCKSIZE]; 
	ULONG len; 
	mg.GetAt (0,len); 
	mg.GetAt (1,buf,len); 
	ReceiveFile.Write (buf,len); 
	FileHaveReceiveLength+=len; 
	mg.Clear (); 
	mg.SetId (ChatNextFileBlock); 
	if(server.isStart()) {rel=SendMsg(strIPFile,mg);TRACE("BeginReceiveFile->ChatNextFileBlock\n");} 
	if(client.isStart()) {rel=SendMsg(mg);TRACE("BeginReceiveFile->ChatNextFileBlock\n");} 
	if(!rel) PrecessSendFileError(ChatNextFileBlock); 
	TRACE("TotalReceiveLength=%d FileHaveReceiveLength=%d\n",TotalReceiveLength,FileHaveReceiveLength); 
	pMainWnd->SendMessage (WM_PANEGROGRESSBAR,0,(LPARAM)(FileHaveReceiveLength*100/TotalReceiveLength)); 
} 
 
void CmischatDoc::PrecessSendFileError(long error_id) 
{ 
	switch(error_id) 
	{ 
	case ChatSendFileOk: 
		TRACE("Error Send ChatSendFileOk\n"); 
		ReceiveFile.Close (); 
		break; 
	case ChatSendFileNo: 
		TRACE("Error Send ChatSendFileNo\n"); 
		break; 
	case ChatNextFileBlock: 
		ReceiveFile.Close (); 
		TRACE("Error Send ChatNextFileBlock\n"); 
		break; 
	case ChatSendFileData: 
		TransmitFile.Close (); 
		TRACE("Error Send ChatSendFileData\n"); 
		break; 
	case ChatSendFileQuery: 
		TransmitFile.Close (); 
		TRACE("Error Send ChatSendFileQuery\n"); 
		break; 
	case ChatSendFileEnd: 
		TransmitFile.Close (); 
		TRACE("Error Send ChatSendFileEnd\n"); 
		break; 
	case ChatReceiveFileOk: 
		TRACE("Error Send ChatReceiveFileOk\n"); 
		break; 
	default: 
		TRACE("Error Send %d\n" ,error_id); 
	}	 
	CanTransmitFile=TRUE; 
	::MessageBox(pMainWnd->GetSafeHwnd(),_T("文件传输过程中发生错误,请稍后重试"),_T("信息"),MB_OK); 
} 
 
void CmischatDoc::ProcessSendFileQuery(CNDKMessage& mg) 
{ 
	CString strFile,str; 
	ULONG ul; 
 
	mg.GetAt (0,strFile); 
	mg.GetAt (1,ul); 
	mg.Clear (); 
	str.Format (_T("服务器给你发送文件:%s 长度为:%d 要接收吗?"),strFile,ul); 
	if(CanTransmitFile && MessageBox(pMainWnd->GetSafeHwnd(),str,_T("信息"),MB_ICONINFORMATION|MB_YESNO)==IDYES) 
	{ 
		CFileDialog dlg(FALSE,NULL,strFile,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER); 
		if(dlg.DoModal ()==IDOK) 
		{ 
			TotalReceiveLength=ul; 
			FileHaveReceiveLength=0; 
			try{ 
				if(ReceiveFile.Open(dlg.GetPathName(), CFile::modeCreate| CFile::modeWrite|CFile::typeBinary)) 
				{ 
					mg.SetId (ChatSendFileOk); 
					if(SendMsg(mg)) {CanTransmitFile=FALSE;TRACE("ProcessSendFileQuery->ChatSendFileOk\n");} 
					else PrecessSendFileError(ChatSendFileOk); 
				} 
			} 
			catch (CFileException* pEx) 
			{ 
				// if an error occurs, just make a message box 
				pEx->ReportError(); 
				pEx->Delete(); 
			}	 
		} 
	} 
	else 
	{ 
		mg.SetId (ChatSendFileNo); 
		if(SendMsg(mg)) TRACE("ProcessSendFileQuery->ChatSendFileNo\n"); 
		else PrecessSendFileError(ChatSendFileNo); 
	} 
} 
 
void CmischatDoc::ProcessSendFileQuery(unsigned long sIP,CNDKMessage& mg) 
{ 
	CString strFile,strIP,str; 
	ULONG ul; 
 
	strIP.Format ("%d.%d.%d.%d",LOBYTE(LOWORD(sIP)),HIBYTE(LOWORD(sIP)),LOBYTE(HIWORD(sIP)),HIBYTE(HIWORD(sIP))); 
	mg.GetAt (0,strFile); 
	mg.GetAt (1,ul); 
	mg.Clear (); 
	str.Format (_T("%s给你发送文件:%s 长度为:%d 要接收吗?"),strIP,strFile,ul); 
	if(CanTransmitFile && MessageBox(pMainWnd->GetSafeHwnd(),str,_T("信息"),MB_ICONINFORMATION|MB_YESNO)==IDYES) 
	{ 
		CFileDialog dlg(FALSE,NULL,strFile,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER); 
		if(dlg.DoModal ()==IDOK) 
		{ 
			TotalReceiveLength=ul; 
			FileHaveReceiveLength=0; 
			try{ 
				if(ReceiveFile.Open(dlg.GetPathName(), CFile::modeCreate| CFile::modeWrite|CFile::typeBinary)) 
				{ 
					mg.SetId (ChatSendFileOk); 
					if(SendMsg(strIP,mg)) {CanTransmitFile=FALSE;TRACE("ProcessSendFileQuery->ChatSendFileOk\n");} 
					else PrecessSendFileError(ChatSendFileOk); 
				} 
			} 
			catch (CFileException* pEx) 
			{ 
				// if an error occurs, just make a message box 
				pEx->ReportError(); 
				pEx->Delete(); 
			}	 
		} 
	} 
	else 
	{ 
		mg.SetId (ChatSendFileNo); 
		if(SendMsg(strIP,mg)) TRACE("ProcessSendFileQuery->ChatSendFileNo\n"); 
		else PrecessSendFileError(ChatSendFileNo);		 
	} 
} 
 
void CmischatDoc::UpdateAllDrawData() 
{ 
	CFileException e; 
	if(AllDrawFile.m_hFile != CFile::hFileNull) AllDrawFile.Close (); 
	try{   
		AllDrawFile.Open(strTempFileS, CFile::modeWrite|CFile::modeCreate|CFile::typeBinary, &e); 
		CArchive ar(&AllDrawFile, CArchive::store); 
		drawList.Serialize (ar); 
		ar.Close(); 
		AllDrawFile.Close (); 
		AllDrawFile.Open(strTempFileS, CFile::modeRead|CFile::typeBinary); 
	} 
	catch(CFileException * e){ 
		e->ReportError(); 
		e->Delete(); 
	} 
 
	totalDrawLen=(ULONG)AllDrawFile.GetLength (); 
	finishLen=0; 
 
	CNDKMessage mg;	 
	mg.SetId (ChatUpdate); 
	mg.Add (totalDrawLen); 
	SendMsgToAll(mg); 
}