爱收集资源网

VC++设计聊天室完整教程

网络整理 2023-09-27 21:04

用VC 设计简单的聊天室程序完整课程设计课程设计任务书 学院 专业 课程名称 VC++课程设计 时间 学生姓名 指导老师 题 目 用VC++设计简单的聊天室程序 主要内容: 该系统要求完成聊天室的全过程,包括客户端和服务器两大部份的编程及其联接。服务器端聊天程序负责接收和发送来自客户端的聊天信息,客户端聊天程序负责构建和维护与服务器端的联接,想服务器发送本顾客的聊天内容。系统采用VISUAL C++语言程序设计编程实现。 要求: (1)通过实际软件项目的剖析、设计、编码、测试等工作c简单聊天程序实训,掌握用软件工程的方式来开发和维护软件。 (2)按要求编撰课程设计报告书,能正确编撰剖析、设计、编码、测试等技术文档和用户使用指南。 (3)进行系统的联合调试,编写系统使用说明。 (4)完成系统的文档、设计说明工作 应当递交的文件: (1) 课程设计学年论文。 (2) 课程设计附件(主要是源程序)。 用VC++设计简单的聊天室程序 学生姓名: 指导老师: 摘 要 计算机网络技术发展至今早已大大赶超了人们当年的想像,无论是人们日常的工作还是学习,我们都越来越多的借助到互联网。各种实时性的聊天娱乐软件也同时诞生,而且为我们的即时通讯带来了诸多的便捷,比如说你们所熟知的腾讯QQ、微软的MSN、移动的Fetion等,都是做的比较成功的实时聊天工具。

随着网路的日渐普及,各种聊天工具也层出不穷,但当我们学习了《TCP/IP协议与网络编程》这门课程以后,我们便会认为,其实要实现简单的网路通信虽然并不难。接下来的课程设计就是针对一个简单的网路聊天程序,利用MFC为开发工具,实现基本的通信功能。在课程设计中,系统开发平台为Windows 2000,程序设计设计语言采用Visual C++,数据库采用MS SQL 2000,程序运行平台为Windows 98/2000/XP。 关键词 聊天软件;网络通信;MFC;课程设计;Visual C++ 1 引 言 1.1课题背景及意义 当今世界正处于信息时代,计算机和通讯网路是这一时代所谓“信息基础设施”。在互联网相当普及的明天,在互联网上聊天对好多“网虫”来说早已是家常便饭了。聊天室程序可以说是网上最简单的多点通讯程序。一个简单的聊天室, 从程序员的观点来看就是在多个I/O端点之间实现多对多的通讯。基于SOCKET的局域网通信是一种灵活的、易于实现的、低成本的方式。它可以运行在各类使用TCP/IP协议作为通信合同的网路上。而在SOCKET API的帮助下,开发基于SOCKET的局域网通讯软件也是便于实现的。

1.2 实验平台介绍 Visual C++(简称VC)是Microsoft公司推出的目前使用极为广泛的基于Windows平台的C++可视化开发环境。VC基于C,C++语言,主要由是MFC组成,是与系统联系十分紧密的编程工具,它兼有中级,和低级语言的双重性,功能强悍,灵活,执行效率高,几乎可说VC在 Windows平台无所不能。VC主要是针对Windows系统,适合一些系统级 的开发,可以便捷实现一些底层 的调用。在VC里面嵌入汇编语言很简单。当对系统性能要求很高的时侯,可用VC开发。VC在多线程、网络通讯、分布应用方面,有着不可比拟的优势。 1.3 可行性分析 本课程设计主要解决在客户端于客户端的信息交换和客户端于服务器的信息交换及服务器的信息处理上的管理的课程设计。 此程序主要分为两部份:服务器端和客户端。服务器端用于提供一个网络端口,等待客户端发出恳求,登录到此服务端,然后进行网路通信和消息的转发;客户端可通过服务器端的IP地址发送联接恳求,然后登录聊天室。在服务器端的成员列表栏中会显示在线的所有人名单,有人退出聊天室,成员列表会手动除名。服务器端同时也提供了成员之间的私聊功能,此时服务器端作为一个转发站,进行消息的转发。

聊天室实验报告_c简单聊天程序实训_小型聊天软件开发实训报告

整个程序的主体使用了CSocket类的方式,实现了网路通信聊天。 先启动服务器端聊天程序,这是聊天服务器须要指定一个端口号,客户端则按照这个端口号以及服务器的网路地址与服务器进行通讯。在这儿,把端口号成为“聊天频道” 。 在前面的程序代码剖析上将听到,端口号并不等同于聊天频道,而是在聊天频道上降低一个固定的偏斜值,使得这个聊天频道不会和系统保留的端口发生冲突。 服务器启动后将在这个指定的端口号中等待顾客的联接。对于公共聊天室,服务器对顾客的数量不做任何限制。而对于私人聊天室,每个聊天频道则只能容许两个顾客相互联接,使得一方发送的信息只能抵达对方的主机中。这里的服务器提供的是公共聊天服务。 通过剖析发觉,该程序完全可以通过Visual C++中MFC完成。2需求剖析 2.1 设计目的 综合运用本课程及计算机网路的相关知识设计并实现一个网路应用程序,以Visual C++作为开发平台,通过实践备考巩固课堂所学的理论知识,提高对所学知识的综合应用能力。 2.2 设计要求 采用客户/服务器模式,分为客户端程序和服务器端程序。服务器采用WINSOCK I/O模型中的任一种,支持多个顾客同时在线聊天。

客户端程序和服务器程序通过网路交换聊天字符串内容,服务器窗口的列表框中显示当前在线用户,支持客户端之间的私聊(可以通过服务器中转,或考虑UDP打洞直接完善端端联接)。 课程设计要求设计并编程完成两个方面的内容:首先构建一个使用TCP合同的聊天室服务器,这个服务器可以同时支持多个用户的在线聊天;其次设计一个可以和服务器通讯的聊天室客户端。 2.3 功能要求 , 支持多个客户端的联接,在服务器和多个客户端之间进行数据传输; , 接收客户端发送的消息,并显示在一个列表框中; , 在用户联接上后有提示c简单聊天程序实训,显示出联接的用户名子; , 发送信息时可以显示聊天的所有记录; 2.4 系统主要功能和主要功能描述: 服务器端聊天程序必须才能做3件事情: (1) 服务器聊天程序要在待定的端口上等待来自聊天顾客的联接恳求,并且须要维护一个顾客连接表,以记录所有成功的联接。 (2) 服务器聊天程序要及时接受从各个聊天顾客发送过来的信息,然后把这种信息转发到一个或多个顾客联接。对于公共聊天室,服务器将把接受到的信息向除源端外的所有顾客发送过去。 (3) 服务器还要监控这种联接的状态,在顾客主动离开或发生故障时从列表中删掉相应的表项,并及时更新连接表。

这些要求可以通过CSocket类提供的功能实现。从CSocket派生出两个类CListenSocket和CClientSocket,它们分别拿来侦听顾客的联接恳求和完善与顾客的联接。服务器只须要一个侦听套接字CListenSocket,然后按照顾客的联接恳求动态创建顾客套接字CClientSocket。客户套接字的数目是不可预知的,因此须要一个列表来记录。MFC的CPtrList类能够实现这些功能。 客户端聊天程序须要完成以下几个功能: (1) 客户端聊天程序要负责构建和维护与服务器的联接,通过获取用户的设置尝试与服务器的联接,并且随时监测联接的状态。 (2) 客户端聊天程序要把用户输入的信息及时发送到聊天服务器。一般情况下,当用户输入一行信息而且按下回车键后聊天程序就要把这一行信息发送出去,才能及时地满足用户的交互需求。 (3) 要随时打算好接受来自服务器的信息,随时把接受到的信息显示下来,让用户及时看见对方的响应。 (4) 在用户退出聊天过程是要关掉与服务器的联接。比较好的做法是提早通知服务器或则直接给服务器发送一条退出通知,使得服务器才能及时把握客户端的联接状态,把对方顾客的退出信息及时发送到对等实体上。

客户端聊天程序须要使用一个通过CSocket类派生下来的CChatSocket类来实现。该套接字拿来发送一个与服务器的联接恳求和维持与服务器的联接,发送和接收聊天信息,完成上述各项功能。3设计流程图 根据对用户的要求及功能设置可以得到以下的流程图3.1,用户首先启动客户端,登陆服务器并向服务器发送信息,启动服务器,服务器等待顾客要求并向顾客反馈在线用户信息,用户向服务器发送信息,服务器处理用户的数据,然后用户开始聊天。客户端的聊天分为对所有人的信息和私聊的信息,该信息应通过程序控制分别进行处理。 CListenSocket CClientSocket 启动 登陆 发送ID和IP 等待客户端登录 登陆失败 登陆成功 连接上 客户端用户 创建子套接字 发送message 显示 找到客户端并显示 Message Message 图3.1 设计流程图 4 调试剖析过程描述 Login服务器:在启动聊天室服务端的时侯,会出现图4.1的界面,该界面为服务器的登录界面。 图4.1登录服务器界面 启动服务器:在登入页面的环境下,点击启动服务器按键,即可创建一个新的服务器,服务器界面如图4.2所示。

图4.2 启动服务器界面 Login客户端:在启动客户端服务端的时侯,会出现图4.3的界面,该界面为客户端的联接界面。 图4.3 登陆客户端界面 图4.4为创建张三客户端,输入用户名张三: 图4.4 输入名称张三 图4.5为用户张三联接服务器界面,在输入用户名张三并点击确定后,出现如下界面: 图4.5 张三登录服务器 图4.6为用户李四的联接界面,在李四联接后,张三和李四用户同时出现在用户列表内: 图4.6 李四登录服务器 图4.7为用户李四的联接界面,在王五联接后,张三,李四和王五用户同时出现在用户列表内: 图4.7 王五登录服务器 服务器显示:在张三,李四,王五步入聊天室后的界面为图4.8.: 图4.8 用户成功登录后界面 开始聊天,群聊:客户端发送信息时的界面为图4.9 图4.9 聊天界面 图4.10为私聊界面。张三与李四私聊:点击私聊选项,并发送私聊内容。 图4.10 张三私聊界面 图4.11为张三私聊界面,李四和张三私聊,张三能见到李四发送的内容: 图4.11 李四私聊界面 图4.12为王五的界面显示,王五看不到张三和李四的私聊内容: 图4.12 非私聊对象界面 5 设计的总结和感受 该次课程设计的制做我主要是参照了图书馆内的相关书籍,找到一个类似的程序,然后根据书上的内容一步步的做出来了,虽然这个程序算不上是我自己写下来的,但通过这样的一个过程,还是让我学会了好多东西,也算能比较熟练地把握MFC这一个软件了,这算是一个不小的收获吧,而且,在做这个程序的过程中,让我认识到了在做这样程序中,遇到解决不了的问题与朋友的讨论时很重要的,譬如可以以运行,但是就是未能出现联接的显示和状态。

最后与朋友讨论后,才晓得是服务器端有了错误,没有设置自己的IP地址,然后对于客户端进行了一番更改,才总算出现了上述的结果。虽然没有彻底做的下来,但是还是比较开心的,因为自己晓得了那里不足,哪里不可以,可以在之后多多的做练习来充实自己。 在课程设计过程中,收获知识,提高能力的同时,我也学到了好多人生的哲理,懂得怎么样去拟定计划,怎么样去实现这个计划,并把握了在执行过程中怎么样去克服心理上的不良情绪。因此在之后的生活和学习的过程中,我一定会把课程设计的精神带到生活中,不畏艰辛,勇往直前~ 我之后还是须要多多的练习,多多的勤劳,这样才有可能让自己有信心,有动力,让自己不至于懂的太少而胆怯,因为不懂而不会做,相信自己之后会编撰出让自己满意的程序和软件的。 6 参考文献 [1] 任泰明著. TCP/IP协议与网络编程. 西安电子科技大学出版社. 2004 [2] 唐克著. MFC程序设计:Using Visual C++ 6.0. 北京希望电子出版社. 2002 [3] 邓全良著. Winsock网路程序设计. 中国铁道出版社. 2002 [4]《Visual C++6.0使用与开发》 清华大学出版社,木林森、高峰霞、罗丽琼、奚红宇编绘 [5]《Visual c++ 实用教程(第三版) 郑阿奇 , 电子工业出版社 附:源代码 I服务器: // ServerDlg.cpp : implementation file // #include "stdafx.h" #include "Server.h" #include "ServerDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[ ] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CServerDlg dialog CServerDlg::CServerDlg(CWnd* pParent /*=NULL*/) : CDialog(CServerDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDI_ICONAPP); } void CServerDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_LIST_USER, m_lbUser); DDX_Text(pDX, IDC_EDIT_DISPLAY, m_strDisplay); } BEGIN_MESSAGE_MAP(CServerDlg, CDialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BN_START, OnBnStart) ON_BN_CLICKED(IDC_BN_CLOSE, OnBnClose) ON_MESSAGE(WM_RECEIVE, OnReceive) ON_MESSAGE(WM_CLIENTCLOSE, OnClientClose) ON_MESSAGE(WM_ACCEPT, OnAccept) ON_WM_DESTROY() END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CServerDlg message handlers BOOL CServerDlg::OnInitDialog() { CDialog::OnInitDialog(); 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); } } SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon m_iNetPort = 3127; m_Server.Initialize(this); m_bServer = FALSE; GetDlgItem(IDC_BN_CLOSE)->EnableWindow(FALSE); return TRUE; // return TRUE unless you set the focus to a control } void CServerDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } void CServerDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); 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; dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } HCURSOR CServerDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } void CServerDlg::OnBnStart() { // 创建套接字 m_Server.Create(m_iNetPort); // 开始窃听 m_Server.Listen(); // 显示 CString strInfo; strInfo.LoadString(IDS_CREATE_SERVER); ShowInDisplay(strInfo); m_bServer = TRUE; GetDlgItem(IDC_BN_START)->EnableWindow(FALSE); GetDlgItem(IDC_BN_CLOSE)->EnableWindow(TRUE); }void CServerDlg::OnBnClose() { CloseServer(); GetDlgItem(IDC_BN_START)->EnableWindow(TRUE); GetDlgItem(IDC_BN_CLOSE)->EnableWindow(FALSE); } void CServerDlg::OnAccept() { // 创建新顾客 CMySocket *pNewClient = new CMySocket; pNewClient->Initialize(this); m_Server.Accept(*pNewClient); // 放入数组中 m_lsClient.AddTail(pNewClient); } void CServerDlg::OnClientClose(WPARAM wParam, LPARAM lParam) { CMySocket *p_delClient = (CMySocket*)wParam; // 关闭该用户 p_delClient->ShutDown(); char buffer[BUFFERSIZE]; while(p_delClient->Receive(buffer, BUFFERSIZE)>0); p_delClient->Close(); // 在用户数组中删掉该用户 POSITION psCur, psList = m_lsClient.GetHeadPosition(); CMySocket *p_curClient; while(psList!=NULL) { psCur = psList; p_curClient = (CMySocket *)m_lsClient.GetNext(psList); if(p_delClient==p_curClient) { m_lsClient.RemoveAt(psCur); break; } } // 发送信息告诉其他用户该顾客退出 CString strMsg; strMsg.LoadString(IDS_CLIENT_CLOSE); NETMESSAGE netMessage(PTC_CLIENT_QUIT, p_delClient->GetName(), _T(""), p_delClient->GetName() + strMsg); SendToAllClient(netMessage); // 界面上清除该用户信息 m_lbUser.DeleteString(m_lbUser.FindString(-1, p_delClient->GetName())); ShowInDisplay(p_delClient->GetName() + strMsg); // 删除该用户 delete p_delClient; } void CServerDlg::OnReceive(WPARAM wParam, LPARAM lParam) { CMySocket *p_curClient = (CMySocket*)wParam; NETMESSAGE netMessage; p_curClient->Receive((char *)&netMessage, sizeof(netMessage)); switch(netMessage.type) { case PTC_NEW: // 新顾客加入 NewClientAdd(p_curClient, &netMessage); break; case PTC_SAY: // 普通聊天 ShowMessage(netMessage); break; } // 把加工过的信息发送给其他用户 SendToAllClient(netMessage); } void CServerDlg::CloseServer() { if(!m_bServer) return; // 向所有顾客发送服务端关掉的信息 CString strInfo; strInfo.LoadString(IDS_CLOSESERVER); NETMESSAGE netMessage(PTC_SYSTEM, _T(""), _T(""), strInfo); SendToAllClient(netMessage); // 服务端界面显示关掉信息 ShowInDisplay(strInfo); // 关闭服务端 m_Server.Close(); // 关闭客户端 char buffer[BUFFERSIZE]; CMySocket *m_pClient; POSITION psList = m_lsClient.GetHeadPosition(); while(psList!=NULL) { m_pClient = (CMySocket *)m_lsClient.GetNext(psList); m_pClient->ShutDown(); while(m_pClient->Receive(buffer, BUFFERSIZE)>0); m_pClient->Close(); delete m_pClient; } m_lsClient.RemoveAll(); m_bServer = FALSE; } // 向所有户发出信息 void CServerDlg::SendToAllClient(const NETMESSAGE &netMessage) { CMySocket *m_pClient; POSITION psList = m_lsClient.GetHeadPosition(); while(psList!=NULL) { m_pClient = (CMySocket *)m_lsClient.GetNext(psList); m_pClient->SendMsg(netMessage); } } void CServerDlg::ShowInDisplay(CString str) { m_strDisplay += str + "\r\n"; UpdateData(false); } void CServerDlg::OnDestroy() { CDialog::OnDestroy(); // TODO: Add your message handler code here } // 新用户加入 void CServerDlg::NewClientAdd(CMySocket *p_client, NETMESSAGE *netMessage) { // 存入用户名子 p_client->SetName(netMessage->form); // 在列表框中显示该用户 m_lbUser.AddString(p_client->GetName()); // 发送用户列表给该顾客 NETMESSAGE netMsg(PTC_USER_LIST, _T(""), _T(""), _T("")); int iListLen = m_lbUser.GetCount(); CString strMsg; for(int index=m_lbUser.GetTopIndex(); indexSendMsg(netMsg); } // 加工信息 strMsg.LoadString(IDS_NEW_CLIENT); strMsg = p_client->GetName() + strMsg; strcpy(netMessage->data, (LPCTSTR)strMsg); // 显示该用户步入 ShowInDisplay(strMsg); } // 显示普通消息 void CServerDlg::ShowMessage(NETMESSAGE netMessage) { CString strTo = netMessage.to; if(strTo==_T("")) { strTo = "所有人"; } CString strForm = netMessage.form; CString strMsg = netMessage.data; CString strOut = strForm + "对" + strTo + "说:" + strMsg; ShowInDisplay(strOut); } II客户端: // ClientDlg.cpp : implementation file // #include "stdafx.h" #include "Client.h" #include "ClientDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[ ] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CClientDlg dialog CClientDlg::CClientDlg(CWnd* pParent /*=NULL*/) : CDialog(CClientDlg::IDD, pParent) { m_strDisplay = _T(""); m_strSend = _T(""); m_bWhispering = FALSE; m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CClientDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_LIST_USER, m_lbUser); DDX_Text(pDX, IDC_EDIT_DIAPLAY, m_strDisplay); DDX_Text(pDX, IDC_EDIT_SEND, m_strSend); DDX_Check(pDX, IDC_CHECK_WHISPERING, m_bWhispering); } BEGIN_MESSAGE_MAP(CClientDlg, CDialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BN_CONNECT, OnBnConnect) ON_BN_CLICKED(IDC_BN_CLOSE, OnBnClose) ON_BN_CLICKED(IDC_BN_SEND, OnBnSend) ON_MESSAGE(WM_RECEIVE, OnReceive) ON_MESSAGE(WM_SOCKETCLOSE, OnServerClose) ON_MESSAGE(WM_SEND, OnSend) ON_MESSAGE(WM_CONNCET, OnConnect) ON_LBN_DBLCLK(IDC_LIST_USER, OnDblclkListUser) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CClientDlg message handlers BOOL CClientDlg::OnInitDialog() { CDialog::OnInitDialog(); 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); } } SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // 参数初始化 m_Socket.Initialize(this); m_strNetIP = _T("127.0.0.1"); m_iNetPort = 3127; m_bConnect = FALSE; GetDlgItem(IDC_BN_CLOSE)->EnableWindow(FALSE); GetDlgItem(IDC_BN_SEND)->EnableWindow(FALSE); return TRUE; // return TRUE unless you set the focus to a control } void CClientDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } void CClientDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); 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; dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } HCURSOR CClientDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } void CClientDlg::OnBnConnect() { CString strConnectError; // 获取用户名子 CInputDlg inputDlg; int iResult = inputDlg.DoModal(); if(iResult==IDCANCEL){return;} m_strName = inputDlg.m_strName; // 创建套接字 if(!m_Socket.Create()) { strConnectError.LoadString(IDS_FAIL_CREATE_SOCKET); ShowInDisplay(strConnectError); return; } CString strInfo; strInfo.LoadString(IDS_CONNECTING); ShowInDisplay(strInfo); // 连接服务器 if(!m_Socket.Connect(m_strNetIP, m_iNetPort)) { int n = m_Socket.GetLastError(); strConnectError.LoadString(IDS_FAIL_CONNECT); ShowInDisplay(strConnectError); return; } strInfo.LoadString(IDS_SUCCEED_CONNECT); ShowInDisplay(strInfo); m_bConnect = TRUE; // 发送自已的名子 NETMESSAGE netMessage(PTC_NEW, m_strName, _T(""), _T("")); m_Socket.SendMsg(netMessage); GetDlgItem(IDC_BN_CONNECT)->EnableWindow(FALSE); GetDlgItem(IDC_BN_CLOSE)->EnableWindow(TRUE); GetDlgItem(IDC_BN_SEND)->EnableWindow(TRUE); } void CClientDlg::OnBnClose() { if(m_bConnect) { m_Socket.Close(); m_bConnect = FALSE; GetDlgItem(IDC_BN_CONNECT)->EnableWindow(TRUE); GetDlgItem(IDC_BN_CLOSE)->EnableWindow(FALSE); GetDlgItem(IDC_BN_SEND)->EnableWindow(FALSE); m_lbUser.ResetContent(); CString strMsg; strMsg.LoadString(IDS_BREAK); ShowInDisplay(strMsg); } } void CClientDlg::OnBnSend() { OnSend(); m_strSend = _T(""); UpdateData(FALSE); } void CClientDlg::OnReceive() { NETMESSAGE netMessage; m_Socket.Receive((char *)&netMessage, sizeof(netMessage)); CString strForm = netMessage.form; // 过滤自已发出的信息 if(strForm==m_strName) return; CString strTo = netMessage.to; CString strMsg = netMessage.data; switch(netMessage.type) { case PTC_USER_LIST: // 用户列表 m_lbUser.AddString(strMsg); break; case PTC_NEW: // 新用户步入 m_lbUser.AddString(strForm); ShowInDisplay(strMsg); break; case PTC_SAY: ShowMessage(netMessage); case PTC_WHISPERING: // 密语 if(strTo!=m_strName) return; ShowMessage(netMessage); break; case PTC_CLIENT_QUIT: // 有用户退出 m_lbUser.DeleteString(m_lbUser.FindString(-1, strForm)); ShowInDisplay(strMsg); break; } } void CClientDlg::OnServerClose() { if(!m_bConnect) return; CString strMsg; strMsg.LoadString(IDS_SERVER_CLOSE); ShowInDisplay(strMsg); m_Socket.Close(); m_bConnect = FALSE; GetDlgItem(IDC_BN_CONNECT)->EnableWindow(TRUE); GetDlgItem(IDC_BN_CLOSE)->EnableWindow(FALSE); GetDlgItem(IDC_BN_SEND)->EnableWindow(FALSE); m_lbUser.ResetContent(); } void CClientDlg::OnSend() { UpdateData(TRUE); // 主要是填充NETMESSAGE结构体 NETMESSAGE netMessage; strcpy(netMessage.form, m_strName); strcpy(netMessage.data, m_strSend); // 取得列表框中的用户 if(m_lbUser.GetText(m_lbUser.GetCurSel(), netMessage.to)==LB_ERR) { strcpy(netMessage.to, _T("")); } if(m_bWhispering) { // 密语 CString strTo = netMessage.to; if(strTo==_T("")) { MessageBox("请选择对方!", "错误"); return; } netMessage.type = PTC_WHISPERING; } else { strcpy(netMessage.to, _T("所有人")); netMessage.type = PTC_SAY; } // 发送该信息 m_Socket.SendMsg(netMessage); // 显示发送信息 CString strTo = netMessage.to; CString strMsg = netMessage.data; ShowInDisplay("你对" + strTo + "说:" + strMsg); } void CClientDlg::ShowInDisplay(CString str) { m_strDisplay += str + "\r\n"; UpdateData(FALSE); } void CClientDlg::ShowMessage(const NETMESSAGE &netMessage) { CString strTo = netMessage.to; if(strTo==_T("")) { strTo = "所有人"; } else if(strTo==m_strName) { strTo = "你"; } CString strForm = netMessage.form; CString strMsg = netMessage.data; CString strOut = strForm + "对" + strTo + "说:" + strMsg; ShowInDisplay(strOut); } void CClientDlg::OnDblclkListUser() { // TODO: Add your control notification handler code here m_lbUser.SetCurSel(-1); } void CClientDlg::OnConnect() { m_bConnect = TRUE; }

c简单聊天程序实训
上一篇:仲裁:解释、详细答案,了解一下 下一篇:没有了
相关文章