This article has been localized into Polish by the community.
Stworzenie pełnego odtwarzacza dźwięku/wideo
W ostatnim rozdziale, obiecałem pokazać jak utworzyć się bardziej kompletny program, potrafiący obsługiwać zarówno pliki audio i wideo, wykorzystując fakt że klasa MediaPlayer/MediaElement ma wbudowaną w sobie obsługę tych plików.Jak zrobić kompletny odtwarzacz audio / video.
Będę korzystał z pojęć używanych w poprzednich rozdziałach o odtwarzaniu audio i wideo, aby włączyć je wszystkie do WPF Media Player. Wynik będzie wyglądać jak to :
Ale dotyczy to tylko sytuacji gdy odtwarzamy pliki audio / MP3. Po wczytaniu wideo interfejs automatycznie rozszerza się, aby wyświetlić treść wideo wewnątrz okna:
Pozwól mi trochę opowiedzieć jak to zostało zbudowane. Na końcu będziesz mógł, oczywiście, zobaczyć na cały źródłowy kod gotowy do uruchomienia.
Interfejs
Interfejs został podzielony na trzy pionowe obszary : górny, gdzie znajduje się pasek narzędziowy; środkowy, gdzie jest pokazywany film ( jeśli jest ładowany plik wideo ) i dolny, gdzie możemy znaleźć pasek stanu, całkowity czas trwania, Suwak do zobaczenia i kontrolowania postępu odtwarzania i ProgressBar na pokazujący głośność. Wszystkie te stosowane kontrolki zostały już wyjaśnione wcześniej w samouczku, tak więc nie będziemy się zbytnio na nich koncentrować.
Zauważ, że użyłem poleceń WPF, zamiast przypisania zdarzeń kliknięcia dla przycisków. To pozwala nam na łatwe ponowne użycie funkcjonalności w przypadku chcemy coś dodać np . w głównym menu lub menu kontekstowym. To również sprawia, że łatwiej będzie lub wyłączyć pewne funkcjonalność, w zależności od aktualnego stanu odtwarzacza.
Należy również zauważyć, że ustawiliśmy własność MediaElement Stretch na None, a okno SizeToContentMode na WidthAndHeight . To sprawia, że okno może zmniejszyć się do minimalnej wielkości niezbędnej, aby pokazać film, jeśli jestodtwarzany.
Dla pokazania głośności, wykorzystywaliśmy kontrolkę ProgressBar znajdującą się w dolnym , prawym rogu. Nie pozwala ona użytkownikowi kontrolować głośności, lecz jedynie pokazuje wartość Głośność, poprzez związanie wskaźnika z rzeczywistą wartością. Mamy wdrożony mały, ale schludny trick pozwalający użytkownikowi na kontrolę głośności- więcej na ten temat będzie poniżej .
Kod
W kodzie źródłowym, wykorzystaliśmy kilka technik już stosowanych w naszych poprzednich przykładach . Na przykład zainicjowaliśmy DispatcherTimer aby uruchamiał się co jedną sekundę i pokazywał aktualny czas odtwarzania. W zdarzeniu Tick timera aktualizujemy wartość Slider poprzez ustawienie Minimum ,Maksimum i aktualną Wartość zgodnie z odtwarzanym plikiem, a przez podpinania się do valueChanged(zmiana Wartości) zdarzenia na suwak , możemy użyć , że aby zaktualizować etykietę pokazano na prąd postęp odtwarzania w godzinach , minutach i sekundach .
Suwak sterujący również pozwala użytkownikowi przejść do innej części pliku, przez przeciągnięcie wskaźnikiem do innego miejsca. Obsługujemy to przez realizację wydarzeń DragStarted i DragCompleted – na początku ustawiamy zmienną ( userIsDraggingSlider ), która opowiada za to, że czasomierz nie aktualizuje się podczas przesuwania Suwaka, a potem przechodzimy do wyznaczonego fragmentu gdy użytkownik uwalnia się myszką przycisk .
Mamy tu procedury CanExecute i Executed dla obsługi czterech komend, najbardziej interesujące są komendy Pauza i Stop. Ponieważ my nie możemy dowiedzieć się aktualnego stanu MediaElement, musimy sami go pamiętać i śledzić. Zrobione jest to poprzez lokalną zmienną o nazwie mediaPlayerIsPlaying , która regularnie sprawdzamy aby zobaczyć czy Pauza Stop i przyciski powinny być włączone .
Ostatni mały szczegół na który warto zwrócić uwagę to zdarzenie Grid_MouseWheel . Informacje o tym zdarzeniu otrzymujemy gdy użytkownik poruszy kółko myszy. Po tego zdarzenia przypisujemy możliwość zmiany głośności. Zależnie od kierunku ( dowiadujemy się o tym poprzez własność Delta, która jest ujemna, gdy przewijanie w dół i dodatnia, gdy przewijanie w górę ). To jest natychmiast odzwierciedlenie w interfejsie użytkownika, kontrolka ProgressBar jest związana z wartości określającą głośność w MediaElement .
Kompletny kod źródłowy
Z całą teorią opisaną powyżej, oto kompletny kod źródłowy.
<Window x:Class="WpfTutorialSamples.Audio_and_Video.AudioVideoPlayerCompleteSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WPF Media Player" Height="300" Width="300"
MinWidth="300" SizeToContent="WidthAndHeight">
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Open" CanExecute="Open_CanExecute" Executed="Open_Executed" />
<CommandBinding Command="MediaCommands.Play" CanExecute="Play_CanExecute" Executed="Play_Executed" />
<CommandBinding Command="MediaCommands.Pause" CanExecute="Pause_CanExecute" Executed="Pause_Executed" />
<CommandBinding Command="MediaCommands.Stop" CanExecute="Stop_CanExecute" Executed="Stop_Executed" />
</Window.CommandBindings>
<Grid MouseWheel="Grid_MouseWheel">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ToolBar>
<Button Command="ApplicationCommands.Open">
<Image Source="/WpfTutorialSamples;component/Images/folder.png" />
</Button>
<Separator />
<Button Command="MediaCommands.Play">
<Image Source="/WpfTutorialSamples;component/Images/control_play_blue.png" />
</Button>
<Button Command="MediaCommands.Pause">
<Image Source="/WpfTutorialSamples;component/Images/control_pause_blue.png" />
</Button>
<Button Command="MediaCommands.Stop">
<Image Source="/WpfTutorialSamples;component/Images/control_stop_blue.png" />
</Button>
</ToolBar>
<MediaElement Name="mePlayer" Grid.Row="1" LoadedBehavior="Manual" Stretch="None" />
<StatusBar Grid.Row="2">
<StatusBar.ItemsPanel>
<ItemsPanelTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</StatusBar.ItemsPanel>
<StatusBarItem>
<TextBlock Name="lblProgressStatus">00:00:00</TextBlock>
</StatusBarItem>
<StatusBarItem Grid.Column="1" HorizontalContentAlignment="Stretch">
<Slider Name="sliProgress" Thumb.DragStarted="sliProgress_DragStarted" Thumb.DragCompleted="sliProgress_DragCompleted" ValueChanged="sliProgress_ValueChanged" />
</StatusBarItem>
<StatusBarItem Grid.Column="2">
<ProgressBar Name="pbVolume" Width="50" Height="12" Maximum="1" Value="{Binding ElementName=mePlayer, Path=Volume}" />
</StatusBarItem>
</StatusBar>
</Grid>
</Window>
using System;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Threading;
using Microsoft.Win32;
namespace WpfTutorialSamples.Audio_and_Video
{
public partial class AudioVideoPlayerCompleteSample : Window
{
private bool mediaPlayerIsPlaying = false;
private bool userIsDraggingSlider = false;
public AudioVideoPlayerCompleteSample()
{
InitializeComponent();
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += timer_Tick;
timer.Start();
}
private void timer_Tick(object sender, EventArgs e)
{
if((mePlayer.Source != null) && (mePlayer.NaturalDuration.HasTimeSpan) && (!userIsDraggingSlider))
{
sliProgress.Minimum = 0;
sliProgress.Maximum = mePlayer.NaturalDuration.TimeSpan.TotalSeconds;
sliProgress.Value = mePlayer.Position.TotalSeconds;
}
}
private void Open_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void Open_Executed(object sender, ExecutedRoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Media files (*.mp3;*.mpg;*.mpeg)|*.mp3;*.mpg;*.mpeg|All files (*.*)|*.*";
if(openFileDialog.ShowDialog() == true)
mePlayer.Source = new Uri(openFileDialog.FileName);
}
private void Play_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = (mePlayer != null) && (mePlayer.Source != null);
}
private void Play_Executed(object sender, ExecutedRoutedEventArgs e)
{
mePlayer.Play();
mediaPlayerIsPlaying = true;
}
private void Pause_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = mediaPlayerIsPlaying;
}
private void Pause_Executed(object sender, ExecutedRoutedEventArgs e)
{
mePlayer.Pause();
}
private void Stop_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = mediaPlayerIsPlaying;
}
private void Stop_Executed(object sender, ExecutedRoutedEventArgs e)
{
mePlayer.Stop();
mediaPlayerIsPlaying = false;
}
private void sliProgress_DragStarted(object sender, DragStartedEventArgs e)
{
userIsDraggingSlider = true;
}
private void sliProgress_DragCompleted(object sender, DragCompletedEventArgs e)
{
userIsDraggingSlider = false;
mePlayer.Position = TimeSpan.FromSeconds(sliProgress.Value);
}
private void sliProgress_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
lblProgressStatus.Text = TimeSpan.FromSeconds(sliProgress.Value).ToString(@"hh\:mm\:ss");
}
private void Grid_MouseWheel(object sender, MouseWheelEventArgs e)
{
mePlayer.Volume += (e.Delta > 0) ? 0.1 : -0.1;
}
}
}
Podsumownie
Kod programu może wydawać się nieco przytłaczający, ale jak możcie zobaczyć, istnieje w nim wiele powtórzeń. Jeśli to przeanalizujesz to wkrótce przekonasz się, że stworzenie całkiem dobrego multimedialnego odtwarzacza w WPF nie jest naprawdę trudne! Nie miej żadnych oporów, aby zastosować go w swoich własnych projektach - np. zaimplementowanie funkcji list nagrań ?