前言本教程适用于有一定MFC基础的同学使用。大部分人调试时会提示缺少变量,一般是没有添加Message.h文件。请学会CTRL+F,找到在哪里添加变量,声明,定义吧~还有有什么不懂就百度一下吧。它会为你解决。提供一个参考版本给大家使用:注:请不要随便发布这篇教程,最起码把我的联系方式删除。强烈建议自己写教程然后发布出去。请不要加我的QQ,由于各种原因,现在我并没有继续学习MFC,我的水平也就停留在这篇教程中。本系统基于客户端/服务器基本原理,程序即是服务端,也是客户端,通过IP就可以相互添加好友,并且实现点到点通信,有聊天记录(未实现根据用户发送的消息而改变字体颜色,只能在客户端改),字体颜色设置(一改全改~),包含主界面MaindBord和聊天Talk两大功能模块。(1)MaindBord模块A、登录模块登陆模块的实现过程有下面几个步骤:(1)初始化列表信息,获取用户名,服务器的IP地址,使按键失效(2)确认登陆后创建套接字,绑定,监听(3)初始化成功后,激活添加好友和隐藏功能B、好友模块添加好友的实现过程有下面几个步骤:(1)弹出对话框(2)获取对话框中的IP(3)检查对方是否在线,建立连接(4)发送请求验证C、好友列表模块(1)客户接收请求,将服务端加入列表,发送客户端信息(2)服务端得到客户端信息,加入列表(3)双击好友列表,弹出发送信息对话框D、隐藏模块(1)隐藏与显示(2)响应鼠标,弹出控制菜单(2)聊天Talk模块A、发送信息模块聊天模块中,发送信息模块的实现过程有下面几个步骤:(1)通过列表双击一个好友为聊天对象,弹出聊天窗口;(2)用户按下发送按钮后,检测对方是否在线,检测对方是否在线(3)将聊天内容发送出去(4)在本地即时聊天内容显示的编辑框中添加发送的内容并写入聊天记录。B、接收信息模块聊天模块中,接收信息模块的实现过程有下面几个步骤:(1)由主界面判断接收到信息的类型,是否为好友发来信息,如果是,则打开聊天窗口(2)读取消息,并写入聊天记录,(3)载入字体颜色信息。(4)显示聊天记录C、聊天记录管理模块聊天记录管理模块的实现过程有下面几个步骤:(1)将发送内容和接收内容写入文本文件;(2)显示聊天记录;(3)删除聊天记录。D、字体颜色模块实现字体颜色模块的过程有下面几个步骤:(1)调用系统字体,获取字体,写入存档(2)调用系统字体颜色,获取颜色,写入存档(3)读取、更新字体颜色。让我们先看下运行结果:Windows7Windows2003Windows7Windows2003Windows7Windows2003Windows7Windows2003心动了么?让我们开始对第一个模块,也就是MainBord的设计吧。一、MainBord模块新建一个MainBord工程选择Dialogbased,然后Finsh二、界面设计如下:(一)、MainBord界面设计如下:将各ID值设置如下图,通过类向导添加listbox成员变量(二)、添加好友对话框界面设计如下:双击,添加类将各ID值设置如下图,通过类向导添加成员变量(三)、弹出菜单界面设计如下:(四)添加图标三、代码部分:(一)准备部分首先,在StdAfx.h中添加如下代码:afxsock.h头文件;在MainBordDlg.cpp添加Message.h、AddFreind.h;其次,MainBordDlg.h添加如下代码:#defineWM_CLIENT_ACCEPTWM_USER+101#defineWM_CLIENT_READCLOSEWM_USER+102///////////////////////////////////////////////////////////////////////////////CMainBordDlgdialog//Constructionpublic:intTrayAddIcon();charlpszTipBefore[100];//修改前的图标提示信息LRESULTOnAccept(WPARAMwParam,LPARAMlParam);LRESULTOnRead(WPARAMwParam,LPARAMlParam);CMainBordDlg(CWnd*pParent=NULL);//standardconstructorSOCKETClient;//客户的连接请求SOCKETServerSocket;//SOCKETSOCKETtempSocket;SOCKADDR_INtempSocketAddr;SOCKADDR_INm_sockServerAddr;//SOCKET结构BOOLIsTrue;CStringip;CStringSystemMessage;voidSendMsg();CStringIPName;CStringHostName;voidGetIP_Name();voidSelectWay();//好友列表structFriendList{charname[100];charIP[18];structFriendList*next;public:CStringip;}*start,*last;第三,添加Message.h文件代码如下:structMessage{intsign;charmsg[1000];}msg;第四,添加消息响应LRESULTCMainBordDlg::OnRead(WPARAMwParam,LPARAMlParam){if(!IsTrue){//m_List.InsertString(0,有数据到达,但是没有工作站连接。);}CStringstr;switch(WSAGETSELECTEVENT(lParam)){caseFD_READ:if(recv(Client,(char*)&msg,sizeof(msg),0)==SOCKET_ERROR){//m_List.InsertString(0,接收数据发生错误。);return0;}SelectWay();//m_History_List.InsertString(0,str);//MessageBox(str);break;caseFD_CLOSE:str=_T(工作站退出。);//m_List.InsertString(0,str);closesocket(Client);//IsTrue=FALSE;break;}return0L;}LRESULTCMainBordDlg::OnAccept(WPARAMwParam,LPARAMlParam){if(WSAGETSELECTERROR(lParam)){//m_List.InsertString(0,ErrordetectedonentryintoOnServerAccept.);return0L;}if(WSAGETSELECTEVENT(lParam)==FD_ACCEPT)//如果{Client=accept(ServerSocket,(LPSOCKADDR)&m_sockServerAddr,0);if(Client==INVALID_SOCKET){//m_List.InsertString(0,Serversocketfailedtoacceptconnection.);return0L;}//ClinetWSAAsyncSelect(Client,m_hWnd,WM_CLIENT_READCLOSE,FD_READ|FD_CLOSE);IsTrue=TRUE;}//m_List.InsertString(0,有客户机连接上了服务器。);return0L;}(一)、登录模块登陆模块的实现过程有下面几个步骤:(1)初始化列表,获取用户名,服务器的IP地址,使按键失效。在MainBordDlg.cpp的初始化函数OnInitDialog添加如下代码:m_FriendList.SetItemHeight(0,18);start=NULL;last=NULL;//TODO:AddextrainitializationhereGetIP_Name();strcpy(lpszTipBefore,QQ+IPName);(CEdit*)GetDlgItem(IDC_AddBTN)-EnableWindow(FALSE);(CEdit*)GetDlgItem(IDC_HIDEBTN)-EnableWindow(FALSE);(2)在MainBordDlg.cpp添加获取主机获得IP和主机名的函数voidCMainBordDlg::GetIP_Name()//获得IP和主机名{WORDwVersionRequested;WSADATAwsaData;charhostname[128];CStringstrip;PHOSTENThostinfo;wVersionRequested=MAKEWORD(2,0);if(WSAStartup(wVersionRequested,&wsaData)==0){if(gethostname(hostname,sizeof(hostname))==0){if((hostinfo=gethostbyname(hostname))!=NULL){strip=inet_ntoa(*(structin_addr*)*hostinfo-h_addr_list);}}WSACleanup();}IPName=strip;HostName.Format(%s,hostname);}(3)确定登陆后创建套接字,绑定,监听,初始化成功后,激活添加好友和隐藏功能在MainBordDlg.cpp添加登陆按钮的方法voidCMainBordDlg::OnStartBTN(){//TODO:AddyourcontrolnotificationhandlercodehereWSADATAwsaData;intiErrorCode;if(WSAStartup(MAKEWORD(2,1),&wsaData))//调用WindowsSocketsDLL{WSACleanup();return;}//m_List.InsertString(0,服务器开始创建SOCKET。);ServerSocket=socket(PF_INET,SOCK_STREAM,0);//创建服务器端Socket,类型为SOCK_STREAM,面向连接的通信if(ServerSocket==INVALID_SOCKET){//m_List.InsertString(0,无法创建服务器socket!);return;}m_sockServerAddr.sin_family=AF_INET;m_sockServerAddr.sin_addr.s_addr=INADDR_ANY;//向所有的IP地址发送消息m_sockServerAddr.sin_port=htons(8001);if(bind(ServerSocket,(LPSOCKADDR)&m_sockServerAddr,sizeof(m_sockServerAddr))==SOCKET_ERROR)//与选定的端口绑定{//m_List.InsertString(0,无法绑定服务器。);return;}iErrorCode=WSAAsyncSelect(ServerSocket,m_hWnd,WM_CLIENT_ACCEPT,FD_ACCEPT);//产生相应传递给窗口的消息为WM_SERVER_ACCEPT,这是自定义消息if(iErrorCode==SOCKET_ERROR){return;}if(listen(ServerSocket,1)==SOCKET_ERROR)//开始监听客户连接请求{//m_List.InsertString(0,服务器监听失败!);return;}IsTrue=TRUE;//m_List.AddString(服务器绑定监听成功。);