基于MFC运用windows media player控件实现的多媒体播放器

合集下载
相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

基于MFC运用windows media player控件实现的多媒体播放器设计平台
PC(windows 7 x64),Visual C++ 6.0
设计框图
一.工程创建
本程序基于MFC的对话框模式,起名为MediaPlayer。

二. 添加Windows Media Player 控件
在对话框的空白处点击右键选择“Insert ActiveX control”,在弹出的对话框中找到Windows Media Player。

(因为Win7系统中没有ActiveMovieControl控件所以就用以上控件代替了。


三.为Windows Media Player 控件设置变量
在已经添加好的控件上单击右键选择“ClassWizard”,在弹出的窗口中切换到“Member Variables”一栏,找到刚刚添加的控件的ID,选中它然后在右侧的按钮中点击“Add Variables”,然后如图所示:
这样就添加成功了。

此时在源文件的对话框中,系统会自动生成必需的媒体实现文件。

四.播放器界面设计
设计的界面如下图所示,其中播放控制按钮有打开文件,播放,暂停,停止,快退,快进,播放列表,全屏,退出,关于。

然后还有音量控制,播放模式,播放进度,列表选项的相关控制器件。

控件ID与变量关联如下:
控件ID 变量类型变量名称
WMPlayer IDC_OCX1 CWMPPlayer4 m_player
ListControl IDC_LIST1 CListCtrl m_listCtrl
Slider IDC_SLIDER1 CSliderCtrl m_schedule
Slider IDC_SLIDER2 CSliderCtrl m_VOLUME Radio Button IDC_ORDER int m_order 按钮控件的ID和对应的响应函数名称如下:
控件名称ID 响应函数名称
打开文件IDC_OPEN OnOpen()
播放IDC_PLAY OnPlay()
暂停IDC_PAUSE OnPause()
停止IDC_STOP OnStop()
快退IDC_REVERSE OnReverse()
快进IDC_FORWARD OnForward()
播放列表IDC_PLAYLIST OnPlayList()
全屏IDC_FULLSCREEN OnFullScreen()
退出IDC_EXIT OnExit()
- IDC_SUB OnSub()
+ IDC_ADD OnAdd()
上一曲IDC_LAST OnLast()
下一曲IDC_NEXT OnNext()
关于IDC_ABOUT OnAbout()
静音IDC_SILENCE OnSlience() 选中项上移IDC_LISTCHOOSEUP OnListchooseup()
选中项下移IDC_LISTCHOOSEDOWN OnListchoosedown()
删除选中项IDC_LISTCHOOSEDELETE OnListchoosedelet()
删除所有项IDC_LISTDELETEALL OnListdeleteall()
导入列表IDC_LISTIMPORT OnListimport()
导出列表IDC_LISTEXPORT OnListexport() 五.功能实现
(1)播放控制
Windows Media Player 控件初始化
在添加该控件的时候自动生成的多个库文件,不同的文件实现播放器各个
方面的功能,所以需要我们手动将他们联系起来。

所以我们要在
MediaPlayerDlg.h头文件中添加如下内容:
添加头文件:
#include "wmpcontrols.h"
#include "wmpsettings.h"
#include "wmpplaylist.h"
#include "wmpmedia.h"
添加公共成员:
CWMPControls m_control;
CWMPSettings m_setting;
CWMPMedia m_media;
在MediaPlayerDlg.cpp的初始化函数BOOL CMediaPlayerDlg::OnInitDialog()
中添加
m_control=static_cast<CWMPControls>(m_player.GetControls());
m_setting=m_player.GetSettings();
m_list=static_cast<CWMPPlaylist>(m_player.GetCurrentPlaylist());
m_media=static_cast<CWMPMedia>(m_player.GetCurrentMedia());
将相应媒体播放控制文件联系起来。

打开文件到播放列表
void CMediaPlayerDlg::OnOpen()
{
m_listCtrl.SetFocus();
CString str;
POSITION pos;
pos = m_listCtrl.GetFirstSelectedItemPosition();
IndexInFieldList = m_listCtrl.GetNextSelectedItem(pos);
m_listCtrl.SetItemState(IndexInFieldList,~LVIS_SELECTED,
LVIS_SELECTED);
TCHAR szFilter[] =
_T("Mp3 File(*.mp3)|*.mp3
|Wma File(*.wma)|*.wma
|Video File(*.dat)|*.dat
|Wave File(*.wav)|*.wav
|AVI File(*.avi)|*.avi
|Movie File(*.mov)|*.mov
|Media File(*.mmm)|*.mmm
|Mid File(*.mid;*,rmi)|*.mid;*.rmi
|MPEG File(*.mpeg)|*.mpeg
|All File(*.*)|*.*||");
CFileDialog fileDlg(TRUE,NULL, NULL,OFN_HIDEREADONLY |
OFN_OVERWRITEPROMPT, szFilter, this);
CString strFilePath;
if (IDOK == fileDlg.DoModal())
{
strFilePath = fileDlg.GetPathName();
strFilePath.MakeUpper();
m_player.SetUrl(strFilePath);
m_media=static_cast<CWMPMedia>(m_player.newMedia(strFilePath));
m_list.appendItem(m_media);
m_listCtrl.InsertItem(0,m_media.GetName());
m_listCtrl.SetItemText(0,1,_T(m_media.getItemInfo("FileType")));
m_listCtrl.SetItemText(0,2,_T(m_media.GetDurationString()));
m_listCtrl.SetItemText(0,3,_T(strFilePath));
m_listCtrl.SetItemText(0,4,_T(m_media.getItemInfo("Duration")));
m_player.SetUrl(m_listCtrl.GetItemText(0,3));
m_listCtrl.SetItemState(0,LVIS_SELECTED,LVIS_SELECTED);
}
}
打开功能实现分为了两个部分,第一部分通过m_player.SetUrl()来取得媒体文件,第二部分是将媒体文件的相关信息添加到右侧的播放列表中去,让列表中的光标始终停留在第一栏的位置。

播放按钮
void CMediaPlayerDlg::OnPlay()
{
if(m_list.GetCount()<=0)
{
MessageBox("列表无文件!","Warning",MB_OK);
spaceflag=1;
}
else
{
if(!finder.FindFile(m_player.GetUrl()))
{
MessageBox("文件不已存在,该列项将被删除!",
"Warning",MB_OK);
CMediaPlayerDlg::OnListchoosedelete();
}
else
{
KillTimer(0);
m_control.play();
if(m_control.GetCurrentPosition()==0)
m_control.SetCurrentPosition(0.01);
SetTimer(0,20,NULL);
spaceflag=0;
}
}
}
播放功能主要是通过控件提供的m_control.play()来实现的。

函数中Timer的设置和后面的播放模式有关,m_control.SetCurrentPosition(0.01)的目的是为了将未播放状态与播放后的停止状态区分开来。

暂停按钮
void CMediaPlayerDlg::OnPause()
{
m_control.pause();
}
停止按钮
void CMediaPlayerDlg::OnStop()
{
KillTimer(0);
m_control.stop();
}
全屏模式
void CMediaPlayerDlg::OnFullscreen()
{
if(m_control.GetCurrentPosition()!=0&&!m_player.GetFullScreen())
{
m_control.pause();
m_player.SetFullScreen(true);
m_control.play();
}
}
全屏模式存在着bug,就是进入到全屏后不能够接收键盘输入字符,否则整个程序会变为未响应状态。

后来有添加了对键盘信息的获取和控制函数来解决这个问题,后面会提到。

快进/退
void CMediaPlayerDlg::OnReverse()
{
double t = m_control.GetCurrentPosition();
m_control.SetCurrentPosition(t=t-10); }
void CMediaPlayerDlg::OnForward()
{
double t = m_control.GetCurrentPosition();
m_control.SetCurrentPosition(t=t+10);
}
虽然"wmpcontrols.h"中有直接快进、退的相关函数,但是视频播放时是无效的,所以就没有用自带的函数来实现。

这里是通过m_control.GetCurrentPosition()来获得播放媒体的当前位置,然后通过m_control.SetCurrentPosition()来设置播放媒体的当前位置为原位置+10或-10来实现快进、退功能。

播放列表的显示和隐藏
void CMediaPlayerDlg::OnPlaylist()
{
flag=!flag
if(flag)
{
SetWindowPos(NULL,0,0,440,505,SWP_NOMOVE);
}
else
{
SetWindowPos(NULL,0,0,760,505,SWP_NOMOVE);
}
}
从函数内容可以看出,播放列表的显示和隐藏是通过设置主窗体的大小来实现
的。

其中flag为bool型的全局变量,初值为false。

当按下播放列表的按钮时
会执行SetWindowPos(NULL,0,0,420,454,SWP_NOMOVE);无相对移动,窗口缩小
列表隐藏。

执行另一语句时列表又会显示出来。

(2)音量控制
静音
void CMediaPlayerDlg::OnSilence()
{
if(!m_setting.GetMute())
m_setting.SetMute(true);
else
m_setting.SetMute(false);
}
通过调用函数m_setting.GetMute()获取当前是否处于静音状态,通过
m_setting.SetMute(false/true)设置是否静音。

加减音量
void CMediaPlayerDlg::OnAdd()
{
m_setting.SetVolume(m_setting.GetVolume()+10);
//获得当前音量大小,并设置当前音量为原音量大小+10
m_VOLUME.SetPos(m_setting.GetVolume());
//设置滑动条位置
}
void CMediaPlayerDlg::OnSub()
{
int Volume=m_setting.GetVolume();
m_setting.SetVolume(Volume=Volume-10);
//获得当前音量大小,并设置当前音量为原音量大小+10
m_VOLUME.SetPos(m_setting.GetVolume());
//设置滑动条位置
}
加减音量也可以通过调用相应的成员函数来实现。

在按下“+”、“-”按钮时,
滑动条也会做出相对应的动作,滚动条需要初始化,会在下面的播放进度中详
细说明。

(3)播放模式
上/下一曲
void CMediaPlayerDlg::OnLast()
{
// TODO: Add your control notification handler code here
m_listCtrl.SetFocus();
POSITION pos;CString strName;
UINT flag1 = LVIS_SELECTED|LVIS_FOCUSED;
pos = m_listCtrl.GetFirstSelectedItemPosition();
IndexInFieldList = m_listCtrl.GetNextSelectedItem(pos);
if(IndexInFieldList == -1)
{
AfxMessageBox("列表内没有被选中项!");
return;
}
if(IndexInFieldList == 0)
{
AfxMessageBox("已经到了列表头部!");
m_listCtrl.SetItemState(IndexInFieldList, flag1, flag1);
return;
}
m_listCtrl.SetItemState(IndexInFieldList,~LVIS_SELECTED,LVIS_SELECTED);
m_listCtrl.SetItemState(IndexInFieldList-1, flag1, flag1);
strName=m_listCtrl.GetItemText(IndexInFieldList-1,3);
CMediaPlayerDlg::OnStop();
m_player.SetUrl(strName);
CMediaPlayerDlg::OnPlay();
}
void CMediaPlayerDlg::OnNext()
{
// TODO: Add your control notification handler code here
m_listCtrl.SetFocus();
POSITION pos;CString strName;
UINT flag1 = LVIS_SELECTED|LVIS_FOCUSED;
pos = m_listCtrl.GetFirstSelectedItemPosition();
IndexInFieldList = m_listCtrl.GetNextSelectedItem(pos);
if(IndexInFieldList == -1)
{
AfxMessageBox("列表内没有被选中项!");
return;
}
if(IndexInFieldList == m_listCtrl.GetItemCount()-1)
{
AfxMessageBox("已经到了列表末尾!");
m_listCtrl.SetItemState(IndexInFieldList, flag1, flag1);
return;
}
m_listCtrl.SetItemState(IndexInFieldList,~LVIS_SELECTED,LVIS_SELECTED);
m_listCtrl.SetItemState(IndexInFieldList+1, flag1, flag1);
strName=m_listCtrl.GetItemText(IndexInFieldList+1,3);
CMediaPlayerDlg::OnStop();
m_player.SetUrl(strName);
CMediaPlayerDlg::OnPlay();
}
上/下一曲的功能主要是通过移动播放列表中的光标来实现的。

如上一曲的功能实现过程为:IndexInFieldList获得列表光标当前位置,通过析构函数m_listCtrl.SetItemState(IndexInFieldList,~LVIS_SELECTED,LVIS_SELECTED)使本行光标消失,通过函数m_listCtrl.SetItemState(IndexInFieldList-1, flag1, flag1)使光标显示在下一行的位置,strName=m_listCtrl.GetItemT ext(IndexInFieldList-1,3)获得光标所在行第四栏的信息,在这里也就是列表中媒体文件的路径,然后再调用相关函数来进行播放。

四种播放模式(顺序播放、随机播放、全曲循环、单曲循环)首先我们需要定义一个Botton Group,在四个Radio Button选择一个单击右键,在弹出菜单中选择“ClassWizard”,翻到“Member Variables”,找到刚刚选择的Radio Button的ID,“Add Bariables”添加一个int型的成员m_order,如图所示:
然后再在MediaPlayerDlg.cpp中填写各个Radio Button函数中的内容:
void CMediaPlayerDlg::OnOrder()
{
//顺序播放
m_order=0;
}
void CMediaPlayerDlg::OnRandom()
{
// 随机播放
m_order=1;
}
void CMediaPlayerDlg::OnAllcircle()
{
//全曲循环
m_order=2;
}
void CMediaPlayerDlg::OnSinglecircle()
{
// 单曲循环
m_order=3;
}
之前在ClassWizard中已经添加好了OnTimer成员。

这时我们要把它联合起来使用:
(关键代码)
CMediaPlayerDlg::OnTimer(UINT nIDEvent)
{//计时器的选择代码省略
switch(m_order)
{
case 0:
{
KillTimer(0);
POSITION pos;
pos = m_listCtrl.GetFirstSelectedItemPosition();
IndexInFieldList = m_listCtrl.GetNextSelectedItem(pos);
m_listCtrl.SetFocus();
if(IndexInFieldList == m_listCtrl.GetItemCount()-1)
{
m_listCtrl.SetItemState(IndexInFieldList, LVIS_SELECTED,LVIS_SELECTED);
m_control.stop();
return;
}
m_listCtrl.SetItemState(IndexInFieldList,~LVIS_SELECTED,
LVIS_SELECTED);
m_listCtrl.SetItemState(IndexInFieldList+1, LVIS_SELECTED,LVIS_SELECTED);
CString strName=m_listCtrl.GetItemText(IndexInFieldList+1,3);
m_player.SetUrl(strName);
CMediaPlayerDlg::OnPlay();
break;
}
case 1:
{
KillTimer(0);
m_listCtrl.SetFocus();
POSITION pos;
pos = m_listCtrl.GetFirstSelectedItemPosition();
IndexInFieldList = m_listCtrl.GetNextSelectedItem(pos);
m_listCtrl.SetItemState(IndexInFieldList,~LVIS_SELECTED,
LVIS_SELECTED);
int i;
srand((unsigned)time( NULL ));
i=rand()%m_listCtrl.GetItemCount();
m_listCtrl.SetItemState(i, LVIS_SELECTED,LVIS_SELECTED);
CString strName=m_listCtrl.GetItemText(i,3);
m_player.SetUrl(strName);
CMediaPlayerDlg::OnPlay();
break;
}
case 2:
{
KillTimer(0);
POSITION pos;
pos = m_listCtrl.GetFirstSelectedItemPosition();
IndexInFieldList = m_listCtrl.GetNextSelectedItem(pos);
m_listCtrl.SetFocus();
if(IndexInFieldList == m_listCtrl.GetItemCount()-1)
{
IndexInFieldList=-1;
}
m_listCtrl.SetItemState(IndexInFieldList,~LVIS_SELECTED,
LVIS_SELECTED);
m_listCtrl.SetItemState(IndexInFieldList+1, LVIS_SELECTED,
LVIS_SELECTED);
CString strName=m_listCtrl.GetItemText(IndexInFieldList+1,3);
m_player.SetUrl(strName);
CMediaPlayerDlg::OnPlay();
break;
}
case 3:
{
KillTimer(0);
m_control.SetCurrentPosition(0.01);
m_control.play();
SetTimer(0,20,NULL);
break;
}
default:
{
KillTimer(0);
break;
}
}
各种播放模式的实现都是通过对播放列表进行操作来实现的。

具体来讲就是通
过控制列表中的光标的移动来获取光标所在行的相关信息。

(4)播放进度
滚动条和数值显示
因为他们共同构成一个整体,又在同一个OnTimer()函数中,所以就合起来说
明。

首先为IDC_SLIDER1添加CSliderCtrl类型的成员m_schedule;
然后是滚动条的初始化,在MediaPlayerDlg.cpp的OnInitDialog()中添加语句:m_schedule.SetRange(0,200,false);
m_schedule.SetTicFreq(1);
m_schedule.SetLineSize(1);
m_schedule.SetPos(0);
最后在对OnTimer()进行编辑:
void CMediaPlayerDlg::OnTimer(UINT nIDEvent)
{
switch(nIDEvent)
{
case 0:
{
If(m_control.GetCurrentPosition()==0);
SetDlgItemText(IDC_CURRENT,"00:00");
SetDlgItemText(IDC_DURATION,"00:00");
//下面是有关播放模式的代码,在这里省略
//……
POSITION pos;double td;
pos = m_listCtrl.GetFirstSelectedItemPosition();
IndexInFieldList = m_listCtrl.GetNextSelectedItem(pos);
td=_ttol(m_listCtrl.GetItemText(IndexInFieldList,4));
m_schedule.SetPos(
(int)((m_control.GetCurrentPosition()/td)*200));
SetDlgItemText(IDC_DURATION,
m_listCtrl.GetItemText(IndexInFieldList,2));
SetDlgItemText(IDC_CURRENT,
m_control.GetCurrentPositionString());
break;
}
}
CDialog::OnTimer(nIDEvent);
}
此处的nIDEvent就是你前面设置的Timer的编号,当编号为0的时候就执行下
面的语句。

SetDlgItemText()让媒体的当前播放的位置和总长度以数值的形式显
示出来。

(5)列表选项
选中项上下移动
void CMediaPlayerDlg::OnListchooseup()
{
// TODO: Add your control notification handler code here
m_listCtrl.SetFocus();
POSITION pos;
int num;
CString name;
CString form;
CString length;
CString strName;
CString duration;
UINT flag1 = LVIS_SELECTED|LVIS_FOCUSED;
pos = m_listCtrl.GetFirstSelectedItemPosition();
IndexInFieldList = m_listCtrl.GetNextSelectedItem(pos);
if(IndexInFieldList == -1)
{
AfxMessageBox("列表内没有被选中项!");
return;
}
if(IndexInFieldList == 0)
{
AfxMessageBox("已经到了列表头部!");
m_listCtrl.SetItemState(IndexInFieldList, flag1, flag1);
return;
}
num=IndexInFieldList;
name=m_listCtrl.GetItemT ext(num,0);
form=m_listCtrl.GetItemText(num,1);
length=m_listCtrl.GetItemText(num,2);
strName=m_listCtrl.GetItemText(num,3);
duration=m_listCtrl.GetItemText(num,4);
m_listCtrl.DeleteItem(num);
m_listCtrl.InsertItem(num-1,_T(name));
m_listCtrl.SetItemText(num-1,1,_T(form));
m_listCtrl.SetItemText(num-1,2,_T(length));
m_listCtrl.SetItemText(num-1,3,_T(strName));
m_listCtrl.SetItemText(num-1,4,_T(duration));
m_listCtrl.SetItemState(IndexInFieldList-1, flag1, flag1); }
void CMediaPlayerDlg::OnListchoosedown()
{
// TODO: Add your control notification handler code here m_listCtrl.SetFocus();
POSITION pos;
int num;
CString name;
CString form;
CString length;
CString strName;
CString duration;
UINT flag1 = LVIS_SELECTED|LVIS_FOCUSED;
pos = m_listCtrl.GetFirstSelectedItemPosition();
IndexInFieldList = m_listCtrl.GetNextSelectedItem(pos);
if(IndexInFieldList == -1)
{
AfxMessageBox("列表内没有被选中项!");
return;
}
if(IndexInFieldList == m_listCtrl.GetItemCount()-1)
{
AfxMessageBox("已经到了列表末尾!");
m_listCtrl.SetItemState(IndexInFieldList, flag1, flag1);
return;
}
num=IndexInFieldList;
name=m_listCtrl.GetItemT ext(num,0);
form=m_listCtrl.GetItemText(num,1);
length=m_listCtrl.GetItemText(num,2);
strName=m_listCtrl.GetItemText(num,3);
duration=m_listCtrl.GetItemText(num,4);
m_listCtrl.DeleteItem(num);
m_listCtrl.InsertItem(num+1,_T(name));
m_listCtrl.SetItemText(num+1,1,_T(form));
m_listCtrl.SetItemText(num+1,2,_T(length));
m_listCtrl.SetItemText(num+1,3,_T(strName));
m_listCtrl.SetItemText(num+1,4,_T(duration));
m_listCtrl.SetItemState(IndexInFieldList+1, flag1, flag1);
}
该功能和上下一曲的实现方法很相似。

将光标所在行的信息通过临时变量记录下来,之后将该行删除,再通过m_listCtrl.InsertItem()、m_listCtrl.SetItemText()将临时变量记录下来的信息插入到前一行或后一行中去并让光标停留在该行。

删除选中项
void CMediaPlayerDlg::OnListchoosedelete()
{
// TODO: Add your control notification handler code here
m_listCtrl.SetFocus();
POSITION pos;CString strname;
int num;
UINT flag1 = LVIS_SELECTED|LVIS_FOCUSED;
pos = m_listCtrl.GetFirstSelectedItemPosition();
IndexInFieldList = m_listCtrl.GetNextSelectedItem(pos);
if(IndexInFieldList == -1)
{
AfxMessageBox("列表内没有被选中项!");
return;
}
num=IndexInFieldList;
m_listCtrl.DeleteItem(num);
CMediaPlayerDlg::OnStop();
if(m_listCtrl.GetItemCount()!=0)
{
if(IndexInFieldList == m_listCtrl.GetItemCount())
{
m_listCtrl.SetItemState(IndexInFieldList-1, flag1, flag1);
strname=m_listCtrl.GetItemText(IndexInFieldList-1,3);
m_player.SetUrl(strname);
}
else
{
m_listCtrl.SetItemState(IndexInFieldList, flag1, flag1);
strname=m_listCtrl.GetItemText(IndexInFieldList,3);
m_player.SetUrl(strname);
}
CMediaPlayerDlg::OnPlay();
}
}
删除选中项通过m_listCtrl.DeleteItem(),不过要注意删完该行后光标应停留在哪里的问题。

如果删除行不是最后一行,那么光标可以停留在下一行,如何是删除的最后一行,那么光标应该停留在上一行。

删除所有项
void CMediaPlayerDlg::OnListdeleteall()
{
// TODO: Add your control notification handler code here
CMediaPlayerDlg::OnStop();
int m=m_listCtrl.GetItemCount(),i;
for(i=m-1;i>=0;i--)
{
m_listCtrl.DeleteItem(i);
}
}
获得列表中的行数,从最后一行往上逐行删除。

导入列表
void CMediaPlayerDlg::OnListimport()
{
// TODO: Add your control notification handler code here
m_listCtrl.SetFocus();
TCHAR szFilter[] = _T("列表文件(*.list)|*.list||");
// 构造打开文件对话框
CFileDialog fileDlg(TRUE, _T("list"), NULL, 0, szFilter, this);
CString strFilePath;
// 显示打开文件对话框
if (IDOK == fileDlg.DoModal())
{
// 如果点击了文件对话框上的“打开”按钮,则将选择的文件路径
显示到编辑框里
strFilePath = fileDlg.GetPathName();
}
CStdioFile file;int i;
if(file.Open(strFilePath,CFile::modeRead|CFile::typeText))
{
POSITION pos;
pos = m_listCtrl.GetFirstSelectedItemPosition();
IndexInFieldList = m_listCtrl.GetNextSelectedItem(pos);
m_listCtrl.SetItemState(IndexInFieldList,
~LVIS_SELECTED,LVIS_SELECTED);
file.SeekToBegin();
CString str;CString strtemp[6];
while(file.ReadString(str))
{
for(i=0;i<5;i++)
AfxExtractSubString(strtemp[i],str,i,'|');
m_listCtrl.InsertItem(0,strtemp[0]);
m_listCtrl.SetItemText(0,1,_T(strtemp[1]));
m_listCtrl.SetItemText(0,2,_T(strtemp[2]));
m_listCtrl.SetItemText(0,3,_T(strtemp[3]));
m_listCtrl.SetItemText(0,4,_T(strtemp[4]));
m_player.SetUrl(strtemp[3]);
m_media=static_cast<CWMPMedia>(
m_player.newMedia(strFilePath));
m_list.appendItem(m_media);
}
m_player.SetUrl(m_listCtrl.GetItemText(0,3));
m_listCtrl.SetItemState(0,LVIS_SELECTED,LVIS_SELECTED);
}
else
{
TRACE("Can't open list file!");
}
file.Close();
}
找到要导入的列表文件,虽然把文件的后缀名改为了list,实际上还是文本文件,只是为了与其他的非列表文本文件区分开来。

通过file.ReadString(str)逐行读取list文件内容。

通过AfxExtractSubString(strtemp[i],str,i,'|'),将字符串流切分成几个小的字符串,记录在数组中,再导入列表里面。

如图是以文本文件格式打开的list文件:
导出列表
void CMediaPlayerDlg::OnListexport()
{
// TODO: Add your control notification handler code here
TCHAR szFilter[]=_T("列表文件(*.list)|*.list||");
CFileDialog fileDlg(FALSE,_T("list"),NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter, this);
CString strFilePath;
if (IDOK == fileDlg.DoModal())
{
// 如果点击了文件对话框上的“保存”按钮,则将选择的文件路径
显示到编辑框里
strFilePath = fileDlg.GetPathName();
}
CStdioFile file;int i,j;
if(file.Open(strFilePath,CFile::modeCreate|CFile::modeReadWrite|
CFile::typeText))
{
for(i=m_listCtrl.GetItemCount()-1;i>=0;i--)
{
CString temp;
for(j=0;j<4;j++)
{
temp=m_listCtrl.GetItemText(i,j);
temp+="|";
file.WriteString(temp);
}
temp=m_listCtrl.GetItemText(i,j);
temp+="\n";
file.WriteString(temp);
}
file.Close();
}
else
{
TRACE("Can't Open File");
}
}
前半部分获取保存路径,后半部分将列表信息写入到该路径下的文件中。

(6)获取按键信息
在”ClassWizard”中的”Message Maps”页面为”CMediaPlayerDlg”添加”Member
functions”:PreTranslateMessage如图所示。

再添加如下代码:
BOOL CMediaPlayerDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
if(pMsg->message==WM_KEYDOWN)
{
switch(pMsg->wParam)
{
case VK_ESCAPE:
{//ESC键
if(m_control.GetCurrentPosition()!=0&&
m_player.GetFullScreen())
m_player.SetFullScreen(false);
else
SendMessage(WM_CLOSE);
return TRUE;
break;
}
case VK_SPACE:
{//空格键
if(spaceflag==0)
CMediaPlayerDlg::OnPause();
else
if(spaceflag==1)
CMediaPlayerDlg::OnPlay();
return TRUE;
break;
}
case VK_LEFT:
{//←键
CMediaPlayerDlg::OnReverse();
return TRUE;
break;
}
case VK_RIGHT:
{//→键
CMediaPlayerDlg::OnForward();
return TRUE;
break;
}
case VK_PRIOR:
{//PageUp键
CMediaPlayerDlg::OnLast();
return TRUE;
break;
}
case VK_NEXT:
{//PageDown键
CMediaPlayerDlg::OnNext();
return TRUE;
break;
}
case VK_UP:
{//↑键
CMediaPlayerDlg::OnAdd();
return TRUE;
break;
}
case VK_DOWN:
{//↓键
CMediaPlayerDlg::OnSub();
return TRUE;
break;
}
default:
return TRUE;
break;
}
}
return CDialog::PreTranslateMessage(pMsg);
}
到此,全屏不能碰键盘的bug被修复了,并且也可以通过键盘进行媒体播放操作,特别是在全屏播放视频文件的时候。

实验结果(1)音乐播放测试
(2)视频播放测试
(3)列表导入测试
(4)列表导出测试
相关代码及工程文件下载:
/share/link?shareid=1420842405&uk=3425060786 2013-6-30。

相关文档
最新文档