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

 

Image(WPF/Silverlight2.0)

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

属性

  • Source:指定图像文件的路径及名称,文件需要被设置为资源。该属性类行为System.Windows.Media.ImageSource。
  • Height:图像控件的高度
  • Width:图像控件的宽度
  • Clip:该属性可以对图像进行剪切,Clip属性中,可以设定几何图形,WPF按照几何图像进行剪切。关于几何图形可以参见2D图形一文中Geometry的介绍。由于几何图像是复杂的元素,所以常以属性元素来设置Image的Clip值。

这里给一个Clip的示例:

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

 

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

  • None:图像不拉伸;图像小于容器,周围以白色填充。如果大于容器,图像将被剪切。
  • Fill:图像被拉伸到容器的Height和Width定义的值,图片可能发生变形。
  • Uniform:图像按原先的外观比例被缩放到最佳大小,如果无法填充满容器,那些区域被白色填充。
  • UniformToFill:图像按原有比例放缩并拉伸填充容器。超出容器的部分将被剪切。

    如果希望在运行时设置Iamge控件中的图片(Source属性的值),可以使用下面这样的代码:

该代码段适用于Silverlight:

1 Uri uri = new Uri("mm.png", UriKind.Relative); 
2 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进行演示:

1 <MediaElement x:Name="mes" Source="balls.wmv" Height="200" Width="200" Stretch="Fill">
2     <MediaElement.RenderTransform>
3         <SkewTransform AngleX="45"/>
4     </MediaElement.RenderTransform>
5 </MediaElement>
  • LayoutTransform(WPF only):设定单独的转换类型或一组转换类型对多媒体元素进行转换。有关转换的详细信息参见《转换》一文。LayoutTransform也常用属性元素设置,同样LayoutTransform属性中设置TransformGroup的方法前文也有描述。

LayoutTransform示例:

1 <MediaElement x:Name="mes" Source="balls.wmv" Height="200" Width="200" Stretch="Fill">
2     <MediaElement.LayoutTransform>
3         <ScaleTransform ScaleX="2" />
4     </MediaElement.LayoutTransform>
5 </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中完成:

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

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

1 function doBuff(sender, args) {
2     var theText = sender.findName("txtBuff");
3     var meVid = sender.findName("vid");
4     var prog = meVid.BufferingProgress * 100;
5     prog = "Buffering % " + prog;
6     theText.Text = prog;
7 }

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

C#版本如下:

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

 

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

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

视频状态相关的属性

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

  • Buffering 缓冲区未满(媒体处于暂停状态)
  • Closed 媒体被关闭
  • Error 媒体下载,缓冲或播放中出现错误
  • Opening 媒体已找到,缓冲或下载即将开始
  • Paused 媒体播放暂停
  • Playing 媒体播放中
  • Stopped 媒体播放停止

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

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

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

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

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

 

控制播放位置的成员

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

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

 

处理媒体的时间线标记

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

  • Time属性:TimeSpan类型,表示起点到此标记的时间跨度。
  • Type属性:字符串,返回用户编码的类型
  • Text属性:字符串,用于添加一些描述。

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

1 private void handleMarker(object sender, TimelineMarkerRoutedEventArgs e)
2 {
3     string strMarkerStatus = e.Marker.Time.ToString();
4     strMarkerStatus += "  :  ";
5     strMarkerStatus += e.Marker.Type;
6     strMarkerStatus += "  :  ";
7     strMarkerStatus += e.Marker.Text;
8 }

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

1 function handleMarker(sender, args) 
2 { 
3    var strMarkerStatus = args.marker.time.seconds.toString(); 
4    strMarkerStatus += "  :  "; 
5    strMarkerStatus += args.marker.type; 
6    strMarkerStatus += "  :  "; 
7    strMarkerStatus += args.marker.text; 
8    alert(strMarkerStatus); 
9 }

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

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

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

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

 

在视频上叠加内容

    像其它XMAL元素可以相互叠加一样,可以把想要的元素,如一些文本叠加到MediaElement上,这样就变相的在视频之上的层中添加的内容,实现了一种叠加效果。

 

posted @ 2012-08-17 17:23  hystar  阅读(309)  评论(0编辑  收藏  举报