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上,这样就变相的在视频之上的层中添加的内容,实现了一种叠加效果。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异