聊天客户端界面
聊天服务端界面
建立项目过程
选择一个MFC项目->基于对话框->dlg
MFC中App与Dlg区别
1.我们在创建MFC基于对话框的工程时,最后都有一个选项,如下图所示
2.那么Dlg与App的区别是什么呢?
程序是按顺序执行的,虽然都被封装成了类对象,看起来模块话,其实还是按顺序执行的,APP这个对象那个先于dlg构建。所以很多需要初始化的东西直接在App的成员initInstance中编写。dlg中编写的基本都是一些与对话框相关的逻辑。
cdialog VS cdialogex
cdialog和cdialogex是MFC中的两个对话框类,它们的区别在于cdialogex支持更多的对话框样式和属性,例如可以设置对话框的背景图片、字体、对话框大小等。 而cdialog则只支持基本的对话框属性设置。 因此,如果需要更加灵活地控制对话框的样式和属性,可以选择使用cdialogex。
DebugView的使用方法
补充(直接在控制台打印)
变量的命名规范
字符串或者字符数组 sz
CString cs或者str
int i前缀
uint u
dword dw
LPCSTR
CSting中_T()的作用
VC支持ascii和unicode两种字符类型,用_T可以保证从ascii编码类型转换到unicode编码类型的时候,程序不需要修改。
注意事项
一般情况下让其成对出现
#include "MFCChatClient.h"
#include "MFCChatClientDlg.h"
错误查找工具
MFC的Dlg VS App
app类。他是一个项目工程类,有一个全局的实例化。theApp你可以理解为整个项目的实例,它重载了入口函数,所有的窗口神马的,都是在这个类里实例化的。
dlg是对话框,是一个窗口。一个程序(app)可能没有窗口,也可能很多窗口,取决于你怎么设计。窗口本质上是一样的,但外观上你可以分成一般窗口和对话框。
两个类的作用完全不同,app类相当于相当于程序初始化,建立消息循环,窗口类实现窗口的功能,每一个程序都必须有一个并且只有一个app类,但是程序不一定要要窗口类!
配置 文件
profile
C++中局部变量的默认值
默认值可以是常量、全局变量或者全局函数。 不可以是局部变量。 原因是函数参数默认值是在编译时确定的,而局部变量存在栈上,编译时不能确定。
路径格式化
_T
_T是一个宏,用于在编译时根据字符集设置切换字符串字面量的宽字符或多字节字符。在 Unicode 字符集下,_T 将字符串字面量变为宽字符(wchar_t)字符串,在多字节字符集下则保持原样。
例如:
_T(“客户端”)
在 Unicode 字符集下会被展开为:
L"客户端"
而在多字节字符集下则被保持为:
"客户端"
使用 _T 是为了使代码更具有可移植性,因为这样可以方便地适应不同字符集的编译环境,而无需手动更改字符串字面量的前缀。
m_list的坑(关闭自动插入)
CListBox m_list;
radio的坑(关闭自动)(checkbox类似)
delete m_chat;出现异常
vs2008导入Bitmap图片无法导入的问题
ShellExecute显示找不到应用
ShellExecute(NULL,_T("open"),_T("https://www.baidu.com"),NULL,NULL,SW_SHOWNORMAL);
设置好默认浏览器
C++实现socket编程 ---- 异步非阻塞Socket封装类 CAsyncSocket
CAsyncSocket 最方便的socket的C++的写法
学会用MSDN去查看类 https://msdn.microsoft.com/zh-cn/?query=
1CAsyncSocket::Create() ,使用#include <afxsock.h>头文件,用AfxSocketInit()初始化
2异步非阻塞
3重写 一个类 客户端和服务端
4收到Socket事件之后,只是简单地回调CAsyncSocket::OnReceive()等虚函数。所以CAsyncSocket的派生类,只需要在这些虚函数里添加发送和接收的代码。
5客户方在使用CAsyncSocket::Connect()时,往往返回一个WSAEWOULDBLOCK的错误(其它的某些函数调用也如此),实际上这不应该算作一个错误,它是Socket提醒我们,由于你使用了非阻塞Socket方式,所以(连接)操作需要时间,不能瞬间建立
6事实上,我们可以在Connect()调用之后等待CAsyncSocket::OnConnect()事件被触发,CAsyncSocket::OnConnect()是要表明Socket要么连接成功了,要么连接彻底失败了。至此,我们在CAsyncSocket::OnConnect()被调用之后就知道是否Socket连接成功了,还是失败了
7特别注意:难点,那就是在客户方调用Connect()连接服务方,那么服务方如何Accept(),以建立连接的问题。简单的做法就是在监听的Socket收到OnAccept()时,用一个新的CAsyncSocket对象去建立连接
重写CAsyncSocket 类
8服务端需要重写2个类?
因为服务端有两类socket,一类是服务器serversock,一类是每来一个连接的socket
C++实现客户端和服务端收发消息的联调
聊天软件111701客户端和服务端收发消息联调
1 connect的问题解决???
m_client->Connect(strIP, iPort) != SOCKET_ERROR
查找这种写法才是正确的
2 如何查找错误 头文件 winerror.h MSDN
10035实际上就是无法立即完成一个非阻止性的套接字操作
14.4 C++实现客户端和服务端整个收发功能的实现
聊天软件111702客户端和服务端收发消息联调编码规范以及代码的简洁性
1收发数据的buf的大小的定义: 不能用魔数 宏定义
#define SEND_MAX_BUF 1024
2 重复的功能一定要封装为函数
CString CMFCChatServerDlg::CatShowString(CString strInfo, CString strMsg)
{
//时间 + 信息(昵称)+消息
CString strTime;
CTime tmNow;
tmNow = CTime::GetCurrentTime();
strTime = tmNow.Format("%X ");
CString strShow;
strShow = strTime + strShow;
strShow += strInfo;
strShow += strMsg;
return strShow;
}
3 beyond compare查看代码的变化
聊天软件配置昵称/自动回复/清除历史记录
1 配置文件的读取与写入
注册表 配置ini
配置昵称的原理
A启动客户端,就应该有个读取配置文件的操作,把昵称从配置文件里面读到控件
B客户配置昵称,需要写入到配置文件
M_list的坑 :sort的属性:自动插入
2清除历史记录
m_list.ResetContent
3 自动回复消息
if (((CButton*)dlg->GetDlgItem(IDC_AUTOSEND_RADIO))->GetCheck())
{
CString strAutoSendMsg;
dlg->GetDlgItem(IDC_AUTOSENDMSG_EDIT)->GetWindowTextW(strAutoSendMsg);
CString strName;
dlg->GetDlgItem(IDC_NAME_EDIT)->GetWindowTextW(strName);
CString strInfo = (CString)"[自动回复]" + strAutoSendMsg;
CHAR *szAutoSendBuf = T2A(strInfo);
dlg->m_client->Send(szAutoSendBuf, 200, 0);
strShow = dlg->CatShowString(strName, strInfo);
dlg->m_list.AddString(strShow);
dlg->m_list.UpdateData(FALSE);
}
完整项目代码
https://download.csdn.net/download/qq_45783660/88712223