1、远端通信目标目标的网络目标地址目标主机名获取设置目标获取设置目标主机名获取设置目标地址CDestination对于用户与远端通信目标之间的交互信息,可以归纳为上下线通知、短消息、文件等类(如下表所示),其属性都很简单,获取要传送的文件可以由的CFileDialog类实现。对用户与远端通信目标之间交互信息的分析上下线通知发送方发送方主机名消息类型(上线下线)无MSG_NOTIFY短消息短消息内容CMessage文件文件路径、文件名获取文件路径、文件名-3 方法分析可以将功能需求分为以下几部分。 ()在线状态管理在线状态管理的内容包括:上线时发送上线消息,在线时监听远端通信目标的状态,下线时则发送
2、下线消息。其活动图如下图(2)所示。其中的初始化包括创建界面窗口、加载WinSock COM、加载系统配置文件、加载用户自身配置文件,系统的配置保存在bin/conf/config.xml文件中,用户自身配置文件保存在bin/conf/Profile.xml文件中。(2) 与远端通信目标的短消息通信短消息通信是在在线状态下进行的,与监听远端通信目标状态、文件传输、信使服务是并行的。发送短消息需要指定接收方的远端通信目标。短消息通信拥有自己的窗口,以便显示短消息内容和编辑发送的短消息。其活动图如下图()所示。图()图()(3) 与远端通信目标的文件传输服务文件传输也在在线状态下进行,也需要指定接
3、收方的远端通信目标,通过CFileDialog查找要传递的文件,然后确认发送,就被发送到接收方的”.File”目录下。其活动图如下图()所示。(4) 信使服务信使服务用于与不经常联系的人进行通信服务,无需维护远端通信目标列表,只需输入对方的地址或主机名(局域网),就能发送简短消息,其活动图如下图()所示。 图()图()三:界面设计按照界面要求提出的需求,初步构想以下主要界面。1 主界面主界面分为与远端通信目标通信和信使服务两种状态,不使用时界面收缩到最小,不影响用户其他工作。用列表来显示远端通信目标在线状态,目标上线则显示其网络名称,下线时则从列表中删除该目标,如下图()所示。由于远端通信目标
4、的短消息通信和发送文件都需要选择目标名,因此双击目标列表项即可打开一个新窗口(如图()所示),由于短消息通信及文件传输服务。2 短消息及文件传输窗口在此窗口中设置控件编辑消息、显示短消息内容,确认发送。设置控件选取要传输的文件路径及文件名,可以直接使用CFileDialog。此窗口仿照及的聊天窗口布置,如图()所示。本例中限定短消息长少于字(Byte),因此可以用简短的Edit控件就可以了。3 信使服务窗口设置控件编辑短消息、输入计算机名或地址。应考虑地址的特殊性(地址是点分位数),此窗口布置如图()所示。图() 图() 图()四:部分源代码1 CMyessengerDlg类void CMyM
5、essengerDlg:ProcessOnlineMsg(CDestination * obj) m_cs.Lock(); POSITION pos = m_DestinationQueue.GetHeadPosition(); bool bExist = false; for ( ; pos != NULL ; m_DestinationQueue.GetNext(pos) if (*m_DestinationQueue.GetAt(pos) = *obj) bExist = true; break; if (bExist) delete obj; else m_DestinationQue
6、ue.AddTail(obj); int nIndex = m_list.AddString(obj-GetName(); /加到List中 if (LB_ERRSPACE = nIndex | LB_ERR = nIndex) AfxMessageBox(加到列表时出错!); TRACE(加到列表时出错误!n ASSERT(FALSE); else m_list.SetItemDataPtr(nIndex, m_DestinationQueue.GetTailPosition(); m_cs.Unlock();ProcessOfflineMsg(CDestination * obj) del
7、ete obj; /删除对象 CDestination *pDeleted = m_DestinationQueue.GetAt(pos); m_DestinationQueue.RemoveAt(pos); /删除结点 if (!pDeleted-Get_pDlg() /删除短消息与文件传输窗口 pDeleted-Get_pDlg()-SetPeer(POSITION)NULL);OnDestOffline(0, 0); /删除远端目标LIST上的条目,通过pos来找到. for (int i = 0; i Get_pDlg(); if (!pDlg) /构造此目标的短消息与文件传输窗口 C
8、String strRemoteIPAddress = pObj-GetIPAddress(); CString strRemoteNickName = pObj-GetName(); DWORD dwRemoteID = pObj-GetID(); pDlg = CDlgChat:CreateRelatedWnd(pos, dwRemoteID, strRemoteNickName, strRemoteIPAddress); /将此结点与窗口绑定 m_DestinationQueue.GetAt(pos)-Set_pDlg(pDlg); pDlg-ShowWindow(SW_RESTORE)
9、; /显示窗口SetForegroundWindow();OnTimer(UINT nIDEvent) SendOnlineMsg(); CDialog:OnTimer(nIDEvent);short CMyMessengerDlg:m_TransPort;SendDestinationMsg(MSG_NOTIFY dgm) TRACE(BroadcastProfile 开始.n / 使用UDP的socket,使用广播方式,MFC自动选择端口。 CWorkSocket wrkSocket; BOOL bErr = wrkSocket.Create(0, SOCK_DGRAM);bErr) TR
10、ACE(wrkSocket.Create error(0x%x)n, GetLastError(); ASSERT(FALSE); BOOL val = TRUE; bErr = wrkSocket.SetSockOpt(SO_BROADCAST, &val, sizeof(BOOL);SetSockOpt error(0x%x)n / 将profile广播到其他机器的m_TransPort int nErr = wrkSocket.SendTo(&dgm, sizeof(dgm), CMyMessengerDlg:m_TransPort, NULL); if (SOCKET_ERROR =
11、nErr) nErr = GetLastError();SendTo error(0x%x)n, nErr); /Send OK!Broadcast profile ok! wrkSocket.Close(); wrkSocket.ShutDown(); void CMyMessengerDlg:OnDblclkList() /与指定目标收发短消息 int nIndex = m_list.GetCurSel(); if (LB_ERR = nIndex) AfxMessageBox(必须指定通信对象! OpenChatDlg(POSITION)m_list.GetItemDataPtr(nIn
12、dex);CloseChatDlg(POSITION pos) if (NULL != pos)Set_pDlg(NULL);LRESULT CMyMessengerDlg:OnChatMsg(WPARAM wParam, LPARAM lParam) CMessage *pDGram = (CMessage *)lParam; if (pDGram) CDestination *pObj = SearchDestination(pDGram-m_dwNetMsgID); if (pObj) /此目标结点是否有短消息与文件传输窗口。 if (pObj-Get_pDlg() /交给短消息与文件传
13、输窗口处理 pObj-OnRecv(pDGram-m_strMsg); else TRACE(信息来自%u, : %sn, pDGram-m_dwNetMsgID, pDGram- delete pDGram; return 0;const CString& CMyMessengerDlg:GetSelfName() const return m_strSelfName;const DWORD&GetSelfID() const return m_dwSelfID;2 在线短消息服务void CDlgChat:SendMsg()SendMsg() 开始.n / 使用一个UDP的socket C
14、WorkSocket workSocket; BOOL bRet = workSocket.Create(0, SOCK_DGRAM); char buf1024 = 0; / Set chat Msg header#pragma message( - Author - Entity problem solved!) sprintf(buf, NetMsgID%uMsg%s/ChatDiagram , m_dwSelfID , try IXMLDOMDocumentPtr xmlDoc(_uuidof(DOMDocument); xmlDoc-async = false;loadXML(_bs
15、tr_t(buf);selectSingleNode(ChatDiagram/Msg)-text = (const char *)m_strMsg; strncpy(buf, xmlDoc-xml, sizeof(buf); catch(_com_error &e) CString sError = com_error: ; sError += (const char *)e.Description(); AfxMessageBox(sError); / 向对方m_strPeerIP的shortChatPort上发送短消息XML int nErr = workSocket.SendTo(buf
16、, strlen(buf) + 1 , CDlgChat:shortChatPort, m_strPeerIP); bool bSendOK = (SOCKET_ERROR != nErr); if (bSendOK)Send message error(0x%x)nSend message ok! PostMessage(WM_CHAT_MSG, 1, 0); workSocket.Close();SaveMsg()%sn, m_strSelfName); SaveMsg(m_strSelfName, m_strMsg);/#pragma message(-OnRecv 在收到对方短信息时,
17、如果窗口没有打开,那么信息就不能被显示,这个要修改。OnRecv(CString strMsg) SaveMsg(m_strPeerName, strMsg); int nLen = m_MsgNote.GetWindowTextLength(); /显示到短消息显示Edit末尾一行 m_MsgNote.SetSel(nLen, nLen); CString strTemp = m_strPeerName + + strMsg + rn m_MsgNote.ReplaceSel(strTemp);OnSend() UpdateData(TRUE); /禁止发送按钮和输入编辑框 m_Send.E
18、nableWindow(FALSE); m_Msg.EnableWindow(FALSE); SendMsg(); /发送信息 SaveMsg(); /保存信息 int nLen = m_MsgNote.GetWindowTextLength(); /显示信息到最后一行。 m_MsgNote.SetSel(nLen, nLen); CString strTemp = m_strSelfName + + m_strMsg + /清空输入框 m_strMsg = UpdateData(FALSE);SaveMsg(CString speaker, CString strMsg) extern CM
19、yMessengerApp theApp; CString strFileName; strFileName.Format(theApp.GetWorkDIR() + chat%u), m_dwPeerID); CString strPut = speaker + strPut += strMsg + CStdioFile file(strFileName, CFile:modeCreate|CFile:modeNoTruncate |CFile:modeWrite |CFile:shareDenyWrite |CFile:typeText); file.SeekToEnd(); file.W
20、riteString(strPut); catch(CFileException & e.ReportError();short CDlgChat:shortChatPort = 0;PostNcDestroy() 删除短消息对话框。, m_strPeerName); CMyMessengerDlg *pMainWnd = static_cast(AfxGetMainWnd(); pMainWnd-CloseChatDlg(m_posPeer); ShutDownRelation();PostNcDestroy(); delete this;OnClose() /CMyMessengerDlg *pMainWnd = static_cast /ShutDownRelation(); DestroyWindow();3 文件传输服务OnSendFiles() CFileDialog dlg(TRUE); if (IDOK = dlg.DoModal() AfxMessageBox(dlg.m_ofn.lpstrFile); SendFile(dlg.m_ofn.lpstrFile); SendFile(CString strFileName)
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1