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

最近在使用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:windowsclock.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、感谢宝蓝公司对所有控件提供源码,要是在没有源码的控件中修改,基本是不可能的。             


数据挖掘研究院

[数据挖掘专家] [数据挖掘研究院] [数据挖掘论坛] [数据挖掘实验室]
上一篇:游戏开发者社区对底层API的投票
下一篇:Delphi版OpenGL样例代码导游
最新评论共有 0 位网友发表了评论 , 查看所有评论
发表评论( 不能超过250字,需审核,请自觉遵守互联网相关政策法规。 )
匿名?
数据挖掘网站导航 数据挖掘论坛导航
  • 数据挖掘工具
  • 数据挖掘论坛
  • DataCruncher - Cognos
  • MineSet - MathSoft
  • Intelligent Miner - GainSmarts
  • Sqlserver - SAS - Clementine
  • CART - Weka - WizSoft
  • NeuroShell - ModelQuest
  • data mining tools - Darwin
  • 数据挖掘交友
  • 数据挖掘博客
  • 数据挖掘工具
  • 数据挖掘资源
  • 数据挖掘技术算法
  • 数据挖掘相关期刊、会议
  • 研究院联盟合作专区
  • 数据挖掘基础与相关技术
  • 数据挖掘厂商与就业
  • 数据挖掘研究者乐园
  • 知名厂商数据挖掘工具资料
  • 国内数据挖掘实验室
  • Foreign Data Mining Lab
  • 热点关注
  • GDI+简介
  • COM与DCOM的区别与联系
  • 使用Delphi解析XML 文档
  • 如何设置delphi/cbuilder/BDE/MSSQL
  • BORLAND在“迫害”程序员?
  • 将image的图片保存为JPG格式图片方法
  • InstallShieldExpressfordelphi制作安装程
  • Real Programmers Use Pascal
  • 关于在COM中使用可选参数的研究
  • TStrings的AddObject方法应用
  • 论坛最新话题
  • Foundations of Statistical Natural Langu
  • Game Theory meet Data Mining: A Recent P
  • System Building: How does it help or hin
  • 数据挖掘与Clementine培训
  • 新手报到
  • 求 SASEM 客户流失预测分析
  • 数据挖掘工程师/搜索研究院—北京——无线
  • 数据挖掘入门介绍(如何着手数据挖掘)
  • Information Overload Survey Results
  • The INEX 2005 Workshop on Element Retrie
  • 相关资讯
  • BORLAND在“迫害”程序员?
  • 李维:我的回忆和一些有趣的事(精彩绝伦)
  • 李维看.net和DELPHI6(含李维照片)
  • 《代码大全》电子版1.01发布了
  • Real Programmers Use Pascal
  • Kylix安装手记
  • Borland与Microsoft关于Delphi的对话
  • InstallShieldExpressfordelphi制作安装程
  • 关于在COM中使用可选参数的研究
  • msagent经典用法
  • 数据挖掘实验室资料
  • 数据挖掘博客地址
  • 数据挖掘实验室网站地址
  • Prepare for Medicare audits by using dat
  • 注册成为SAS用户与爱好者俱乐部会员
  • 水南梅
  • 明日烟
  • 新人报道
  • 下载
  • 厦门服务器托管,450元/月—0592-5177319 高
  • 买空间送域名--0592-5177319 高静