您的位置:首页 > 其它

WPF,Silverlight与XAML读书笔记第二十八 - 控件之十 – 媒体控件

2012-08-17 17:23 417 查看
Image(WPF/Silverlight2.0)

顾名思义这个控件用来显示各种格式的图片。

属性

Source:指定图像文件的路径及名称,文件需要被设置为资源。该属性类行为System.Windows.Media.ImageSource。

Height:图像控件的高度

Width:图像控件的宽度

Clip:该属性可以对图像进行剪切,Clip属性中,可以设定几何图形,WPF按照几何图像进行剪切。关于几何图形可以参见2D图形一文中Geometry的介绍。由于几何图像是复杂的元素,所以常以属性元素来设置Image的Clip值。

这里给一个Clip的示例:

<Image Source="res.jpg" Width="300" Height="200">
<Image.Clip>
<EllipseGeometry Center="150,150" RadiusX="100" RadiusY="100"/>
</Image.Clip>
</Image>


Strech:当图片大小与控件大小不同时,可以使用这个属性定义如何对图片进行拉伸,以使图片适应控件,有如下几种拉伸模式。

None:图像不拉伸;图像小于容器,周围以白色填充。如果大于容器,图像将被剪切。

Fill:图像被拉伸到容器的Height和Width定义的值,图片可能发生变形。

Uniform:图像按原先的外观比例被缩放到最佳大小,如果无法填充满容器,那些区域被白色填充。

UniformToFill:图像按原有比例放缩并拉伸填充容器。超出容器的部分将被剪切。
如果希望在运行时设置Iamge控件中的图片(Source属性的值),可以使用下面这样的代码:

该代码段适用于Silverlight:

Uri uri = new Uri("mm.png", UriKind.Relative);
image.Source = new BitmapImage(uri);


这段代码很易懂,不再赘述。

MediaElement(WPF/Silverlight2.0)

MediaElement控件定义于System.Windows.Control,类似于Image控件,使用Source属性设定要播放的媒体文件(声音或视频)。MediaElement支持的媒体文件格式主要为wma,mp3类型的音频及vc1编码的wmv的视频,具体列表可以参见MSDN网站,另外MediaElement也支持asx格式的播放列表文件。在协议方面MediaElement控件支持mms,http与https三种协议。对于这三种协议MediaElement控件采用了不同的访问方式,对于mms协议的Url,首先启用数据流方式播放,当这种方式遇到问题时则采用边下边播的方式,即首先下载数据填充满缓冲区然后播放。而对于http与https协议,这种尝试想法,首先MediaElement会尝试边下边播,在无法下载时将尝试数据流方式播放。

外观方面,如果指定了控件的宽高两个属性(Height与Width),则视频会被切成这个大小(原始视频大小大于控件大小时,如果控件尺寸大于视频则视频显示在控件中央周围填充黑边),如果只指定其中一个属性,则视频会被按比例拉伸或缩小到适应控件的大小,否则两个属性都不指定视频会按原始大小进行展现,但如果此时视频超出了MediaElement的可视范围(受其它元素所限),超出部分会被切掉。

属性:

Strech:这个属性对视频拉伸的方式与前文介绍的Image控件的同名属性及布局-内容溢出处理部分介绍的Strech属性的使用完全一致,此处不再赘述。

Clip:同样在Image部分我们介绍的同名属性,可以原样照搬到MediaElement元素中。

Opacity:这个属性用来控制视频的透明度,0表示完全不透明而1表示完全透明,当视频透明时可以看到后面的内容。

RenderTransform:Element中当然也支持使用RenderTransform进行变形

下面的例子我们使用SkewTransform进行演示:

<MediaElement x:Name="mes" Source="balls.wmv" Height="200" Width="200" Stretch="Fill">
<MediaElement.RenderTransform>
<SkewTransform AngleX="45"/>
</MediaElement.RenderTransform>
</MediaElement>


LayoutTransform(WPF only):设定单独的转换类型或一组转换类型对多媒体元素进行转换。有关转换的详细信息参见《转换》一文。LayoutTransform也常用属性元素设置,同样LayoutTransform属性中设置TransformGroup的方法前文也有描述。

LayoutTransform示例:

<MediaElement x:Name="mes" Source="balls.wmv" Height="200" Width="200" Stretch="Fill">
<MediaElement.LayoutTransform>
<ScaleTransform ScaleX="2" />
</MediaElement.LayoutTransform>
</MediaElement>


LoadedBehavior:

AutoPlay:该属性默认值为true,这样当Source属性被设置了视频后MeidaElement会自动播放,如将此属性设置为false,需要手动调用MeidaElement的Play方法来播放。

下面的几个属性与音频相关:

IsMuted:布尔值,当设置为true时,不会播放声音。

Volume:这个属性用来控制音量,其值是一个相对数值,当为0时没有音量,1时为最大音量。

Balance:这个属性控制音频的平衡,此属性取值为-1到1,在由-1到1变化的过程中左声道声音逐渐减小,右声道声音逐渐增大。为0时两个声道音量平衡。如当此值设置为0.8时,左边扬声器按20%音量来播,右边扬声器按80%音量来播。

方法:

Play,Pause和Stop:这三个方法提供所有媒体播放类软件中最常见的3种功能 – 播放,暂停与停止。特别的,对于 Silverlight,这三个方法不但可以在托管环境下由C#中直接调用,还暴露给Silverlight控件的JavaScript环境,这样在JavaScript环境中获得MediaElement对象的引用(具体方法在Silverlight与JavaScript交互一节有详细介绍)后,可以直接调用这三个方法。

与缓冲有关的属性与事件:

BufferingProgress属性,通过这个属性可以监控缓冲的情况,如当缓冲百分比始终达不到50%时,可以提示用户当前网络环境比较差。这个属性的值在0到1间浮动,0表示缓冲区还没有数据,1表示缓冲区已慢,每当缓冲区变化超过5%时,就会触发下面的事件。

BufferingProgressChanged事件:通过这个事件的处理函数我们真正有机会将缓冲状态反馈给用户。

我们通过下面的代码进行分析:

首先是给事件订阅处理函数,我们放在XAML中完成:

<MediaElement x:Name="vid" Source="balls.wmv" BufferingProgressChanged="doBuff" 
DownloadProgressChanged="doDown"
CurrentStateChanged="doState"
MarkerReached="handleMarker"
MediaOpened="handleOpened">
</MediaElement>


接下来我们可以选择在JavaScript中或是C#中来实现这个事件处理函数,首先是JavaScript的代码:

function doBuff(sender, args) {
var theText = sender.findName("txtBuff");
var meVid = sender.findName("vid");
var prog = meVid.BufferingProgress * 100;
prog = "Buffering % " + prog;
theText.Text = prog;
}


(以上JavaScript部分仅适用于Silverlight,下同)

C#版本如下:

private void doBuff(object sender, RoutedEventArgs e)
{
double prog = vid.BufferingProgress * 100;
txtBuff.Text = "Buffering % " + prog;
}


BufferingTime属性:这个属性接收一个时间段作为参数,如0:0:10,表示需要缓冲区的内容足够播放10秒时才开始播放,并始终维持一个10秒的缓冲,以避免在网络较差情况下播放不连续。

当遇到服务端不支持流式播放,只能下载完后开始播放这样情况时,可以使用DownloadProgressChanged和DownloadProgress来监控下载状态。这两个对象的使用类似Silverlight控件的Downloader对象中类似的2个成员。稍有不同的是此处的事件和属性分别支持在C#环境下处理与访问。

视频状态相关的属性

CurrentState属性:表示当前多媒体的状态,可能的值有如下:

Buffering 缓冲区未满(媒体处于暂停状态)

Closed 媒体被关闭

Error 媒体下载,缓冲或播放中出现错误

Opening 媒体已找到,缓冲或下载即将开始

Paused 媒体播放暂停

Playing 媒体播放中

Stopped 媒体播放停止

当这个属性变化时,会触发下面这个事件

CurrentStateChanged事件,订阅这个事件的代码见上文XAML,下面是C#版的事件处理函数:

private void doState(object sender, RoutedEventArgs e)
{
txtBuff.Text = vid.CurrentState;
}


同样在Silverlight中我们还可以使用JavaScript来实现回调函数:

function doState(sender, args) {
var meVid = sender.findName("vid");
alert(meVid.CurrentState);
}


控制播放位置的成员

NaturalDuration属性:在媒体的CurrentState属性为Opened的状态下,这个属性被设置,NaturalDuration.Seconds属性表示视频长度,单位为秒。

Position属性:返回视频当前播放的位置。

与前面的例子相同,我们可以使用C#或JavaScript(限Silverlight)中处理CurrentStateChanged事件并展示这两个属性的值。

处理媒体的时间线标记

使用Expression Media等软件加工媒体时可以给视频添加时间线标记,其是位于某一时间点的元数据。这个标记可以用来表示视频章节的分隔点。MediaElement播放视频过程中遇到时间线标记时会触发MakerReached事件。这个事件的参数 – TimeLineMarkerRountedEventArgs类型的e有一个Marker属性,这其中有3个比较有用的属性:

Time属性:TimeSpan类型,表示起点到此标记的时间跨度。

Type属性:字符串,返回用户编码的类型

Text属性:字符串,用于添加一些描述。

下面的代码处理上述事件,并展示3个属性:

private void handleMarker(object sender, TimelineMarkerRoutedEventArgs e)
{
string strMarkerStatus = e.Marker.Time.ToString();
strMarkerStatus += "  :  ";
strMarkerStatus += e.Marker.Type;
strMarkerStatus += "  :  ";
strMarkerStatus += e.Marker.Text;
}


同样Silverlight中可使用的JavaScript实现如下:

function handleMarker(sender, args)
{
var strMarkerStatus = args.marker.time.seconds.toString();
strMarkerStatus += "  :  ";
strMarkerStatus += args.marker.type;
strMarkerStatus += "  :  ";
strMarkerStatus += args.marker.text;
alert(strMarkerStatus);
}


我们也可以添加时间线标记到媒体文件中,当然这段数据不会被永久保存的视频中,只是在会话过程中有效。时间线标记由TimeLineMarker类表示,只需要创建一个该类对象并设置3个属性并将其添加到MediaElement的Makers属性就可以了,我们不需要保证多个添加的标记时间按前后顺序排列,MediaElement会自动按顺序触发这些事件。比如我们可以在MediaOpened事件的处理函数中完成这个操作:

private void handleOpened(object sender, RoutedEventArgs e)
{
TimelineMarker t = new TimelineMarker();
t.Time = new TimeSpan(0, 0, 0, 10);
t.Type = "My Temp Marker";
t.Text = "Dynamically Added Marker";
vid.Markers.Add(t);
}


同样下面给出Silverlight中JavaScript的实现:

function handleOpened(sender, args)
{
var marker =
sender.getHost().content.createFromXaml(
"<TimelineMarker Time='0:0:10'" +
" Type='My Temp Marker' Text='Dynamically Added Marker Marker' />");
sender.markers.add(marker);
}


在视频上叠加内容

像其它XMAL元素可以相互叠加一样,可以把想要的元素,如一些文本叠加到MediaElement上,这样就变相的在视频之上的层中添加的内容,实现了一种叠加效果。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐