VFP 探讨之 OLE 控件(五):多媒体控制器(下)
这期聊聊用简易媒体播放器如何放音乐。前面几期说过,Microsoft Multimedia Control不能播放MP3,我们以播放WAVE文件为例来聊。既然是播放音乐文件了,就要碰到一些问题:让使用者选择文件夹;搜索使用者指定的文件夹(是否含子文件夹);如何让音乐文件连续播放(模拟CD播放器的播放方式)等。当然,要做得更到位点么,还可以增加一些功能,比如:搜索过程中的提示信息;播放时的进度信息;允许使用者拖动音乐的播放点;允许使用者选择音乐文件进行播放等。现在就说说这些问题如何解决。首先,在单选钮“数字音频播放器”的Click事件中设置:MMC.播放器.DeviceType="Waveaudio"。
如何让使用者选择文件夹?
可以做一个按钮,Caption设置为“浏览…”,然后利用FoxPro的函数GETDIR()打开对话框让使用者进行选择。这个函数的使用方法可以参阅帮助文件,这里只提醒一个问题:如果没有选择任何文件夹(点击了“取消”钮、按了ESC键,或从控件菜单上选择了“关闭”命令),该函数将返回空字符串。即使之前变量已经赋过值,也会被清空。
浏览.Click事件中的部分代码:
音频主目录=GETDIR("","选择一个包含音频文件的主目录","选择文件夹",16+32+64)
IF EMPTY(音频主目录) THEN
MMC.路径显示.Value=当前目录
音频主目录=当前目录
ELSE
MMC.路径显示.Value=音频主目录
ENDIF
如何搜索使用者指定的文件夹(是否含子文件夹)?
做一个复选框,用来对是否包含子文件夹作选择。再做一个扫描音频文件的按钮,用来对指定文件夹进行扫描。在本例中,该按钮的Caption属性设置为“扫描音频文件”,Name设置为“扫描”。扫描文件其实是利用了FoxPro的ADIR()函数,该函数既能返回找到的文件数,又能在数组中存储找到的文件名。关于该函数的详细用法请参阅帮助文件。
如果设置了不包含子文件夹,则该按钮的功能比较简单,只需在指定的文件夹中查找;若设置了包含子文件夹,就要设计一个递归过程进行文件夹的遍历操作,把每个子文件夹中的所有.wav音频文件都找出来。由于在表单的事件代码中不允许定义过程,所以需要编写一个PRG文件,其中定义一个过程,用来遍历文件夹找音频文件。本例建立了一个Findwav.prg文件,该文件中没有调用代码(由“扫描.Click”事件代码调用该文件里的过程),只定义了一个名为“SearchWAV”的过程,以下是该过程的代码:
PROCEDURE SearchWAV(DirName)
LOCAL Subdirs,I,SubdirArray[1,1],WAVsOfDir,FilesOfDir[1,1]
CD (DirName)
MMC.扫描提示.Caption="正在扫描:"+DirName
WAVsOfDir=ADIR(FilesOfDir,"*.WAV")
WAVs=WAVs+WAVsOfDir
MMC.Label1.Caption="已经找到"+ALLTRIM(STR(WAVs,10))+"首曲目"
MMC.Label1.ForeColor=RGB(0,0,255)
IF WAVsOfDir>0 THEN &&如果当前目录有音频文件,就汇总起来
PUBLIC WAVFiles[WAVs],WAVFilesDir[WAVs]
FOR I=WAVs-WAVsOfDir+1 TO WAVs
**************************
*汇总:第一列放文件夹名,*
* 第二列放音频文件名*
**************************
WAVFilesDir[I]=DirName
WAVFiles[I]=JUSTSTEM(FilesOfDir[I-(WAVs-WAVsOfDir),1])
NEXT
ENDIF
IF MMC.含子文件夹.Value THEN
Subdirs=ADIR(SubdirArray,"","D") &&搜集子目录
FOR I=1 TO Subdirs
IF SubdirArray[I,1]="." OR SubdirArray(I,1)=".."
LOOP &&跳过搜集到的“.”和“..”目录
ENDIF
DO SearchWAV WITH DirName+SubdirArray[I,1]+'\'
ENDFOR
ENDIF
RETURN
ENDPROC
红色的那条语句就是递归调用。关于利用递归调用遍历文件夹的详细介绍可以参阅本人写的《FoxPro 9.0入门手册(2014第四次修订版)》一书中第九章第237页的实例2。
如何显示搜索过程中的提示信息?
这个问题解决起来很简单:新建一个标签,给它的占用空间大一点,然后在遍历到每个文件夹时给该标签的Caption属性赋当前文件夹名称的值。如此一来,当遍历到不同文件夹时,它在表单上就有滚动显示遍历到的文件夹名字这个效果了。
如何象CD一样连续播放音频文件?
思路是这样的:利用“多媒体控制器(上)”提到过的UpdateInterval属性和StatusUpdate事件配合起来实时探测当前音频文件是否已经播放完,如果播放完,则调用“下一首”按钮的Click事件接下去播放。“下一首”按钮的Click事件代码除了要考虑播放下一首曲目外,还要考虑循环播放的问题,即,当前若是最后一首曲目,播放完后将跳转到第一首曲目接着播放。UpdateInterval属性一般用默认值1000就好,设置得太小会给拖曳定位播放点带来困难。
StatusUpdate事件代码如下:
IF 播放类型=2 THEN &&播放音频文件时
MMC.进度条.Value=MMC.播放器.Position
IF This.Position=This.Length &&如果已经播放到尽头
MMC.下一首.Click
ENDIF
ENDIF
“下一首”按钮的Click事件代码如下:
WITH MMC
IF 播放类型=1 THEN &&如果播放的是CD
.播放器.Command='Next'
ELSE &&如果播放的是音频
IF .播放器.Mode>524 THEN &&如果处在播放停止状态
.播放器.Command='Close'
ENDIF
IF .光驱列表.ListIndex=.光驱列表.ListCount THEN &&已经是最后一首曲目
.光驱列表.ListIndex=1 &&循环进到第一首
ELSE
.光驱列表.ListIndex=.光驱列表.ListIndex+1
ENDIF
.光驱列表.DisplayValue=WAVFiles[.光驱列表.ListIndex]
.播放器.FileName=WAVFilesDir[.光驱列表.ListIndex]+;
WAVFiles[.光驱列表.ListIndex]+".WAV"
.Label1.Caption=WAVFilesDir[.光驱列表.ListIndex]
.Label1.ForeColor=RGB(0,0,0)
.播放.Click
ENDIF
ENDWITH
如何允许使用者选择音乐文件进行播放?
其实光驱列表不止担任让使用者选择光驱盘符这一个角色,它还在播放音频时担任着让使用者选择音频文件的职务。只要使用者在光驱列表中选择了一个音频文件,播放器就立即切换到该音频进行播放。在“多媒体控制器(中)”曾经列出过光驱列表.Click事件的上半部分,也就是CD播放部分,本次就列出它的下半部分,即,音频播放部分。
光驱列表.Click事件代码如下:
IF 播放类型=1 THEN &&放CD时
… …
ELSE &&放音频文件时
IF MMC.播放器.Mode>524 THEN
MMC.播放器.Command='close'
ENDIF
This.DisplayValue=WAVFiles[This.ListIndex]
WITH MMC
.播放器.FileName=WAVFilesDir[This.ListIndex]+;
WAVFiles[This.ListIndex]+".WAV"
.Label1.Caption=WAVFilesDir[This.ListIndex]
.Label1.ForeColor=RGB(0,0,0)
.播放.Click
ENDWITH
ENDIF
关于如何显示播放时的进度信息,如何允许使用者拖动音乐的播放点,下一次介绍滑杆控件的时候再聊。