65.9K
CodeProject 正在变化。 阅读更多。
Home

WPF电视应用程序

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.75/5 (7投票s)

2010 年 4 月 29 日

CPOL

3分钟阅读

viewsIcon

46169

downloadIcon

1484

一篇通过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.wmvFilePath 等。您将在标记 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对象定义。使用的图像是具有透明背景的播放、暂停和停止符号。在其默认状态下(已启用且未选中),每个播放按钮都会发出红色光芒。您首先点击最左侧的电源按钮打开电视(即,复选框未选中),控件为灰色。当用户点击该按钮时,控件变为绿色。然后点击箭头单选按钮。显示反射,视频和音频开始播放。

1.JPG

此应用程序的功能来自代码隐藏文件。当用户打开电视(即选中powerCheckBox)时,反射变得可见,并且播放选项被启用。当用户关闭电视时,将调用MediaElementclose方法来关闭媒体。此外,反射变得不可见,并且播放选项被禁用。每当代表每个播放选项的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
© . All rights reserved.