初来乍到,接触到音视频领域,在这期间参考开源代码和项目代码,用C++做了一个类似QQ的视频聊天Demo,这里将其中开源的视频通讯技术分享给大家。
工具: vs2010,MFC制作界面,网络传输机制(Socket等),
VFW视频采集,FFmpeg编解码器,SDL播放
选择做聊天软件,首先要选取一个界面工具,做界面可不是底层的C++语言的强项,传统的有微软的MFC,比较庞大,开源的有QT、DirectUI,做出界面很炫,使用也比较简单。但为配合vs2010,还是选择了MFC这种适合底层语言的界面工程。
话不多说,直接上图:
怎么样,用MFC也可以做出很炫的界面的。以上两个界面,可以理解一个客户端,一个服务端,客户端登录服务器与其连接,然后两者互发消息进行聊天。
该聊天软件的主要功能有:
登录
文字聊天
表情聊天
文件传输
视频聊天
下面介绍几种实用的功能,基础功能大家自己找资料补一下。
在Properties面板上添加一个编辑框(Edit Control),右键点击属性,修改ID,选上multiline、vertical scroll 和Auto Vscroll属性,添加滚动条并且实现自动换行;如果要实现滚动条自动回滚到最下方,可添加如下代码(m_edit为该编辑框的Control变量)
m_edit.LineScroll(m_edit.GetLineCount());
依次创建发送框、接收框,分别为其添加CString型数值变量m_editInput、m_editOutput,创建send按钮,聊天软件要实现的功能是:
(1)发送框输入的内容保存起来,通过网络发送出去
(2)发送框的内容显示到接收框上
参考代码如下:
void CclientDlg::OnBnClickedSendButton()
{
UpdateData(TRUE);
Send(m_editInput); //网络发送函数,需自己实现
m_editOutput = m_editOutput + "\r\n 我:" +m_editInput;
m_editInput = ""; //清空发送框
UpdateData(FALSE);
m_editOutput.LineScroll(m_editOutput.GetLineCount());
}
如果要向对方发送文件,我们希望实现这样的功能:
点击”文件“图标按钮,弹出文件对话框,然后在本地计算机中选择文件,发送出去。
MFC封装了文件对话框类CFileDialog,通过调用类函数,实现发送文件功能,看下面:
void CclientDlg::OnBnClickedFileButton()
{
//设置过滤器
TCHAR szFilter[] = _T("文本文件(*.txt)|*.txt|所有文件(*.*)|*.*||");
// 构造打开文件对话框
CFileDialog fileDlg(TRUE,_T("txt"),NULL,0,szFilter,this);
CString strFilePath,strText;
// 显示打开文件对话框
if (IDOK == fileDlg.DoModal())
{
TFileInfo tempFileInfo;
strFilePath = fileDlg.GetPathName(); //获取文件路径
SetDlgItemText(IDC_INPUT_EDIT,strFilePath+" 正在上传...");
CStdioFile file2;
if(!file2.Open( strFilePath ,CFile::modeRead)) //打开文件
return;
while(true)//按行循环读取文件内容存入strText
{
if(!file2.ReadString(strText))
break;
Send(strText); //发送出去
}
}
}
当然这里只是最简单的文本文件,如果是图片、视频等文件,可以借用网络传输工具Socket实现,在项目中,我有很好的网络传输工具,直接拿来用了。
为了界面美观,有时我们需要为按钮添加相应的图片,如表情位图、文件位图、视频位图,以及通过点击按钮实现位图的切换,如暂停、取消位图。接下来就介绍为按钮添加位图的方法。
1. 对话框上创建按钮资源IDC_BUTTON时选择 owner draw (自己画);
(注:选择自画时,Bitmap属性一定要设置False,不然会出错)
2. 在对话框.h文件内定义位图按钮对象 CBitmapButton m_button;
3. 导入准备好的位图到资源中,并修改ID (如:IDB_START);
4. 在初始化函数 BOOL CclientDlg::OnInitDialog() 中 添加如下代码:
{
BOOL start = 0;
m_button.LoadBitmaps(IDB_START,IDB_PAUSE);
m_button.SubclassDlgItem(IDC_PAUSE_BUTTON,this);
m_button.SizeToContent();
}
如果我们想通过点击按钮,实现两种位图的切换,可以这样实现:
void CclientDlg::OnBnClickedPauseButton()
{
//转换开始、暂停图标
if(!start)
{
m_button.LoadBitmaps(IDB_START); //切换到开始
m_button.SizeToContent();
start = 0;
}
else
{
m_button.LoadBitmaps(IDB_PAUSE); //切换到暂停
m_button.SizeToContent();
start = 1;
}
//记得刷新按钮
Invalidate();
}
在文件上传时,当我们想知道上传的进度,可以通过绘制进度条类实现。
进度条控制在MFC类库中的封装类为CProgressCtrl,通常仅作为输出类控制,所以其操作主要是设置进度条的范围和当前位置,并不断地更新当前位置。过程很简单,可以实现基本的显示功能,如下:
1. 对话框上添加一条进度条IDC_PROGRESS 和一个静态文本框 IDC_STATIC
2. 在对话框.h文件内定义进度条对象 CProgressCtrl MyProCtrl;
3. 对话框.cpp文件中绑定对象:
void CclientDlg::DoDataExchange(CDataExchange* pDX)
{
DDX_Control(pDX, IDC_PROGRESS_up, MyProCtrl);
}
4. OnInitDialog()进度条初始化
MyProCtrl.SetRange(0,100);
MyProCtrl.SetPos(0);
5. 计算上传进度百分比Rate,然后这样
{
MyProCtrl.SetPos(lParamRate*100); //进度条移动
CString str;
str.Format(_T("%d%%"),lParamRate*100);
GetDlgItem(IDC_STATIC2)->SetWindowText(str); //显示百分比
if (lParamRate == 1) //上传结束时,更新图标
{
m_button.LoadBitmaps(IDB_START);
m_button.SizeToContent();
start = 0;
Invalidate();
}
}
进一步,如果想实现类似QQ表情的聊天形式,可以进一步实现,过程就有点麻烦了,还好有大神们的”前车之鉴“,MFC RichEdit就是比较好的工具,做出来也很炫,感兴趣的可以点开参考:
CRichEditCtrlEx支持静态表情聊天类的使用
向Richedit插入动态Gif的实现(关于QQ表情功能的制作)
先写到这里吧,本来是想写关于视频聊天传输的东西的,前边的聊天界面就介绍了这么多,下一章接着写视频传输,先放两张图片感受下效果,哈哈。。