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

📄 lancommuniondlg.cpp

📁 局域网实现聊天,并传输文件,功能较齐全,可添加用户!欢迎大家下载!
💻 CPP
📖 第 1 页 / 共 3 页
字号:
			if(SOCKET_ERROR==result)
			{
				AfxMessageBox("发送返回在线确认消息出错。");
				continue;
			}
		}
		else
		{
			if(buf[0]=='E'&&buf[1]=='X'&&buf[2]=='I'&&buf[3]=='T')//下线消息。
			{
				int		iIndex2=4;
				int		n2=0;
				while(0!=buf[iIndex2])
					bufHost[n2++]=buf[iIndex2++];
				del=true;
				//AfxMessageBox(bufHost);
			}
			else
				strcpy(bufHost,buf);	//子网内返回的在线用户确认消息。
		}
		
		//查找指定IP 地址用户是否存在。
		bItemExist=false;
		nListItemDelete=-1;
		nListItemCount=pCLAN->m_list.GetItemCount(	);
		if(0!=nListItemCount)
		{
			for(int	i=0;i<nListItemCount;i++)
			{
				strFind.Empty(	);
				strFind=pCLAN->m_list.GetItemText(i,1);
				if(strFind==ip)
				{
					nListItemDelete=i;
					bItemExist=true;
					break;
				}
			}
		}
		if(!bItemExist)//列表中无此用户信息。
		{
			if(!del)		//不是下线通知消息,添加用户信息。
			{
				pCLAN->m_list.InsertItem(nListItemCount,bufHost);
				pCLAN->m_list.SetItemText(nListItemCount,1,ip);
			}
		}
		else			//列表中有此用户信息且为下线通知消息。
		{
			if(del)		//下线通知消息,删除此用户信息。
			{
				pCLAN->m_list.DeleteItem(nListItemDelete);
			}
		}
		//////////////////////////////////////////////////
		
	}

	return	0;
}
/////////////////////////////////////////////////////////////////////////////

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

/////////////////////////////////////////////////////////////////////////////
// CLANCommunionDlg dialog

CLANCommunionDlg::CLANCommunionDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CLANCommunionDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CLANCommunionDlg)
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	m_sockChat=INVALID_SOCKET;
	m_sockBRecv=INVALID_SOCKET;
	m_sockBSend=INVALID_SOCKET;

	//////////////////////////////////
	ReadUserInfo();	
}

CLANCommunionDlg::~CLANCommunionDlg(		)
{
}

void CLANCommunionDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CLANCommunionDlg)
	DDX_Control(pDX, IDC_LIST_USER, m_list);
	DDX_Control(pDX, IDC_EDIT_SANDCHAT, m_editSendChat);
	DDX_Control(pDX, IDC_BUTTON_CLEAR, m_Clear);
	DDX_Control(pDX, IDC_BUTTON_QUIT, m_Quit);
	DDX_Control(pDX, IDC_BUTTON_SENDCHAT, m_SendChat);
	DDX_Control(pDX, IDC_BUTTON_SENDFILE, m_SendFile);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CLANCommunionDlg, CDialog)
	//{{AFX_MSG_MAP(CLANCommunionDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON_SENDFILE, OnButtonSendFile)
	ON_BN_CLICKED(IDC_BUTTON_SENDCHAT, OnButtonSendChat)
	ON_BN_CLICKED(IDC_BUTTON_CLEAR, OnButtonClear)
	ON_BN_CLICKED(IDC_BUTTON_QUIT, OnButtonQuit)
	ON_WM_CLOSE()
	ON_COMMAND(IDM_ADD_USER, OnAddUser)
	ON_COMMAND(IDM_USAGE, OnUsage)
	ON_BN_CLICKED(IDC_BTN_FLUSH, OnBtnFlush)
	ON_EN_MAXTEXT(IDC_EDIT_RECEIVE, OnMaxtextEditReceive)
	ON_EN_MAXTEXT(IDC_EDIT_SANDCHAT, OnMaxtextEditSandchat)
	ON_WM_CTLCOLOR()
	ON_WM_SIZE()
	ON_COMMAND(IDM_POPUP_QUIT, OnPopupQuit)
	ON_COMMAND(IDM_POPUP_ADDUSER, OnPopupAdduser)
	ON_COMMAND(IDM_POPUP_ABOUT, OnPopupAbout)
	//}}AFX_MSG_MAP
	ON_WM_DROPFILES(	)
	ON_MESSAGE(UM_NOTIFY,OnNotifyIcon)
	ON_MESSAGE(UM_CREATE_TRANSPORTDLG,OnCreateTransportInfoDlg)
	ON_MESSAGE(UM_DELETE_DLG,OnDeleteDlg)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CLANCommunionDlg message handlers

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

	// 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
	//////////////////////////////////////
	
	
	//设置CListCtrl属性,使其每次选择一行。
//	m_list.SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE,0,(LPARAM)LVS_EX_FULLROWSELECT);
	
	//设置CListCtrl属性,使其绘制网格。
	m_list.SetExtendedStyle(m_list.GetExtendedStyle()|LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT);
//	m_list.SetExtendedStyle(m_list.GetExtendedStyle()|LVS_SHOWSELALWAYS );
	
    // Initialize the LVCOLUMN structure.
    // The mask specifies that the format, width, text, and subitem
    // members of the structure are valid. 
	
	m_list.InsertColumn(0,_T("用户名"),LVCFMT_LEFT,100);
	m_list.InsertColumn(1,_T("IP地址"),LVCFMT_LEFT,150);
	InitBSocket(	);//初始化广播套接字。
	FlushListBox();		//刷新在线用户列表,主要是发送 请求返回 用户是否在线消息,
						//从而获得在线的用户。
	//初始化各按钮显示状态。
	
	m_SendChat.EnableWindow(false);
	m_SendFile.EnableWindow(false);
	m_Clear.EnableWindow(false);

	////////////////////////////////////////////////
	///////////////////////////////////////////////
	//初始化聊天套接字、创建接收文件监听线程。
	InitChat(	);
	
	AfxBeginThread(ListenFileTransport,this);
	////////////////////////////////////////////////
	//让应用程序支持拖放文件操作。
	this->DragAcceptFiles();

	//初始化托盘结构体。
	//////////////////////////////////////////////////////////////////
	m_nid.cbSize=sizeof(NOTIFYICONDATA);
	m_nid.hIcon=::LoadIcon(AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDI_ICON_NOTIFY));
	m_nid.hWnd=m_hWnd;
	strcpy(m_nid.szTip,"NETCommunionTool  3.34版");
	m_nid.uCallbackMessage=UM_NOTIFY;
	m_nid.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP;
	m_nid.uID=IDR_MAINFRAME;

	if(!Shell_NotifyIcon(NIM_ADD,&m_nid))
	{
		MessageBox("建立托盘失败。");
		return	false;
	}
	/////////////////////////////////////////////////////////////////////
	return TRUE;  // return TRUE  unless you set the focus to a control
}

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

//////////////////////////////////////////////////////////////////////////////////////
//发送文件按钮消息响应函数。
void CLANCommunionDlg::OnButtonSendFile() 
{
	// TODO: Add your control notification handler code here
	CString		ip;
	if(!GetIPAddr(ip))
	{
		return	;
	}

	int			modal,nCount;
	CString		fileName;
	CFileDialog fdlg(true);
	modal=fdlg.DoModal(	);
	if(IDCANCEL==modal)	
	{
		return	; //用户取消发送。
	}

	SENDFILEPARAM*	p=new	SENDFILEPARAM;
	fileName=fdlg.GetFileName(	);
	p->pathName=fdlg.GetPathName(	);
	nCount=fileName.GetLength(	);
	memset(p->fileName,0,NAMELENGTH);
	for(int	i=0;i<nCount;i++)
	{
		p->fileName[i]=fileName.GetAt(i);
	}
	p->pCLAN=this;
	p->ip=ip;
	
	////////////////////////////////////////////////

	::AfxBeginThread(SendFileSingle,(LPVOID)p);
	return;
}


//初始化聊天用套接字。
void CLANCommunionDlg::InitChat(		)
{
	//创建服务器端聊天用套接字.
	int		errCode;
	m_sockChat=socket(AF_INET,SOCK_DGRAM,0);
	if(	INVALID_SOCKET==m_sockChat	)
	{
		MessageBox("聊天用套接字创建失败.");
		m_SendChat.EnableWindow(false);
		m_Clear.EnableWindow(false);
		return;
	}
	//把服务器端聊天用套接字绑定到端口 5208。
	SOCKADDR_IN		addrClient;
	memset(&addrClient,0,sizeof(SOCKADDR_IN));
	addrClient.sin_addr.S_un.S_addr	=htonl(	INADDR_ANY	);
	addrClient.sin_family				=AF_INET;
	addrClient.sin_port				=htons(	CHATPORT	);
	
	errCode=bind(m_sockChat,(SOCKADDR*)&addrClient,sizeof(SOCKADDR));
	if(	SOCKET_ERROR==errCode	)
	{
		MessageBox("服务器端聊天用套接字绑定失败。");
		m_SendChat.EnableWindow(false);
		m_Clear.EnableWindow(false);
		return;
	}
	//聊天套接字创建成功。
	//打开按钮。
	m_SendChat.EnableWindow(true);
	m_Clear.EnableWindow(true);
	CHAT*	p=new	(CHAT);
	p->sock=m_sockChat;
	AfxBeginThread(ChatReceive,(LPVOID)p);
	return	;
}

//发送聊天内容。
void CLANCommunionDlg::OnButtonSendChat() 
{
	// TODO: Add your control notification handler code here
	//目的方地址簇。
	SOCKADDR_IN		addrDest;
	int				len=sizeof(SOCKADDR);
	int				nListIndex,nListCount,err;
	char			send[1024],temp[800];
	bool			bChoosed;
	CString			ip;
	memset(send,0,1024);
	memset(temp,0,800);
	memset(&addrDest,0,sizeof(SOCKADDR_IN));
	
	//获取目的主机IP地址。
	
	bChoosed=false;
	nListIndex=-1;
	nListCount=m_list.GetItemCount();
	for(int i=0; i<nListCount; i++)
	{
		if( m_list.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED )
		{
			bChoosed=true;		//有已经选择的项。
			nListIndex=i;		//已经选择的项序号。
			m_list.SetItemState(i,LVIS_SELECTED,LVIS_SELECTED);
		}
	}
	if(!bChoosed)		//用户还没有选择。
	{
		AfxMessageBox("你还没有选择发送的目的用户呢,请选择后再重新发送。");
		return	;
	}
	
	ip=m_list.GetItemText(nListIndex,1);
	
	addrDest.sin_addr.S_un.S_addr	=inet_addr(	ip	);
	addrDest.sin_family				=AF_INET;
	addrDest.sin_port				=htons(	CHATPORT	);
	
	GetDlgItemText(IDC_EDIT_SANDCHAT,temp,800);
	CString		strTime;
	CTime		tm=CTime::GetCurrentTime();
	strTime=tm.Format("%H:%M:%S");
	//获取主机名
	char	phost[200];
	memset(phost,0,200);
	if(	0==gethostname(phost,200)	);
	else	strcpy(phost,"Anony");
	sprintf(send,"%s\t%s:\r\n%s",phost,strTime,temp);
	err=sendto(m_sockChat,send,strlen(send)+1,0,(SOCKADDR*)&addrDest,sizeof(SOCKADDR));
	if(SOCKET_ERROR==err)
	{
		MessageBox("发送聊天消息失败。\t"+GetError(GetLastError(	)));
		return;
	}

	CString	strOld;
	
	GetDlgItemText(IDC_EDIT_RECEIVE,strOld);
	strOld+="\r\n";
	strOld+=send;
	SetDlgItemText(IDC_EDIT_RECEIVE,strOld);
	SetDlgItemText(IDC_EDIT_SANDCHAT,"");	 //清空  Edit  控件内容
	GetDlgItem(IDC_EDIT_RECEIVE)->
	SendMessage(WM_VSCROLL,SB_BOTTOM);
	
}

//清空聊天内容。
void CLANCommunionDlg::OnButtonClear() 
{
	// TODO: Add your control notification handler code here
	SetDlgItemText(IDC_EDIT_RECEIVE,"");
}

void CLANCommunionDlg::OnButtonQuit() 
{
	SaveUserInfo();			//保存用户添加的不在同一子网的IP 地址。
	// TODO: Add your control notification handler code here
	BroadCastExit(	);		//通知其他主机我下线了。
	if(INVALID_SOCKET!=m_sockChat)		//释放套接字资源。
		closesocket(m_sockChat);
	if(INVALID_SOCKET!=m_sockBRecv)
		closesocket(m_sockBRecv);
	if(INVALID_SOCKET!=m_sockBSend)
		closesocket(m_sockBSend);

	if(!Shell_NotifyIcon(NIM_DELETE,&m_nid))
	{
		MessageBox("删除托盘失败。");
//		return;
	}

	exit(	0	);
}

void CLANCommunionDlg::OnClose() 
{
	SaveUserInfo();			//保存用户添加的不在同一子网的IP 地址。
	// TODO: Add your message handler code here and/or call default
	BroadCastExit(	);		//通知其他主机我下线了。
	if(INVALID_SOCKET!=m_sockChat)		//释放套接字资源。
		closesocket(m_sockChat);
	if(INVALID_SOCKET!=m_sockBRecv)
		closesocket(m_sockBRecv);
	if(INVALID_SOCKET!=m_sockBSend)
		closesocket(m_sockBSend);

⌨️ 快捷键说明

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