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

📄 im1.cpp

📁 本系统所完成功能如下: &#61548 即时消息:用户之间发送即时消息。 &#61548 聊天纪录:聊天记录的保存及显示。 &#61548 注册:登陆界面即可进入注册界面 &#61548
💻 CPP
字号:
// IM1.cpp : implementation file
//

#include "stdafx.h"
#include "user.h"
#include "IM.h"
#include "IMDlg.h"
#include "IM1.h"
#include "AddUser.h"
#include "MngDlg.h"
#include "hatDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// IM dialog


IM::IM(CWnd* pParent /*=NULL*/)
	: CDialog(IM::IDD, pParent)
{
	//{{AFX_DATA_INIT(IM)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}


void IM::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(IM)
	DDX_Control(pDX, IDC_TREE, m_TreeCtl);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(IM, CDialog)
	//{{AFX_MSG_MAP(IM)
	ON_BN_CLICKED(ID_ADDUSER, OnAdduser)
	ON_BN_CLICKED(IDC_BTN_MNG, OnBtnMng)
	ON_NOTIFY(NM_DBLCLK, IDC_TREE, OnDblclkTree)
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_RECVDATA,OnRecvData)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// IM message handlers

BOOL IM::OnInitDialog()
{
	CDialog::OnInitDialog();
	IMhWnd=m_hWnd;
	m_nToP=FALSE;
	m_ImgCs.Create(IDB_BITMAP4,16,1,RGB(255,255,255));
	HICON hIcon = AfxGetApp() ->LoadIcon(IDI_ICON1);
	m_ImgCs.Add(hIcon);
	hIcon = AfxGetApp() ->LoadIcon(IDI_ICON2);
	m_ImgCs.Add(hIcon);
	hIcon = AfxGetApp() ->LoadIcon(IDI_ICON3);
	m_ImgCs.Add(hIcon);
	hIcon = AfxGetApp() ->LoadIcon(IDI_ICON4);
	m_ImgCs.Add(hIcon);
	m_TreeCtl.SetImageList(&m_ImgCs, LVSIL_NORMAL);
	UpdateIM(TRUE);
	
	//初始化UDP套接字
	InitSocket();

	//创建子进程接受UDP消息 传递参数为UDP套接字 处理函数为RecvProc
	HANDLE udphThread=CreateThread(NULL,0,RecvProc,(LPVOID)m_socket,0,NULL);
	CloseHandle(udphThread);
    return TRUE;
}

void IM::OnCancel() 
{
	// TODO: Add extra cleanup here	
	CString str;char buffer[1024];
	
	//离线通知 e标志代表e类服务 离线后关闭TCP套接字
	str.Format("e%d",m_uid);
	::send(TCPsocket,str,str.GetLength()+1,0);
	::recv(TCPsocket,buffer,1024,0);
	closesocket(TCPsocket);

	CDialog::OnCancel();
}

void IM::OnAdduser() 
{
	//添加好友模块

	// TODO: Add your control notification handler code here
	AddUser adu;
	if(adu.DoModal()==IDOK)
	{
		m_TreeCtl.DeleteAllItems();
		UpdateIM(TRUE);
	}
}

//更新客户端好友列表  参数代表是否需访问数据库
void IM::UpdateIM(BOOL AccessDB)
{
	CString str;
	str.Format("%d的全部好友",m_uid);

	//判断时候有广播消息
	if(HaveStoreMsg(1000))
		hItemRoot=m_TreeCtl.InsertItem(str,4,4,TVI_ROOT);
	else hItemRoot=m_TreeCtl.InsertItem(str,-1,-1,TVI_ROOT);

	char buf[20][16];
	int grpnum=GetPrivateProfileInt("FriendGroup","Groupnum",0,CRdir+"\\fenzu.ini");

	//读本地好友列表分组信息 添加树枝节点
	HTREEITEM hItem[100];
	for(int i=1;i<=grpnum;i++)
	{
		str.Format("Groupname%d",i);
		GetPrivateProfileString("FriendGroup",str,NULL,buf[i],16,CRdir+"\\fenzu.ini");
		hItem[i]=m_TreeCtl.InsertItem(buf[i],0,0,hItemRoot);
	}
	
	if(AccessDB)
	{
		//需要访问数据库时 请求读取好友信息
		//f标志代表 f类服务
		char buffer[2048];
		str.Format("f%d",m_uid);
		::send(TCPsocket,str,str.GetLength()+1,0);
		//读好友个数
		::recv(TCPsocket,buffer,4,0);
		str.Format("%s",buffer);
		//全局变量 好友总数
		total=atoi(str);
		::recv(TCPsocket,buffer,1024,0);
		str.Format("%s",buffer);
		str.Delete(0,1);
		//将接受到的流转换保存为好友信息
		StreamToStruct(str);
	}
	
	int k;
	for(i=total;i>=1;i--)
	{			
		//读分组文件  插入叶子节点
		k=GetFriendGrp(fuser[i].uid);		
		str.Format("%s(%d)",fuser[i].fnicheng,fuser[i].uid);
				
		//根据会员,在线,离线,有消息。判断关联哪个图片
		//从而给出相应提示
		if(fuser[i].fonline)		
				{
					if(HaveStoreMsg(fuser[i].uid))
						m_TreeCtl.InsertItem(str,4,4,hItem[k],TVI_FIRST);
					else if(fuser[i].fvip)
						m_TreeCtl.InsertItem(str,1,1,hItem[k],TVI_FIRST);
					else 		
						m_TreeCtl.InsertItem(str,2,2,hItem[k],TVI_FIRST);
				}
				else if(m_nToP==FALSE)
				{
					m_TreeCtl.InsertItem(str,3,3,hItem[k],TVI_LAST);
				}
	}
}



void IM::OnBtnMng() 
{
	// TODO: Add your control notification handler code here
	MngDlg mdlg;
	mdlg.DoModal();
	if(mdlg.m_nOnline==0)
		m_nToP=TRUE;
	else if(mdlg.m_nOnline==1)
		m_nToP=FALSE;
	m_TreeCtl.DeleteAllItems();
	if(mdlg.m_nDeID!=0)
		UpdateIM(TRUE);
	else UpdateIM(FALSE);
}

void IM::OnDblclkTree(NMHDR* pNMHDR, LRESULT* pResult) 
{
	//双击好友叶结点 弹出对话框 处理函数

	// TODO: Add your control notification handler code here
	HTREEITEM hItem=m_TreeCtl.GetSelectedItem();
	if(m_TreeCtl.GetChildItem(hItem )==NULL&&m_TreeCtl.GetParentItem(hItem)!=hItemRoot)
	{
		CString s,str=m_TreeCtl.GetItemText(hItem);
		int length=str.GetLength();
		//获取好友 昵称
		for(int i=length-2;i>=0;i--)
		{
			s=str.GetAt(i)+s;
			if(str.GetAt(i)=='(')
			{
				str.SetAt(i,'\0');
				break;
			}
		}
		int digital,num=0;
		//获取好友ID
		for(int j=1;j<length-i-1;j++)
		{
			digital=s.GetAt(j)-48;//-48什么意思? 
			num=num*10+digital; 
		}

		ChatDlg cd;
		cd.m_nuid=num;
		m_iding=num;
		cd.m_nicheng=str;
		cd.m_socket=m_socket;
		cd.DoModal();
		ChathWnd=NULL;
		m_iding=-1;
	}
	else if(hItem == hItemRoot && HaveStoreMsg(1000))
	{
		//当有广播时双击根节点弹出广播消息
		ChatDlg cd;
		cd.m_nuid=1000;
		m_iding=1000;
		cd.m_nicheng="系统广播";
		cd.m_socket=m_socket;
		cd.DoModal();
		ChathWnd=NULL;
		m_iding=-1;
	}
	m_TreeCtl.DeleteAllItems();
	UpdateIM(FALSE);
	*pResult = 0;
}

BOOL IM::InitSocket()
{
	m_socket=socket(AF_INET,SOCK_DGRAM,0);
	if(INVALID_SOCKET==m_socket)
	{
		AfxMessageBox("套接字创建失败!");
		exit(1);
	}
	SOCKADDR_IN addrSock;
	addrSock.sin_family=AF_INET;
	addrSock.sin_port=htons(m_nPort);
	addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);/*inet_addr("59.72.27.169")*/;

	int retval;
	retval=bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR));
	if(SOCKET_ERROR==retval)
	{
		int t;
		t = WSAGetLastError();
		closesocket(m_socket);
		MessageBox("UDP绑定失败!");
		exit(1);
	}
	//int z= ntohs(addrSock.sin_port);
	return TRUE;
}

DWORD WINAPI IM::RecvProc(LPVOID lpParameter)
{
	//接收到UDP包的处理函数

	SOCKET sock= (SOCKET)lpParameter;

	SOCKADDR_IN addrFrom;
	int len=sizeof(SOCKADDR);

	char recvBuf[1024];
	char IPPortBuf[32];
	int retval;
	while(TRUE)
	{
		retval=recvfrom(sock,recvBuf,1024,0,(SOCKADDR*)&addrFrom,&len);
		if(SOCKET_ERROR==retval)
			break;
		if(-1==retval)
		{
			AfxMessageBox("与服务器断开,谢谢您的使用!");
			exit(0);
		}
		 sprintf(IPPortBuf,"%s:%d",inet_ntoa(addrFrom.sin_addr),ntohs(addrFrom.sin_port));
		
		 //传递消息
		 ::PostMessage(IMhWnd,WM_RECVDATA,(WPARAM)IPPortBuf,(LPARAM)recvBuf);
	}
	return 0;
}

void IM::OnRecvData(WPARAM wParam,LPARAM lParam)
{
	//接收到消息的处理函数

	CString recvBuf=(char*)lParam;
	char c=recvBuf.GetAt(0);;

	for(int i=1;i<=total;i++)
	{
		if(fuser[i].fipport==(char*)wParam)
			break;
	}

	switch(c)
	{
	case 'a'://A类  普通聊天信息
		if(i<=total)
		{
			if(m_iding!=-1&&fuser[i].uid==m_iding)
			{
				::PostMessage(ChathWnd,WM_RECVDATA,wParam,lParam);			
			}
			else 
			{
				//如果聊天对话框未打开则插入临时消息链表

				apacket.msg =recvBuf;
				apacket.uid=fuser[i].uid;
				if(head==NULL) 
					head->InsertRear(head,apacket);
				head->InsertRear(head,apacket);
			}
		}	
		break;
	case 'b':break;//好友上线通知
	case 'c':break;//好友离线通知
	case 'd':	
		        //广播
				recvBuf.Delete(0,1);
				apacket.msg =recvBuf;
				apacket.uid=1000;
				if(head==NULL) 
					head->InsertRear(head,apacket);
				head->InsertRear(head,apacket);
				break;
	default:;
	}
	m_TreeCtl.DeleteAllItems();
	UpdateIM(TRUE);
}

void IM::StreamToStruct(CString str)
{
	//将接收到的好友信息流转化为本地好友数据

	int j=1;    
	CString s;
	for(int n=1;n<=total;n++)
	{
		for(int i=0;i<str.GetLength();i++)
		{
			if(str.GetAt(i)!='#')
				s=s+str.GetAt(i);
			else
			{
				if(j==1)
				{
					fuser[n].uid=atoi(s);
					s="";
					j++;
				}
				else if(j==2)
				{
					fuser[n].fipport=s;
					s="";
					j++;
				}
				else if(j==3)
				{
					fuser[n].fvip=atoi(s);
					s="";
					j++;
				}
				else if(j==4)
				{
					fuser[n].fonline=atoi(s);
					s="";
					j++;
				}
				else break;
			}
		}
		fuser[n].fnicheng=s;
		s="";
		j=1;
		str.Delete(0,i+1);
	}
}

BOOL IM::HaveStoreMsg(int uid)
{
	//判断用户 uid 在消息链表中是否有存储的数据

	if(head!=NULL)
	{
		Node <struct APacket> *tempnode=head->NextNode();
		while(tempnode!=NULL)
		{
			if(tempnode->data.uid==uid)
				return TRUE;
			tempnode = tempnode->NextNode();
		}
	}
	return FALSE;
}

int IM::GetFriendGrp(int uid)
{
	//从本地好友分组文件中读取好友 uid 所属组号码并返回

	int friendnum,k=1;
	CString str,s;
	char buf[20][16];
	int grpnum=GetPrivateProfileInt("FriendGroup","Groupnum",0,CRdir+"\\fenzu.ini");
	for(int i=1;i<=grpnum;i++)
	{
		str.Format("Groupname%d",i);
		GetPrivateProfileString("FriendGroup",str,NULL,buf[i],16,CRdir+"\\fenzu.ini");
		friendnum=GetPrivateProfileInt(buf[i],"Friendnum",0,CRdir+"\\fenzu.ini");
			for(k=1;k<=friendnum;k++)
				{
					str.Format("Friend%d",k);
					if(uid==(int)GetPrivateProfileInt(buf[i],str,0,CRdir+"\\fenzu.ini"))
					  return i;
				}
				
	}
	if(i>grpnum)
	{
		friendnum=GetPrivateProfileInt("我的好友","Friendnum",0,CRdir+"\\fenzu.ini");
		str.Format("Friend%d",++friendnum);
		s.Format("%d",uid);
		WritePrivateProfileString("我的好友",str,s,CRdir+"\\fenzu.ini");
		str.Format("%d",friendnum);
		WritePrivateProfileString("我的好友","Friendnum",str,CRdir+"\\fenzu.ini");
	}
	return 1;
}

⌨️ 快捷键说明

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