惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
V2EX
C
Check Point Blog
博客园_首页
B
Blog
D
Docker
U
Unit 42
量子位
I
InfoQ
有赞技术团队
有赞技术团队
Martin Fowler
Martin Fowler
GbyAI
GbyAI
L
LangChain Blog
云风的 BLOG
云风的 BLOG
博客园 - Franky
美团技术团队
T
The Blog of Author Tim Ferriss
阮一峰的网络日志
阮一峰的网络日志
月光博客
月光博客
Vercel News
Vercel News
Recent Announcements
Recent Announcements
雷峰网
雷峰网
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
Google DeepMind News
Google DeepMind News

博客园 - GeneralXU

股市量化智能分析2035 忘记mysql root密码的解决方法 Mule 官方例子研究 开源企业服务总线ESB汇总与对比 Apache CXF 介绍 JAX-WS eclipse.ini/myeclipse.ini文件中参数配置 Web2.0是什么:下一代软件的业务模式与设计模式 FaceBook网站架构软件揭秘 概念介绍:OLAP和ROLAP,MOLAP,HOLAP Oracle WebCenter 11g 快速开发指南--翻译(三) J2EE框架(TomcatStrutsHibernateSpringAjax(dojo))开发步骤 Oracle WebCenter 11g 快速开发指南--翻译(二) 《人月神话》--摘录 Oracle WebCenter 11g 快速开发指南--翻译(一) ORACLE11G 字符集更改(这里更改为AL32UTF8) oracle 11g登录密码问题 java.lang.NoClassDefFoundError: net/sf/cglib/proxy/CallbackFilter 异常解决办法 hibernate -----Could not instantiate cache implementation异常处理(转) - GeneralXU
C# Media Player控件(转)
GeneralXU · 2011-01-22 · via 博客园 - GeneralXU

Media player控件基本使用步骤如下:
一、往控件箱中添加此控件:wmp.dll
二、往窗体上拖控件
三、wmp.URL=XXXX;wmp.play()即可。
  平常应用就这三步就OK了。但是,我想写个播放器的话,就遇到了一些问题。
在dotnet中使用非基于dotnet的控件,需要做一些额外的事,不过这些事vs已经帮我们做好了,当我们拖了此控件进窗体时,vs会自动调用 AxImp.exe,用它根据原有的dll或ocx生成一个用AxHost类包装的新的一组程序集(更为精确的描述见msdn),于是根据 WMPLib.dll生成两个文件:AxInterop.WMPLib.dll、Interop.WMPLib.dll。这两个文件中包含了转化后的类。 包装后的控件继承自System.Windows.Forms.AxHost。
这是第一个问题,控件怎么使用呢?如果是拖控件,很简单,无论如何都能有效的使用。但是,如果手工new创建控件的实例呢?那就不一定了。
我做过种种实验,获得如下的结论:
  在非可视化类中无法创建有UI的控件的实例,或者是在没有把实例加入到一个可视化的容器中时。
我实验了下面的代码:
       AxWMPLib.AxWindowsMediaPlayer wmp = new AxWMPLib.AxWindowsMediaPlayer();
       this.Controls.Add(wmp);
       wmp.URL = "约定.mp3";
       wmp.Ctlcontrols.play();
  这几行代码不一定能运行。发现,如果这几行代码写在窗体的构造函数中,哪怕show出来都不能运行,只有写在Load或Load之后的事件中,并且把窗 体show出来才有运行,否则会抛出一个错误:引发类型为“System.Windows.Forms.AxHost+ InvalidActiveXStateException”的异常。网上有些人也遇到这个问题,其实都没有谈到点子上。甚为遗憾。
是不是不show就一定不能运行呢?我拖了个播放器控件放窗体上,在InitializeComponent后面写了行play的代码,能运行。可见,这中间有蹊跷啊。我比较了上面的代码跟拖上去生成的代码,有两点不同:
  一、拖控件生成的代码为多一对((System.ComponentModel.ISupportInitialize)(this.wmp1)).BeginInit()/EndInit()
  二、拖的控件多了一行:this.wmp1.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("wmp1.OcxState"))); 我查了MSDN,ocxstate是控件状态。用于持久化控件的状态的。com组件的状态信息被写在对应窗体的资源文件中,用记事本打开窗体资源文件就可 以看到。在手工创建中,这个ocxstate是没法赋值的。
我试了加入BeginInit、EndInit,没用,可见问题是出在控件状态问题上。没有办法了。

  取当前播放媒体的信息,这个很简单,currentMedia就可以取得。怎样创建播放列表呢?让播放器依次播放指定的媒体呢?有办法,我自己摸索出来的:
wmp1.currentPlaylist.appendItem(wmp1.newMedia("约定.mp3"))
我看到网上的兄弟不晓得用currentPlaylist,在自己实现播放列表,我觉得没必要。
郁闷无比,用wmp播放rmvb等非默认支持文件时,会弹出错误消息框,尽可以用一个属性 wmp.settings.enableErrorDialogs=false控制它不显示,但是,还是有一个后遗症,就是调用 wmp.Ctlcontrols.play()时,它并不会播放,但是单击一下自带播放控制栏中的三角行按钮就能播放了。郁闷啊。
我又去的了暴风3的mps.dll。果然,它用的是酷热影音的内核。不过,酷热提供的这个控件实在太差劲了。没什么高级功能。郁闷。还是wmp好啊。继续研究wmp。我现在装的是wmp11。
现在又找到一些更全的关于wmp API的资料,如下:
属性/方法名说明:
详尽的API文档(比MSDN更透彻):
[基本属性]  
URL:String; 指定媒体位置,本机或网络地址
uiMode:String; 播放器界面模式,可为Full, Mini, None, Invisible(不计大小写)
playState:integer; 播放状态。这个属性改变时同时引发PlayStateChange事件与StateChange事件。取值范围为枚举型:WMPLib.WMPPlayState,它的成员如下:
  wmppsUndefined = 0;   //未知状态
  wmppsStopped = 1;    //播放停止
  wmppsPaused = 2;     //播放暂停
  wmppsPlaying = 3;     //正在播放
  wmppsScanForward = 4;   //向前搜索
  wmppsScanReverse = 5;   //向后搜索
  wmppsBuffering = 6;     //正在缓冲
  wmppsWaiting = 7;      //正在等待流开始
  wmppsMediaEnded = 8;    //播放流已结束
  wmppsTransitioning = 9;    //准备新的媒体文件
  wmppsReady = 10;      //播放准备就绪
  wmppsReconnecting = 11;   //尝试重新连接流媒体数据
  wmppsLast = 12;       //上一次状态,状态没有改变
  在PlayStateChange中写代码可以防止播放rmvb等非默认类型的问题(用wmppsReady)。
  enableContextMenu:Boolean;    启用/禁用右键菜单
  fullScreen:boolean;         是否全屏显示

  //播放器基本控制
  Ctlcontrols.play; 播放
  Ctlcontrols.pause; 暂停
  Ctlcontrols.stop; 停止
  Ctlcontrols.currentPosition:double; 当前进度
  Ctlcontrols.currentPositionString:string; 当前进度,字符串格式。如“00:23”
  Ctlcontrols.fastForward; 快进
  Ctlcontrols.fastReverse; 快退
  Ctlcontrols.next; 下一曲
  Ctlcontrols.previous; 上一曲

  [settings] wmp.settings //播放器基本设置
  settings.volume:integer; 音量,0-100
  settings.autoStart:Boolean; 是否自动播放
  settings.mute:Boolean; 是否静音
  settings.playCount:integer; 播放次数
  //顺序播放
  wmp.settings.setMode("shuffle", False)
  //随机播放
  wmp.settings.setMode("shuffle", True)
  //循环播放
  wmp.settings.setMode("loop", True)

[currentMedia] wmp.currentMedia //当前媒体属性
currentMedia.duration:double; 媒体总长度
currentMedia.durationString:string; 媒体总长度,字符串格式。如“03:24”
currentMedia.getItemInfo(const string); 获取当前媒体信息"Title"=媒体标题,"Author"=艺术家,"Copyright"=版权信息,"Description"=媒体内容描述, "Duration"=持续时间(秒),"FileSize"=文件大小,"FileType"=文件类型,"sourceURL"=原始地址
currentMedia.setItemInfo(const string); 通过属性名设置媒体信息
currentMedia.name:string; 同 currentMedia.getItemInfo("Title")

[currentPlaylist] wmp.currentPlaylist //当前播放列表属性
currentPlaylist.count:integer; 当前播放列表所包含媒体数
currentPlaylist.Item[integer]; 获取或设置指定项目媒体信息,其子属性同wmp.currentMedia
axWindowsMediaPlayer1.currentMedia.sourceURL; //获取正在播放的媒体文件的路径
axWindowsMediaPlayer1.currentMedia.name;          //获取正在播放的媒体文件的名称
axWindowsMediaPlayer1.Ctlcontrols.Play          播放  
axWindowsMediaPlayer1.Ctlcontrols.Stop          停止  
axWindowsMediaPlayer1.Ctlcontrols.Pause          暂停  
axWindowsMediaPlayer1.Ctlcontrols.PlayCount         文件播放次数  
axWindowsMediaPlayer1.Ctlcontrols.AutoRewind       是否循环播放 (无效)
axWindowsMediaPlayer1.Ctlcontrols.Balance          声道  
axWindowsMediaPlayer1.Ctlcontrols.Volume         音量  
axWindowsMediaPlayer1.Ctlcontrols.Mute          静音  
axWindowsMediaPlayer1.EnableContextMenu     是否允许在控件上点击鼠标右键时弹出快捷菜单  
axWindowsMediaPlayer1.Ctlcontrols.AnimationAtStart       是否在播放前先播放动画(无效)
axWindowsMediaPlayer1.Ctlcontrols.ShowControls       是否显示控件工具栏(无效)
axWindowsMediaPlayer1.Ctlcontrols.ShowAudioControls       是否显示声音控制按钮(无效) 
axWindowsMediaPlayer1.Ctlcontrols.ShowDisplay         是否显示数据文件的相关信息(无效) 
axWindowsMediaPlayer1.Ctlcontrols.ShowGotoBar        是否显示Goto栏(无效)
axWindowsMediaPlayer1.Ctlcontrols.ShowPositionControls       是否显示位置调节按钮(无效)
axWindowsMediaPlayer1.Ctlcontrols.ShowStatusBar      是否显示状态栏(无效)
axWindowsMediaPlayer1.Ctlcontrols.ShowTracker       是否显示进度条(无效)
axWindowsMediaPlayer1.Ctlcontrols.FastForward        快进  
axWindowsMediaPlayer1.Ctlcontrols.FastReverse        快退  
axWindowsMediaPlayer1.Ctlcontrols.Rate            快进/快退速率  
axWindowsMediaPlayer1.AllowChangeDisplaySize   是否允许自由设置播放图象大小(无效)
axWindowsMediaPlayer1.DisplaySize       设置播放图象大小(无效)
1-MpDefaultSize         原始大小  
2-MpHalfSize           原始大小的一半  
3-MpDoubleSize         原始大小的两倍  
4-MpFullScreen          全屏  
5-MpOneSixteenthScreen      屏幕大小的1/16  
6-MpOneFourthScreen        屏幕大小的1/4  
7-MpOneHalfScreen          屏幕大小的1/2  
axWindowsMediaPlayer1.ClickToPlay    是否允许单击播放窗口启动Media Player 

在视频播放之后,可以通过如下方式读取源视频的宽度和高度,然后设置其还原为原始的大小.
         private void ResizeOriginal()
         {
             int intWidth = axWindowsMediaPlayer1.currentMedia.imageSourceWidth;
             int intHeight = axWindowsMediaPlayer1.currentMedia.imageSourceHeight;
             axWindowsMediaPlayer1.Width = intWidth + 2;
             axWindowsMediaPlayer1.Height = intHeight + 2;
         }

打开媒体文件并播放:

         Dim filePath As String
         With Me.OpenFileDialog1
             .Title = "打开语音文件"
             .CheckPathExists = True
             .CheckFileExists = True
             .Multiselect = False
             .Filter = "mp3文件(*.mp3)|*.mp3|所有文件(*.*)|*.*"
             If .ShowDialog = DialogResult.Cancel Then
                 Exit Sub
             End If
             filePath = .FileName
         End With
         Me.Text = "PC复读机-文件 " & filePath
         AxWindowsMediaPlayer1.URL = filePath
         Try
             Me.AxWindowsMediaPlayer1.Ctlcontrols.play()
         Catch ex As Exception
             MsgBox("对不起,不能播放此格式语音文件", MsgBoxStyle.OKOnly, "PC复读机")
             Exit Sub
        End Try
注意:
AxWindowsMediaPlayer1.URL 中URL是表示要播放的文件名,取消了原来的Name属性.
AxWindowsMediaPlayer1.Ctlcontrols.play()播放,同样还有Pause,Stop等其他属性.
AxWindowsMediaPlayer1.settings.balance表示媒体播放的声道设置,0表示均衡,-1和1表示左右声道.
AxWindowsMediaPlayer1.currentMedia.duration 表示要播放的文件的时间长度.可用它获取文件长度.
AxWindowsMediaPlayer1.Ctlcontrols.currentPosition表示正在播放的文件的当前播放位置,可用这个属性来对媒体文件进行前进后退等设置.如
AxWindowsMediaPlayer1.Ctlcontrols.currentPosition+1 表示前进1个时间单位.
AxWindowsMediaPlayer1.settings.rate播放速率,一般乘以16后再显示kbps单位.
注意:在上面程序中,如果在后面加上一个:
msgbox(AxWindowsMediaPlayer1.currentMedia.duration.ToString )
则显示结果很可能为0,因此,这时候很可能获取不到文件的播放时间长度,容易出错。所以在利用的时候可以加一个timer控件:
Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
         EndPoint = AxWindowsMediaPlayer1.currentMedia.duration
         If EndPoint = 0 Then Exit Sub '可能因为媒体文件的打开需要一定时间,这里等待媒体文件的打开
         msgbox(AxWindowsMediaPlayer1.currentMedia.duration.ToString )
End Sub
此时msgbox便会显示文件播放长度。
2. Ctlcontrols属性
Ctlcontrols属性是AxWindowsMediaPlayer的一个重要属性, 此控件中有许多常用成员。
(1) 方法play
用于播放多媒体文件,其格式为:
窗体名.控件名.Ctlcontrols.play()
如: AxWindowsMediaPlayer1.Ctlcontrols.play()  ‘此处缺省窗体名是Me
(2) 方法pause
用于暂停正在播放的多媒体文件,其格式为:
窗体名.控件名.Ctlcontrols.pause()
如: AxWindowsMediaPlayer1.Ctlcontrols.pause()
(3) 方法stop
用于停止正在播放的多媒体文件,其格式为:
窗体名.控件名.Ctlcontrols.stop()
如: AxWindowsMediaPlayer1.Ctlcontrols.stop()
(4) 方法fastforward
用于将正在播放的多媒体文件快进,其格式为:
窗体名.控件名.Ctlcontrols.fastforward()
如: AxWindowsMediaPlayer1.Ctlcontrols.forward()
(5) 方法fastreverse
窗体名.控件名.Ctlcontrols.fastreverse()
如: AxWindowsMediaPlayer1.Ctlcontrols.fastreverse()
6. 属性CurrentPosition
用于获取多媒体文件当前的播放进度,其值是数值类型,使用格式为:
窗体名.控件名.Ctlcontrols.currentPosition
d1 =AxWindowsMediaPlayer1.Ctlcontrols.currentPosition
其中d1 是一个整型变量。
7. 属性Duration
用于获取当前多媒体文件的播放的总时间,其值为数值类型,其使用格式为:
窗体名.控件名.currentMedia.duration
如:d2 =AxWindowsMediaPlayer1.currentMedia.duration
其中d2是一个整型变量。
对WMP的感叹
感叹一
这是我找到的关于WMP的最全的中文资料了。刚才又查了一下,查到了MSDN有更全的API文档,终于找到它了。上面的资料基本上够用了,但是,如果要写一个更为精致的播放器,这些还不够啊。看MSDN去也。WMP11在MSDN中的位置如下:
win32和COM开发-Griphics And MultiMedia-Audio And Vedio-Windows Media Player 11 SDK
看了一个晚上的MSDN与资料。发现MSDN上关于WMP SDK的文档也很不扎实。没有实例。我要找的答案都不在上面。唯一的收获是晓得了wpl。wmp有自己的播放列表文件,但是,我查遍msdn,发现sdk 并不提供手动保存播放列表的任何方法。所以,现在的问题是,我们创建了一个IWMPPlayList,但是,这个接口不提供任何保存的方法,结果。 newPlayList(name,path)只提供打开一个已有列表。郁闷。查了英文资料。老外建议用:StreamWrite/StreamRead 的办法来读写wpl,我也看了。事实上wpl是一个xml文件。我们可以用System.Xml中的API来读写。不过,sdk中的这个漏子我始终无法释 怀。
感叹二
从WMP8开始就不支持mms/rtsp协议了,所用wmp.URL="mms://xxxx";是不行的了。点此处见详情,而mms这个协议现在还在广泛使用。郁闷。因此,我们不能使用wmp来看网络电视了。
使用WMP的常见问题:
一、升级wmp后,再拖windows media player控件至窗体出错的问题(至今没解决,应当是修改工程序文件,用文本编辑器)
二、播放rmvb/rm等非官方格式文件要先双击文件再点播放按钮,而不能直接播放的问题,并弹出消息框:Windows Media Player下载文件遇到问题。有关帮助信息请单击“Web帮助”。消息下面两个按钮:关闭、Web帮助。我没有找到出现这个问题的官方说明。我个人意 见,这是因为wmp默认只播能播放官方指定的几种类型的媒体。如果不是,wmp会试图下载对应的解码器来播放。而这个下载过程失败了,所以弹出这个消息 框。wmp好像没有去判断这个解码器是否已经存在。但是,如果你再点播放的话,又能播放,这是什么原因呢?应当是wmp在这次会试图搜索本机上的解码器以 图播放媒体。怎样解决这个点两次鼠标的问题呢?如下:

先设置属性:wmp.settings.enableErrorDialogs = false;事实上这个属性默认就是false。不用设置。


private void wmp_PlayStateChange(object sender, AxWMPLib._WMPOCXEvents_PlayStateChangeEvent e)
{
         //如果已播放完毕就播放下一个文件
         if ((WMPLib.WMPPlayState)e.newState == WMPLib.WMPPlayState.wmppsReady) wmp.Ctlcontrols.play();
}  
唉,我费了九牛二虎之力总算找到了这个办法解决。

  三、怎样获得一个媒体文件中的信息,并且修改媒体的一些信息?

  有办法:AxWindowsMediaPlayer.newMedia(filename),它会创建一个IWMPMedia的实例。用它的setItemInfo就成了。至于有哪些信息可供设置,可去msdn中查,里面列举了所有相关信息。

  四、IWMPPlayList是不是鸡肋????????
确实是好大的一块鸡肋!!!!!!!!!!!

  五、播放器控件有几个组成部分,可有隐藏其中相关部分的方法?

  媒体播放器包括如下元素:
Video Display Panel:视频显示面板;
Video Border:视频边框;
Closed Captioning Display Panel;字幕显示面板;
Track Bar;搜索栏;
Control Bar with Audio and Position Controls:带有声音和位置控制的控制栏;
Go To Bar:转到栏;
Display Panel:显示面板;
Status Bar:状态栏;

  就是这么几个部分,网上有资料说控件提供方法控制它们显示与否,但是我在sdk中并没有找到它们。唯一可以粗略控制它们的就是uiMode属性。它的取值前面有。

  六、控件的网络设置,如设置代理、缓冲次数、缓冲时间等信息在哪设置?

  AxWindowsMediaPlayer.netWork。它是IWMPNetWork的实例。

  七、像暴风有字幕相关信息的设置,wmp控件有这个功能吗?

  当然有。就是AxWindowsMediaPlayer.closedCaption。它是IWMPClosedCaption的实例。