初级问题:
我的那个定时提醒程序中要用到它,初步使用问题已解决。基本使用步骤如下:
一、往控件箱中添加此控件: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.WMPPla