WPF电视应用程序






4.75/5 (7投票s)
一篇通过WPF呈现电视播放器的文章。
引言
有时,许多人会质疑 Silverlight 和 WPF 相对于 Flash 技术的用途。Silverlight 和 WPF 的一个优势在于它们能够接收高清视频/音频流进行播放。图形通常指向静态图像,照片也是如此。然而,视频(在电视中)使用大约每秒 60 帧图像的帧率来欺骗眼睛,使其看到动态画面。电视信号以同步的视频和音频信号进行传输。该信号由电视接收机接收,并通过称为外差原理的方法进行步进(电压)。视频图像和音频被重新追踪以形成动态画面。那么我们如何使用 WPF 创建一个电视应用程序呢?本文假设读者了解 WPF 的使用方法。它提供了一个模拟电视的 WPF 应用程序。GUI 描绘了一个 3D 风格的环境,其中包含一台电视(或其图像),可以打开它来播放、暂停和停止电视视频。当视频播放时,会同时播放一个半透明的反射效果。虽然这很复杂,但它实际上是一个使用控件和修改外观构建的基本 WPF GUI 应用程序。在本例中,示例演示了如何使用 WPF 位图效果来将视觉效果应用于某些 GUI 元素。但是,此应用程序并非试图以 WPF 应用程序的形式伪装成 Windows Media Player;它还引入了不透明度蒙版,可用于隐藏元素的某些部分。
下载此文件后,您将观看名为“future_nasa.wmv”的视频。可以从此处下载。将该文件添加到视频文件夹中,并确保视频的属性设置正确:“复制到输出”:始终;文件名:future_nasa.wmv;FilePath 等。您将在标记 XAML 文件中注意到此标题。
<Window x:Class="TV.TVWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TV" Height="720" Width="720">
<Window.Resources>
<ControlTemplate x:Key="RadioButtonTemplate"
TargetType="RadioButton">
<Grid>
<Ellipse Width="25" Height="25" Fill="Silver" />
<Ellipse Name="backgroundEllipse" Width="22" Height="22">
<Ellipse.Fill>
<RadialGradientBrush>
<GradientStop Offset="0" Color="Red"/>
<GradientStop Offset="1.25" Color="Black" />
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<ContentPresenter Content="{TemplateBinding Content}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="RadioButton.IsEnabled" Value="False">
<Setter TargetName="backgroundEllipse" Property="Fill">
<Setter.Value>
<RadialGradientBrush>
<GradientStop Offset="0" Color="LightGray" />
<GradientStop Offset="1.25" Color="Black" />
</RadialGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="RadioButton.IsChecked" Value="True">
<Setter TargetName="backgroundEllipse" Property="Fill">
<Setter.Value>
<RadialGradientBrush>
<GradientStop Offset="0" Color="LimeGreen" />
<GradientStop Offset="1.25" Color="Black" />
</RadialGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Window.Resources>
<Canvas>
<Border Canvas.Left="150" Height="370" Width="490"
Canvas.Top="20" Background="DimGray">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border Margin="0,20,0,10" Background="Black"
HorizontalAlignment="Center" VerticalAlignment="Center"
BorderThickness="2" BorderBrush="Silver" CornerRadius="2">
<MediaElement Height="300" Width="400"
Name="videoMediaElement" Source="Video/future_nasa.wmv"
LoadedBehavior="Manual" Stretch="Fill" />
</Border>
<StackPanel Grid.Row="1" HorizontalAlignment="Right"
Orientation="Horizontal">
<RadioButton Name="playRadioButton" IsEnabled="False"
Margin="0,0,5,15" Checked="playRadioButton_Checked"
Template="{StaticResource RadioButtonTemplate}">
<Image Height="20" Width="20"
Source="Images/play.png" Stretch="Uniform" />
</RadioButton>
<RadioButton Name="pauseRadioButton" IsEnabled="False"
Margin="0,0,5,15" Checked="pauseRadioButton_Checked"
Template="{StaticResource RadioButtonTemplate}">
<Image Height="20" Width="20"
Source="Images/pause.png" Stretch="Uniform" />
</RadioButton>
<RadioButton Name="stopRadioButton" IsEnabled="False"
Margin="0,0,15,15" Checked="stopRadioButton_Checked"
Template="{StaticResource
RadioButtonTemplate}">
<Image Height="20" Width="20"
Source="Images/stop.png" Stretch="Uniform" />
</RadioButton>
</StackPanel>
<CheckBox Name="powerCheckBox" Grid.Row="1" Width="25"
Height="25" HorizontalAlignment="Left"
Margin="15,0,0,15" Checked="powerCheckBox_Checked"
Unchecked="powerCheckBox_Unchecked">
<CheckBox.Template>
<ControlTemplate TargetType="CheckBox">
<Grid>
<Ellipse Width="25" Height="25"
Fill="Silver" />
<Ellipse Name="backgroundEllipse" Width="22"
Height="22">
<Ellipse.Fill>
<RadialGradientBrush>
<GradientStop Offset="0"
Color="LightGray" />
<GradientStop Offset="1.25"
Color="Black" />
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<Image Source="Images/power.png" Width="20"
Height="20" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="CheckBox.IsChecked"
Value="True">
<Setter TargetName="backgroundEllipse"
Property="Fill">
<Setter.Value>
<RadialGradientBrush>
<GradientStop Offset="0"
Color="LimeGreen" />
<GradientStop Offset="1.25"
Color="Black" />
</RadialGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</CheckBox.Template>
</CheckBox>
</Grid>
<Border.RenderTransform>
<SkewTransform AngleY="15" />
</Border.RenderTransform>
<Border.BitmapEffect>
<BitmapEffectGroup>
<BevelBitmapEffect BevelWidth="10" />
<DropShadowBitmapEffect Color="Gray" ShadowDepth="15" Softness="1"/>
</BitmapEffectGroup>
</Border.BitmapEffect>
</Border>
<Border Canvas.Left="185" Canvas.Top="410" Height="300"
Width="400">
<Rectangle Name="reflectionRectangle">
<Rectangle.Fill>
<VisualBrush
Visual="{Binding ElementName=videoMediaElement}">
<VisualBrush.RelativeTransform>
<ScaleTransform ScaleY="-1" CenterY="0.5" />
</VisualBrush.RelativeTransform>
</VisualBrush>
</Rectangle.Fill>
<Rectangle.OpacityMask>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="Black" Offset="-0.25" />
<GradientStop Color="Transparent" Offset="0.5" />
</LinearGradientBrush>
</Rectangle.OpacityMask>
</Rectangle>
<Border.RenderTransform>
<SkewTransform AngleY="15" AngleX="-45"/>
</Border.RenderTransform>
</Border>
</Canvas>
</Window>
电视左下角的控件打开电视,箭头控件加载视频,在本例中是火箭发射到月球的视频。这是电视 GUI 元素的图像。此示例中的电视按钮不是 Button 控件。“播放”、“暂停”和“停止”按钮是RadioButton
,电源按钮是CheckBox
。这应该是有道理的。这些控件的形状不同,但执行的功能几乎相同,并且通常成组出现。每个按钮的背景中有两个圆圈,由Ellipse
对象定义。使用的图像是具有透明背景的播放、暂停和停止符号。在其默认状态下(已启用且未选中),每个播放按钮都会发出红色光芒。您首先点击最左侧的电源按钮打开电视(即,复选框未选中),控件为灰色。当用户点击该按钮时,控件变为绿色。然后点击箭头单选按钮。显示反射,视频和音频开始播放。

此应用程序的功能来自代码隐藏文件。当用户打开电视(即选中powerCheckBox
)时,反射变得可见,并且播放选项被启用。当用户关闭电视时,将调用MediaElement
的close
方法来关闭媒体。此外,反射变得不可见,并且播放选项被禁用。每当代表每个播放选项的RadioButton
之一被选中时,MediaElement
就会执行其中一个事件处理程序,例如播放视频。
// File: TV.xaml.cs
using System.Windows;
namespace TV
{
public partial class TVWindow : Window
{
public TVWindow()
{
InitializeComponent();
}
private void powerCheckBox_Checked( object sender,
RoutedEventArgs e )
{
reflectionRectangle.Visibility = Visibility.Visible;
playRadioButton.IsEnabled = true;
pauseRadioButton.IsEnabled = true;
stopRadioButton.IsEnabled = true;
}
private void powerCheckBox_Unchecked( object sender,
RoutedEventArgs e )
{
videoMediaElement.Close();
reflectionRectangle.Visibility = Visibility.Hidden;
playRadioButton.IsChecked = false;
pauseRadioButton.IsChecked = false;
stopRadioButton.IsChecked = false;
playRadioButton.IsEnabled = false;
pauseRadioButton.IsEnabled = false;
stopRadioButton.IsEnabled = false;
}
// plays the video (as mentioned above)
private void playRadioButton_Checked( object sender,
RoutedEventArgs e )
{
videoMediaElement.Play();
}
private void pauseRadioButton_Checked( object sender,
RoutedEventArgs e )
{
videoMediaElement.Pause();
}
private void stopRadioButton_Checked( object sender,
RoutedEventArgs e )
{
videoMediaElement.Stop();
}
}
}
请注意,这将下载为一个已部署的应用程序,该应用程序显示了一个技术人员在零重力环境下操作的视频。没有解决方案文件可供下载的原因是,整个文件、图像和视频容器太大,无法上传。我使用下载并刻录的 Visual Studio 2010 ISO 映像构建了这些应用程序。但是,没有理由它们不应该在 Visual Studio 2008 上运行,因为该平台与 .NET 3.5 兼容。
参考文献
- Joe Mayo 编著的专业 Visual Studio 2008
- Deitel Associates