分享
 
 
 

Delphi中MediaPlayer控件的一个Bug即修复

王朝delphi·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

最近在使用MediaPlayer控件编程时发现一个奇怪的问题,刚开始百思不得其解,不知道是MediaPlayer的问题,还是Delphi的MMSystem.pas本身就错了

问题如下

MediaPlay.DeviceType的值只能设成dtAutoSelect,否则,不管是AVI,还是MPG文件都不能播放,我用Delphi6 和Delphi6 sp2 在win2000和xp环境下测试,均不能成功。

如果将设备类型设置成明显的错误,MediaPlay控件会报错,如文件是AVI或MPG格式,选择DeviceType=dtCDAudio,会报MCI错误,但是如果用AVI文件,选择dtAVIVideo,则不报任何错误,文件打开,但不管是通过程序,还是通过MediaPlay的Button总之是播放不了文件的,而且MediaPlay.Length的长度也不正确例如:

ExPlay.DeviceType :=dtAVIVideo;

ExPlay.FileName := 'd:\windows\clock.avi';

ExPlay.Open;

ExPlay.Play;

在不得已的情况下我只能去看MediaPlayer的源代码(本人对Delphi实在了解的不多)

分析情况如下

Delphi的TMediaPlayer控件的DeviceType是只能在几种类型中选择,这是在MPlay.pas中定义的几种

TMPDeviceTypes = (dtAutoSelect, dtAVIVideo, dtCDAudio, dtDAT, dtDigitalVideo, dtMMMovie,

dtOther, dtOverlay, dtScanner, dtSequencer, dtVCR, dtVideodisc, dtWaveAudio);

在MCI的定义中有如下结构:

tagMCI_OPEN_PARMSA = record

dwCallback: DWORD;

wDeviceID: MCIDEVICEID;

lpstrDeviceType: PAnsiChar; //设备类型

lpstrElementName: PAnsiChar;

lpstrAlias: PAnsiChar;

end;

在mplay.pas中

procedure TMediaPlayer.Open;

const

DeviceName: array[TMPDeviceTypes] of PChar = ('', 'AVIVideo', 'CDAudio', 'DAT',

'DigitalVideo', 'MMMovie', 'Other', 'Overlay', 'Scanner', 'Sequencer',

'VCR', 'Videodisc', 'WaveAudio');

...设定了实际传给MCI的DeviceType值................

begin

......(mplay.pas lines 841)

OpenParm.lpstrDeviceType := DeviceName[FDeviceType]; // 你选定的设备类型

......

if FDeviceType <> dtAutoSelect then

FFlags := FFlags or mci_Open_Type;

if FDeviceType <> dtAutoSelect then //不明白为什么这里要做两次同样的判断

FFlags := FFlags or mci_Open_Type

else

FFlags := FFlags or MCI_OPEN_ELEMENT; //只有这样才能正确播放,也就是自动模式

OpenParm.dwCallback := Handle;

FError := mciSendCommand(0, mci_Open, FFlags, Longint(@OpenParm)); //。。。。。。

参照上面的情况,我选择DeviceType=dtAVIVideo时传的值就应该是‘AVIVideo’。这也和注册表中的MCI32项中的值对应。为了验证使用lpstrDeviceType的值确实是可以用'AVIVideo'我加载了一个MCI32.OCX,这个控件是在VS6种附带的,其中的DeviceType属性和TMediaPlayer中的DeviceType属性大致相当,只不过MCI32.ocx中的值可以直接指定到设备名,我将MCI32.ocx的DeviceType设成'AVIVideo',结果可以正常播放。

为了找出原因,我将VC的MMSystem.h文件和MMSystem.pas中的参数和数据结构作比较,没有发现有什么差异,基本判断MMSystem,pas是没有问题的,那么问题一定在mplay.pas中了。于是从mplay.pas中另外生成一个控件TDeMediaPlay,跟踪下来,居然也没有发现什么问题,文件打开MCIOpened 、设备号FDeviceID、是否显示FHasVideo等标志正常,GetDeviceCaps函数无异常,唯独GetLength函数中

FError := mciSendCommand( FDeviceID, mci_Status, FFlags, Longint(@StatusParm));

Result := StatusParm.dwReturn;

的返回值不正常,而且居然也没有返回错误,在我的机器上,不管怎么设置timeformat都返回4,您的机器可能会不一样

播放器之类的软件实在是以前没写过,去网上查找关于这方面的Delphi的资料,好像都是让自动选择的也就是dtAutoSelect模式的,但恰恰我的要求是一定要指定具体驱动。

没有办法,再次打开VC,找到一个MCI的例子,仔细阅读,发现了问题,例子中有这样一段代码

mciMO.lpstrDeviceType="MpegVideo";

......

dwFlags=(DWORD)(MCI_OPEN_ELEMENT|MCI_OPEN_TYPE|);

dwResult=mciSendCommand(0,MCI_OPEN,dwFlags, (DWORD)(LPMCI_DGV_OPEN_PARMS) &mciMO);

......

问题好像有了一点头绪,VC代码中dwFlags在指定DeviceType后,并不是仅仅用到了MCI_OPEN_TYPE标志,而是连MCI_OPEN_ELEMENT标志一起带进去的。于是我有回到mplay.pas中,在上面提到的搞不懂为什么两段代码重复的语句中作了修改:

OpenParm.lpstrDeviceType := DeviceName[FDeviceType]; 你选定的设备类型

......

if FDeviceType <> dtAutoSelect then

FFlags := FFlags or mci_Open_Type;

if FDeviceType <> dtAutoSelect then

FFlags := FFlags or MCI_OPEN_ELEMENT 改在此处

else

FFlags := FFlags or MCI_OPEN_ELEMENT;

OpenParm.dwCallback := Handle;

FError := mciSendCommand(0, mci_Open, FFlags, Longint(@OpenParm)); //。。。。。。

重新Build,安装新控件。

测试,为了验证新的控件确实是使用我指定的设备播放,而不是自动选择的设备,我按以下步骤测试

1、我将注册表中所有关于.AVI内说明使用AVIVideo设备播放的项目备份并删除,然后新控件的DeviceType设成dtAutoSelect,提示出错,不能打开MCI设备,这正是我需要的效果,系统已经不能自动识别AVI文件的播放设备了。

2、把新控件的DeviceType设置为dtAVIVideo,播放一切正常。说明新控件确实是用指定的设备播放AVI文件。

结论:

1、很奇怪mplay.pas中怎么会有这样的怪怪的语句,为什么一个条件要判断两次,而且没有实际意义,因为mci_Open_Type or mci_Open_Type结果还是mci_Open_Type。肯定是控件源码的作者有一定的考虑,在修改源码后还是觉得很奇怪,如果是源码作者的笔误,那么根本不应该对条件还判断第三次。只需要改成:

if FDeviceType <> dtAutoSelect then

FFlags := FFlags or MCI_OPEN_TYPE;

FFlags := FFlags or MCI_OPEN_ELEMENT ;

即可。

2、虽然我很赞成在大的项目中用常量代替变量,可是对于DeviceType这样的值,似乎把控制权交给用户比较合适,因为TMPDeviceTypes定义是死的,而系统是活的,像MPEGVideo、MPEGVideo2这样的设备,在TMPDeviceTypes中就没有定义,这一点,我觉得还是MCI32.ocx做的比较好,所以我改写了新的控件可以直接传入设备名,以Open一个媒体文件。

3、感谢宝蓝公司对所有控件提供源码,要是在没有源码的控件中修改,基本是不可能的。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有