ChatDlg.cpp
Upload User: whzytd4
Upload Date: 2022-08-01
Package Size: 7346k
Code Size: 9k
Category:

WinSock-NDIS

Development Platform:

Visual C++

  1. // ChatDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "resource.h"
  5. #include "Client.h"
  6. #include "ChatDlg.h"
  7. #ifdef _DEBUG
  8. #define new DEBUG_NEW
  9. #undef THIS_FILE
  10. static char THIS_FILE[] = __FILE__;
  11. #endif
  12. /////////////////////////////////////////////////////////////////////////////
  13. // CChatDlg dialog
  14. CChatDlg::CChatDlg(CWnd* pParent /*=NULL*/)
  15. : CDialog(CChatDlg::IDD, pParent),m_strRec("")
  16. {
  17. //{{AFX_DATA_INIT(CChatDlg)
  18. // NOTE: the ClassWizard will add member initialization here
  19. //}}AFX_DATA_INIT
  20. m_pSocket = NULL;
  21. m_pFile = NULL;
  22. m_pArchiveIn = NULL;
  23. m_pArchiveOut = NULL;
  24. m_bOfflineWnd = FALSE;
  25. m_pOfflinePacket = NULL;
  26. }
  27. /*
  28.  * 在线/离线窗口
  29.  */
  30. CChatDlg::CChatDlg(CWnd* pParent, const CUserInfo &peerInfo, const CUserInfo &userInfor)
  31. :CDialog(CChatDlg::IDD, pParent),m_strRec("")
  32. {
  33. m_PeerInfo = peerInfo; //对方用户信息
  34. m_UserInfo = userInfor; //用户信息
  35. m_pSocket = NULL; //CChatSocket指针
  36. m_pFile = NULL; //文件对象
  37. m_pArchiveIn = NULL; //读入文档对象
  38. m_pArchiveOut = NULL; //写入文档对象
  39. m_pOfflinePacket = NULL;//离线数据包
  40. m_bOfflineWnd = FALSE; //接收离线窗口
  41. }
  42. /*
  43.  * 显示离线消息窗口
  44.  */
  45. CChatDlg::CChatDlg(CWnd* pParent, CChatPacket *pPacket)
  46. :CDialog(CChatDlg::IDD, pParent),m_strRec("")
  47. {
  48. m_pOfflinePacket = pPacket; //离线数据包
  49. m_bOfflineWnd = TRUE; //接收离线窗口
  50. m_pSocket = NULL; //CChatSocket指针
  51. m_pFile = NULL; //文件对象
  52. m_pArchiveIn = NULL; //读入文档对象
  53. m_pArchiveOut = NULL; //写入文档对象
  54. }
  55. void CChatDlg::DoDataExchange(CDataExchange* pDX)
  56. {
  57. CDialog::DoDataExchange(pDX);
  58. //{{AFX_DATA_MAP(CChatDlg)
  59. DDX_Control(pDX, IDC_CLIENT_CHAT_OUTPUT_EDIT, m_ctlOutput);
  60. DDX_Control(pDX, IDC_CLIENT_CHAT_IPUT_EDIT, m_ctlInput);
  61. //}}AFX_DATA_MAP
  62. }
  63. BEGIN_MESSAGE_MAP(CChatDlg, CDialog)
  64. //{{AFX_MSG_MAP(CChatDlg)
  65. ON_WM_DESTROY()
  66. //}}AFX_MSG_MAP
  67. END_MESSAGE_MAP()
  68. /////////////////////////////////////////////////////////////////////////////
  69. // CChatDlg message handlers
  70. /*
  71.  * 接收消息
  72.  */
  73. void CChatDlg::ProcessPendingRead(void)
  74. {
  75. do 
  76. {
  77. CChatPacket chatPact;
  78. chatPact.Serialize(*m_pArchiveIn);
  79. if (CChatPacket::MESSAGE == chatPact.m_type)//消息
  80. {
  81. DisplayRecvMessage(&chatPact);
  82. }
  83. } while(!m_pArchiveIn->IsBufferEmpty());
  84. }
  85. /*
  86.  * WM_INITDIALOG消息响应函数
  87.  */
  88. BOOL CChatDlg::OnInitDialog() 
  89. {
  90. //调用基类函数
  91. CDialog::OnInitDialog();
  92. if (NULL != m_pOfflinePacket && TRUE == m_bOfflineWnd) //显示离线消息
  93. {
  94. DisplayOfflineMessage(m_pOfflinePacket);
  95. }else if (m_PeerInfo.m_eStatus == CUserInfo::ONLINE) //在线聊天
  96. {
  97. SetWindowText(_T("与") + m_PeerInfo.m_strName + _T("聊天中"));
  98. }else //发送离线消息
  99. {
  100. SetWindowText(m_PeerInfo.m_strName + _T("不在线哦"));
  101. }
  102. return TRUE;  
  103. }
  104. /*
  105.  * 连接对方
  106.  */
  107. BOOL CChatDlg::ConnectToPeer(void)
  108. {
  109. //创建CChatSocket对象
  110. if(!InitSocket())
  111. {
  112. return FALSE;
  113. }
  114. //创建套接字,绑定
  115. if (!m_pSocket->Create())
  116. {
  117. delete m_pSocket;
  118. m_pSocket = NULL;
  119. AfxMessageBox(_T("创建套接字失败!"));
  120. return FALSE;
  121. }
  122. m_pFile = new CSocketFile(m_pSocket); //创建文件对象
  123.   m_pArchiveIn = new CArchive(m_pFile,CArchive::load);//创建读入文档对象
  124. //连接对方
  125. SOCKADDR_IN peerAddr;
  126. peerAddr.sin_family = AF_INET;
  127. peerAddr.sin_addr.S_un.S_addr = m_PeerInfo.m_lIP;
  128. peerAddr.sin_port = m_PeerInfo.m_nPort;
  129. while (!m_pSocket->Connect((SOCKADDR*)&peerAddr, sizeof(SOCKADDR_IN)))
  130. {
  131. if (AfxMessageBox(_T("连接对方失败,是否再次尝试连接。"),MB_YESNO) == IDNO)
  132. {
  133. return FALSE;
  134. }
  135. }
  136. return TRUE;
  137. }
  138. BOOL CChatDlg::InitSocket(void)
  139. {
  140. //创建套接字
  141. m_pSocket = new CChatSocket(this);
  142. return TRUE;
  143. }
  144. /*
  145.  * 显示主动聊天接收到的消息
  146.  */
  147. void CChatDlg::DisplayRecvMessage(CChatPacket *pPacket)
  148. {
  149. CString chatHeader = pPacket->m_UserInfo.m_strName;//发送消息的用户名称
  150. //格式化日期和时间
  151. CTime timeChatting(pPacket->m_time);
  152. int year = timeChatting.GetYear();
  153. int month = timeChatting.GetMonth();
  154. int day = timeChatting.GetDay();
  155. int hour = timeChatting.GetHour();
  156. int minute = timeChatting.GetMinute();
  157. int second = timeChatting.GetSecond();
  158. CString chatTime;
  159. chatTime.Format(" (%d-%d-%d  %d:%d:%d)", year, month, day, hour, minute, second);
  160. //显示消息头
  161. chatHeader += chatTime;
  162. CString strItem = chatHeader + "rn"+ pPacket->m_strMsg + "rn";
  163. //显示消息
  164. int len = m_ctlOutput.GetWindowTextLength();
  165. m_ctlOutput.SetSel(len,len);
  166. m_ctlOutput.ReplaceSel(strItem);
  167. }
  168. /*
  169.  * 处理键盘消息
  170.  */
  171. BOOL CChatDlg::PreTranslateMessage(MSG* pMsg) 
  172. {
  173. if(pMsg->hwnd == m_ctlInput.GetSafeHwnd()) //输入消息窗口    
  174. {  
  175. if (pMsg->wParam == VK_RETURN) //return键  
  176. if (TRUE == m_bOfflineWnd ) //显示离线消息窗口
  177. {
  178. return TRUE;
  179. }else //在线/离线聊天窗口
  180. {
  181. SendPeerMessage(); //发送消息
  182. m_ctlInput.SetWindowText(""); //清空输入消息窗口内容
  183. }
  184. return TRUE;
  185. }  
  186. }  
  187. return CDialog::PreTranslateMessage(pMsg); //其他消息
  188. }
  189. /*
  190.  * 发送消息
  191.  */
  192. void CChatDlg::SendPeerMessage( void )
  193. {
  194. //输入消息窗口内容为空
  195. if (0 == m_ctlInput.GetWindowTextLength())
  196. {
  197. return;
  198. }
  199. //对方在线
  200. if(m_PeerInfo.m_eStatus == CUserInfo::ONLINE) //发送在线消息
  201. {
  202. CChatPacket packet;
  203. packet.m_UserInfo = this->m_UserInfo; //发送消息用户名称
  204. packet.m_type = CChatPacket::MESSAGE; //包的类型
  205. m_ctlInput.GetWindowText(packet.m_strMsg); //消息
  206. packet.m_time = CTime::GetCurrentTime(); //发包时间
  207. //发送消息
  208. m_pArchiveOut = new CArchive(m_pFile,CArchive::store);//创建写入文档对象
  209. packet.Serialize(*m_pArchiveOut);
  210. m_pArchiveOut->Flush();
  211. delete m_pArchiveOut;
  212. m_pArchiveOut = NULL;
  213. //显示发送的消息
  214. DisplaySentMessage(&packet);
  215. }else//对方离线
  216. {
  217. //显示发送的离线消息
  218. DisplaySentMessage();
  219. }
  220. }
  221. /*
  222.  * 显示发送的消息
  223.  */
  224. void CChatDlg::DisplaySentMessage(CChatPacket *pPacket)
  225. {
  226. CString chatHeader = pPacket->m_UserInfo.m_strName; //发送消息用户名称
  227. //格式化发送消息的时间
  228. CTime timeChatting =  pPacket->m_time;
  229. int year = timeChatting.GetYear(); //年
  230. int month = timeChatting.GetMonth(); //月
  231. int day = timeChatting.GetDay(); //日
  232. int hour = timeChatting.GetHour(); //时
  233. int minute = timeChatting.GetMinute(); //分
  234. int second = timeChatting.GetSecond(); //秒
  235. CString chatTime;
  236. chatTime.Format(" (%d-%d-%d  %d:%d:%d)", year, month, day, hour, minute, second);
  237. chatHeader += chatTime;//消息头
  238. //获取输入消息
  239. CString strMsg;
  240. m_ctlInput.GetWindowText(strMsg);
  241. //消息头与消息分行显示
  242. CString strItem = chatHeader + "rn"+ pPacket->m_strMsg + "rn";
  243. //在当前消息行下面显示消息
  244. int len = m_ctlOutput.GetWindowTextLength();//当前文本长度
  245. m_ctlOutput.SetSel(len,len); //移动插入符到当前文本最后
  246. m_ctlOutput.ReplaceSel(strItem); //在当前文本后插入消息
  247. }
  248. /*
  249.  * 显示发送的消息
  250.  */
  251. void CChatDlg::DisplaySentMessage(void)
  252. {
  253. CString chatHeader = m_UserInfo.m_strName;
  254. CTime timeChatting =  CTime::GetCurrentTime();
  255. int year = timeChatting.GetYear(); //年
  256. int month = timeChatting.GetMonth(); //月
  257. int day = timeChatting.GetDay(); //日
  258. int hour = timeChatting.GetHour(); //时
  259. int minute = timeChatting.GetMinute(); //分
  260. int second = timeChatting.GetSecond(); //秒
  261. CString chatTime;
  262. chatTime.Format(" (%d-%d-%d  %d:%d:%d)", year, month, day, hour, minute, second);
  263. chatHeader += chatTime;//消息头
  264. CString strMsg;
  265. m_ctlInput.GetWindowText(strMsg);
  266. CString strItem = chatHeader + "rn"+ strMsg + "rn";
  267. //显示消息
  268. int len = m_ctlOutput.GetWindowTextLength();
  269. m_ctlOutput.SetSel(len,len);
  270. m_ctlOutput.ReplaceSel(strItem);
  271. }
  272. void CChatDlg::InitArchive(void)
  273. {
  274. //初始化输入和输出流
  275. m_pFile = new CSocketFile(m_pSocket); //初始化CSocketFile
  276. m_pArchiveIn = new CArchive(m_pFile,CArchive::load); //初始化读入流
  277. }
  278. void CChatDlg::SetPeerInfor( CUserInfo &peerInfo )
  279. {
  280. m_PeerInfo = peerInfo;
  281. }
  282. void CChatDlg::SetUserInfor( CUserInfo &userInfo )
  283. {
  284. m_UserInfo = userInfo;
  285. }
  286. void CChatDlg::OnDestroy() 
  287. {
  288. m_ctlOutput.GetWindowText(m_strRec);//聊天记录
  289. CDialog::OnDestroy();
  290. }
  291. CChatDlg::~CChatDlg()
  292. {
  293. if(FALSE == m_bOfflineWnd)
  294. {
  295. if (NULL != m_pArchiveIn)
  296. {
  297. delete m_pArchiveIn;
  298. m_pArchiveIn = NULL;
  299. }
  300. if (NULL != m_pFile)
  301. {
  302. delete m_pFile;
  303. m_pFile = NULL;
  304. }
  305. if (NULL != m_pSocket)
  306. {
  307. delete m_pSocket;
  308. m_pSocket = NULL;
  309. }
  310. }
  311. }
  312. CChatSocket *CChatDlg::GetChatSocket( void )
  313. {
  314. return m_pSocket;
  315. }
  316. /*
  317.  * 显示离线消息
  318.  */
  319. void CChatDlg::DisplayOfflineMessage( CChatPacket *pPacket )
  320. {
  321. CRect inputWndRect;
  322. m_ctlInput.GetWindowRect(&inputWndRect);//获取输入消息窗口区域
  323. m_ctlInput.MoveWindow(0, 0, 0, 0); //设置该窗口大小为0
  324. CRect chatDlgRect;
  325. GetClientRect(&chatDlgRect); //获取对话框客户区大小
  326. MoveWindow(0, 0, chatDlgRect.Width(), //修改对话框的高度
  327. chatDlgRect.Height() - inputWndRect.Height());
  328. GetClientRect(&chatDlgRect); //获取对话框客户区大小
  329. m_ctlOutput.MoveWindow(5, 5, //修改显示消息窗口高度
  330. chatDlgRect.Width() -10, chatDlgRect.Height() -10);
  331. m_PeerInfo = pPacket->m_UserInfo; //发送消息用户名称
  332. SetWindowText(m_PeerInfo.m_strName + _T("发送给您的离线消息"));  //设置标题
  333. m_ctlOutput.SetWindowText(pPacket->m_strMsg ); //设置消息
  334. }