728x90
반응형
728x170
▶ MediaPlayListItem.cs
namespace TestProject
{
/// <summary>
/// 미디어 재생 리스트 항목
/// </summary>
public class MediaPlayListItem
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 파일명 - FileName
/// <summary>
/// 파일명
/// </summary>
public string FileName { get; set; }
#endregion
#region 파일 경로 - FilePath
/// <summary>
/// 파일 경로
/// </summary>
public string FilePath { get; set; }
#endregion
}
}
728x90
▶ CustomSlider.cs
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace TestProject
{
/// <summary>
/// 커스텀 슬라이더
/// </summary>
public class CustomSlider : Slider
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Dependency Property
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Public
#region 자동 이동 여부 속성 - AutoMoveProperty
/// <summary>
/// 자동 이동 여부 속성
/// </summary>
public static readonly DependencyProperty AutoMoveProperty = DependencyProperty.Register
(
"AutoMove",
typeof(bool),
typeof(CustomSlider),
new FrameworkPropertyMetadata(false, AutoMovePropertyChangedCallback)
);
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 디폴트 포인트 이동 이용 가능 여부
/// </summary>
private bool defaultIsMoveToPointEnabled;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 자동 이동 여부 - AutoMove
/// <summary>
/// 자동 이동 여부
/// </summary>
public bool AutoMove
{
get
{
return (bool)GetValue(AutoMoveProperty);
}
set
{
SetValue(AutoMoveProperty, value);
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Private
#region 자동 이동 여부 속성 변경시 콜백 처리하기 - AutoMovePropertyChangedCallback(d, e)
/// <summary>
/// 자동 이동 여부 속성 변경시 콜백 처리하기
/// </summary>
/// <param name="d">의존 객체</param>
/// <param name="e">이벤트 인자</param>
private static void AutoMovePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
CustomSlider customSlider = d as CustomSlider;
if(customSlider != null)
{
if((bool)e.NewValue)
{
customSlider.defaultIsMoveToPointEnabled = customSlider.IsMoveToPointEnabled;
customSlider.IsMoveToPointEnabled = true;
customSlider.PreviewMouseMove += customSlider_PreviewMouseMove;
}
else
{
customSlider.IsMoveToPointEnabled = customSlider.defaultIsMoveToPointEnabled;
customSlider.PreviewMouseMove -= customSlider_PreviewMouseMove;
}
}
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Instance
//////////////////////////////////////////////////////////////////////////////// Private
#region 커스텀 슬라이더 PREVIEW 마우스 이동시 처리하기 - customSlider_PreviewMouseMove(sender, e)
/// <summary>
/// 커스텀 슬라이더 PREVIEW 마우스 이동시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private static void customSlider_PreviewMouseMove(object sender, MouseEventArgs e)
{
if(e.LeftButton == MouseButtonState.Pressed)
{
CustomSlider customSlider = sender as CustomSlider;
Point point = e.GetPosition(customSlider);
customSlider.Value = point.X / (customSlider.ActualWidth / customSlider.Maximum);
}
}
#endregion
}
}
300x250
▶ MediaPlayListWindow.xaml
<Window x:Class="TestProject.MediaPlayListWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowStyle="None"
MinWidth="300"
Width="300"
MinHeight="342"
Height="342"
Title="MediaPlayListWindow">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="23" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Row="0" Grid.RowSpan="2"
BorderThickness="5 0 5 5">
<Border.BorderBrush>
<LinearGradientBrush
StartPoint="0.5 0"
EndPoint="0.5 1">
<GradientStop Offset="0" Color="White" />
<GradientStop Offset="1" Color="#ff4e4e4e" />
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush
StartPoint="0.5 0"
EndPoint="0.5 1">
<GradientStop Offset="0" Color="#ff414141" />
<GradientStop Offset="1" Color="#ff2f2f2f" />
</LinearGradientBrush>
</Border.Background>
</Border>
<Grid Grid.Row="1"
Margin="10 0 10 12">
<Border
BorderThickness="1"
BorderBrush="#ff606060">
<ListBox Name="listBox"
Background="Black"
Foreground="White"
FontSize="12">
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Content" Value="{Binding FileName}" />
</Style>
</ListBox.Resources>
</ListBox>
</Border>
</Grid>
<StackPanel Grid.Row="0"
HorizontalAlignment="Right"
Margin="0 3 13 3"
Background="#00000000"
Orientation="Horizontal">
<Button Name="closeButton"
Style="{DynamicResource ButtonNullRecStyle}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="3 0 0 0"
FontSize="9">
<Image Source="IMAGE/btn_close.png" />
</Button>
</StackPanel>
<ResizeGrip Grid.Row="1"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="0 0 2 2" />
</Grid>
</Window>
반응형
▶ MediaPlayListWindow.xaml.cs
using System.Collections.ObjectModel;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace TestProject
{
/// <summary>
/// 미디어 재생 리스트 윈도우
/// </summary>
public partial class MediaPlayListWindow : Window
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Event
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 리스트 인덱스 변경시 이벤트 - ListIndexChanged
/// <summary>
/// 리스트 인덱스 변경시 이벤트
/// </summary>
public event ListIndexChangedHandler ListIndexChanged;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Delegate
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 리스트 인덱스 변경시 핸들러 - ListIndexChangedHandler
/// <summary>
/// 리스트 인덱스 변경시 핸들러
/// </summary>
/// <param name="index">인덱스</param>
public delegate void ListIndexChangedHandler(int index);
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 항목 소스 - ItemsSource
/// <summary>
/// 항목 소스
/// </summary>
public ObservableCollection<MediaPlayListItem> ItemsSource
{
set
{
this.listBox.ItemsSource = value;
}
}
#endregion
#region 선택 인덱스 - SelectedIndex
/// <summary>
/// 선택 인덱스
/// </summary>
public int SelectedIndex
{
set
{
this.listBox.SelectedIndex = value;
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MediaPlayListWindow()
/// <summary>
/// 생성자
/// </summary>
public MediaPlayListWindow()
{
InitializeComponent();
this.listBox.AllowDrop = true;
MouseLeftButtonDown += (s, e) => DragMove();
this.closeButton.Click += (s, e) => Close();
this.listBox.MouseDoubleClick += listBox_MouseDoubleClick;
this.listBox.DragOver += listBox_DragOver;
this.listBox.Drop += listBox_Drop;
this.listBox.KeyDown += listBox_KeyDown;
this.listBox.SelectionChanged += (s, e) => this.listBox.Focus();
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Private
#region 리스트 박스 마우스 더블 클릭시 처리하기 - listBox_MouseDoubleClick(sender, e)
/// <summary>
/// 리스트 박스 마우스 더블 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void listBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
Visual visual = e.OriginalSource as Visual;
while(visual != null)
{
if(visual is ListBoxItem)
{
ListIndexChanged?.Invoke(listBox.SelectedIndex);
break;
}
visual = VisualTreeHelper.GetParent(visual) as Visual;
}
}
#endregion
#region 리스트 박스 드래그 OVER 처리하기 - listBox_DragOver(sender, e)
/// <summary>
/// 리스트 박스 드래그 OVER 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void listBox_DragOver(object sender, DragEventArgs e)
{
if((e.AllowedEffects & DragDropEffects.Copy) == DragDropEffects.Copy)
{
e.Effects = DragDropEffects.Copy;
}
else
{
e.Effects = DragDropEffects.None;
}
e.Handled = true;
}
#endregion
#region 리스트 박스 DROP 처리하기 - listBox_Drop(sender, e)
/// <summary>
/// 리스트 박스 DROP 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void listBox_Drop(object sender, DragEventArgs e)
{
string[] filePathArray = e.Data.GetData(DataFormats.FileDrop) as string[];
foreach(string filePath in filePathArray)
{
FileInfo fileInfo = new FileInfo(filePath);
ObservableCollection<MediaPlayListItem> collection = this.listBox.ItemsSource as ObservableCollection<MediaPlayListItem>;
if(fileInfo.Extension.Equals(".wmv") || fileInfo.Extension.Equals(".avi") || fileInfo.Extension.Equals(".mp4"))
{
collection.Add
(
new MediaPlayListItem()
{
FileName = fileInfo.Name,
FilePath = filePath
}
);
}
}
if(this.listBox.Items.Count > 0 && this.listBox.SelectedIndex < 0)
{
this.listBox.SelectedIndex = 0;
}
e.Handled = true;
}
#endregion
#region 리스트 박스 키 DOWN 처리하기 - listBox_KeyDown(sender, e)
/// <summary>
/// 리스트 박스 키 DOWN 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void listBox_KeyDown(object sender, KeyEventArgs e)
{
if(e.Key == Key.Delete)
{
if(this.listBox.SelectedItem != null)
{
int index = this.listBox.SelectedIndex;
(this.listBox.ItemsSource as ObservableCollection<MediaPlayListItem>).RemoveAt(index);
if(index - 1 >= 0)
{
this.listBox.SelectedIndex = index - 1;
}
else if(this.listBox.Items.Count >= 1)
{
this.listBox.SelectedIndex = index;
}
}
}
}
#endregion
}
}
▶ MainWindow.xaml
<Window x:Class="TestProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestProject"
MinWidth="378"
Width="378"
MinHeight="342"
Height="342"
WindowStartupLocation="CenterScreen"
WindowStyle="None">
<Window.Resources>
<Storyboard x:Key="LoadedStoryboardKey" />
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource LoadedStoryboardKey}" />
</EventTrigger>
</Window.Triggers>
<Grid Name="rootGrid">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="VisualStateGroup">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="00:00:00.25">
<VisualTransition.GeneratedEasingFunction>
<QuadraticEase EasingMode="EaseInOut" />
</VisualTransition.GeneratedEasingFunction>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="VideoOverOnState" />
<VisualState x:Name="VideoOverOffState" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle
RadiusX="5"
RadiusY="5"
Stroke="White">
<Rectangle.Fill>
<LinearGradientBrush
StartPoint="0.5 0"
EndPoint="0.5 1">
<GradientStop Color="#fffdfffd" Offset="0" />
<GradientStop Color="White" Offset="0.07" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="23" />
<RowDefinition Height="*" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Grid.RowSpan="2"
Margin="6 0">
<Grid.RowDefinitions>
<RowDefinition Height="22" />
<RowDefinition Height="*" />
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<Border Grid.Row="0" Grid.RowSpan="3"
BorderThickness="1 0 1 1"
CornerRadius="0 0 5 5">
<Border.BorderBrush>
<LinearGradientBrush
StartPoint="0.5 0"
EndPoint="0.5 1">
<GradientStop Color="White" Offset="0" />
<GradientStop Color="#ff4e4e4e" Offset="1" />
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush
StartPoint="0.5 0"
EndPoint="0.5 1">
<GradientStop Offset="0" Color="#ff414141" />
<GradientStop Offset="1" Color="#ff2f2f2f" />
</LinearGradientBrush>
</Border.Background>
</Border>
<Border Name="videoBorder" Grid.Row="1"
Margin="6 0"
BorderThickness="1"
BorderBrush="#ff606060"
Background="Black">
<MediaElement Name="mediaElement"
Margin="1"
LoadedBehavior="Manual"
ScrubbingEnabled="True"
Volume="{Binding Value, ElementName=volumeSlider}" />
</Border>
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="22" />
<ColumnDefinition Width="66" />
</Grid.ColumnDefinitions>
<local:CustomSlider x:Name="timeLineSlider" Grid.Column="1"
Style="{DynamicResource SliderStyle}"
Margin="5 -1 0 0"
Cursor="Hand"
AutoMove="True"
Minimum="0"
Value="0"
IsEnabled="False" />
<ToggleButton Name="muteToggleButton" Grid.Column="2"
Style="{DynamicResource ToggleButtonMuteStyle}"
Width="11"
Padding="1 -3 1 1">
<Image Source="/IMAGE/btn_mute.png" />
</ToggleButton>
<Slider Name="volumeSlider" Grid.Column="4"
Style="{DynamicResource SliderStyle}"
Margin="0 -1 5 0"
Cursor="Hand"
Minimum="0"
Maximum="1"
Value="0.5" />
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="6 1 0 0"
Orientation="Horizontal">
<TextBlock
TextWrapping="Wrap"
Foreground="Black"
FontFamily="Helvesegoe-normal"
FontSize="11"
Text="{Binding ElementName=currentTimeTextBlock, Path=Text}" />
<TextBlock
Margin="2 0"
TextWrapping="Wrap"
Foreground="Black"
FontFamily="Helvesegoe-normal"
FontSize="11"
Text="/" />
<TextBlock
TextWrapping="Wrap"
Foreground="Black"
FontFamily="Helvesegoe-normal"
FontSize="11"
Text="{Binding ElementName=totalTimeTextBlock, Path=Text}" />
</StackPanel>
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="5 0 0 0"
Orientation="Horizontal">
<TextBlock Name="currentTimeTextBlock"
TextWrapping="Wrap"
Foreground="{DynamicResource OrangeBrush}"
FontFamily="Helvesegoe-normal"
FontSize="11"
Text="00:00:00" />
<TextBlock
Margin="2 0"
TextWrapping="Wrap"
Foreground="{DynamicResource OrangeBrush}"
FontFamily="Helvesegoe-normal"
FontSize="11"
Text="/" />
<TextBlock Name="totalTimeTextBlock"
TextWrapping="Wrap"
Foreground="{DynamicResource OrangeBrush}"
FontFamily="Helvesegoe-normal"
FontSize="11"
Text="00:00:00" />
</StackPanel>
</Grid>
</Grid>
<Grid Grid.Row="2"
Margin="0 4 0 0">
<Grid.Background>
<ImageBrush ImageSource="/IMAGE/bg_repeat.png" />
</Grid.Background>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="9" />
<ColumnDefinition Width="44" />
<ColumnDefinition Width="29" />
<ColumnDefinition Width="29" />
<ColumnDefinition Width="29" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="28" />
<ColumnDefinition Width="29" />
<ColumnDefinition Width="44" />
<ColumnDefinition Width="8" />
</Grid.ColumnDefinitions>
<ToggleButton Name="playToggleButton" Grid.Column="1"
Style="{DynamicResource tBtnPlayPauseStyle}"
VerticalAlignment="Top"
IsChecked="True" />
<Button Name="stopButton" Grid.Column="2"
Style="{DynamicResource ButtonNullStyle}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="2 0 0 0"
Width="26"
Height="26"
FontSize="9">
<Image Source="/IMAGE/btn_stop.png" />
</Button>
<Button Name="previousButton" Grid.Column="3"
Style="{DynamicResource ButtonNullStyle}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="1 0 0 0"
Width="26"
Height="26"
FontSize="9">
<Image Source="/IMAGE/btn_previous.png" />
</Button>
<Button Name="nextButton" Grid.Column="4"
Style="{DynamicResource ButtonNullStyle}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="0"
Width="26"
Height="26"
FontSize="9">
<Image Source="/IMAGE/btn_next.png" />
</Button>
<Grid Grid.Column="5"
Margin="4 0 7 19">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="15" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="15" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0"
Source="/IMAGE/bg_left.png" />
<Image Grid.Column="1"
Margin="-1 0"
Stretch="Fill"
Source="/IMAGE/bg_center.png" />
<Image Grid.Column="2"
Source="/IMAGE/bg_right.png" />
<TextBlock Name="titleTextBlock" Grid.Column="0" Grid.ColumnSpan="3"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="0 -3 0 0"
TextTrimming="CharacterEllipsis"
Foreground="{DynamicResource OrangeBrush}" />
</Grid>
<Button Name="openButton" Grid.Column="6"
Style="{DynamicResource ButtonNullStyle}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Width="26"
Height="26"
FontSize="9">
<Image Source="/IMAGE/btn_open.png" />
</Button>
<Button Name="playListButton" Grid.Column="7"
Style="{DynamicResource ButtonNullStyle}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Width="26"
Height="26"
FontSize="9">
<Image Source="/IMAGE/btn_playlist.png" />
</Button>
<Button Name="linkButton" Grid.Column="8"
Style="{DynamicResource ButtonNullStyle}"
Margin="0 0 0 2">
<Image Source="/IMAGE/logo_big.png" />
</Button>
<ResizeGrip Grid.Column="9"
VerticalAlignment="Bottom"
Margin="-10 0 1 1" />
</Grid>
<Grid Grid.Row="0"
Margin="0 3 12 2">
<StackPanel
HorizontalAlignment="Right"
Margin="0 0 0 1"
Orientation="Horizontal"
Background="#00000000">
<Button Name="setFullScreenButton"
Style="{DynamicResource ButtonNullRecStyle}"
Margin="2 0 0 0"
FontSize="9">
<Image Source="/IMAGE/btn_full.png" />
</Button>
<Rectangle
Margin="3 -2 1 0"
Width="1"
Height="15"
Fill="Black" />
<Button Name="minimizeButton"
Style="{DynamicResource ButtonNullRecStyle}"
Margin="2 0 0 0"
FontSize="9">
<Image Source="/IMAGE/btn_min.png" />
</Button>
<Button Name="maximizeButton"
Style="{DynamicResource ButtonNullRecStyle}"
Margin="2 0 0 0"
FontSize="9">
<Image Source="/IMAGE/btn_max.png" />
</Button>
<Button Name="closeButton"
Style="{DynamicResource ButtonNullRecStyle}"
Margin="2 0 0 0"
FontSize="9">
<Image Source="/IMAGE/btn_close.png" />
</Button>
</StackPanel>
<Image
HorizontalAlignment="Left"
Margin="13 0 0 1"
Source="/IMAGE/logo_small.png" />
</Grid>
</Grid>
</Grid>
</Window>
▶ MainWindow.xaml.cs
using Microsoft.Win32;
using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.IO;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
namespace TestProject
{
/// <summary>
/// 메인 윈도우
/// </summary>
public partial class MainWindow : Window
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 전체 화면 여부
/// </summary>
private bool isFullScreen = false;
/// <summary>
/// 정지 여부
/// </summary>
private bool isPause = true;
/// <summary>
/// 영상 종료 여부
/// </summary>
private bool isClosed = false;
/// <summary>
/// 타임라인 이동 여부
/// </summary>
private bool isTimelineMoving = false;
/// <summary>
/// 현재 재생 인덱스
/// </summary>
private int currentPlayIndex = 0;
/// <summary>
/// 타이머
/// </summary>
private DispatcherTimer timer = new DispatcherTimer();
/// <summary>
/// 미디어 재생 리스트 컬렉션
/// </summary>
private ObservableCollection<MediaPlayListItem> mediaPlayCollection = new ObservableCollection<MediaPlayListItem>();
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainWindow()
/// <summary>
/// 생성자
/// </summary>
public MainWindow()
{
InitializeComponent();
this.videoBorder.AllowDrop = true;
this.timer.Interval = TimeSpan.FromSeconds(1);
MouseLeftButtonDown += (s, e) => DragMove();
KeyDown += Window_KeyDown;
this.setFullScreenButton.Click += (s, e) => SetFullScreen();
this.minimizeButton.Click += (s, e) => this.WindowState = WindowState.Minimized;
this.maximizeButton.Click += maximizeButton_Click;
this.closeButton.Click += (s, e) => Exit();
this.videoBorder.DragOver += videoBorder_DragOver;
this.videoBorder.Drop += videoBorder_Drop;
this.mediaElement.MediaOpened += mediaElement_MediaOpened;
this.mediaElement.MediaEnded += mediaElement_MediaEnded;
this.timeLineSlider.PreviewMouseMove += timeLineSlider_PreviewMouseMove;
this.timeLineSlider.PreviewMouseLeftButtonUp += timeLineSlider_PreviewMouseLeftButtonUp;
this.timeLineSlider.ValueChanged += timeLineSlider_ValueChanged;
this.muteToggleButton.Click += (s, e) => this.mediaElement.IsMuted = !this.mediaElement.IsMuted;
this.playToggleButton.Click += playToggleButton_Click;
this.stopButton.Click += (s, e) => { CloseMedia(); this.timeLineSlider.Value = 0; };
this.previousButton.Click += (s, e) => PlayMedia(this.currentPlayIndex - 1);
this.nextButton.Click += (s, e) => PlayMedia(this.currentPlayIndex + 1);
this.openButton.Click += (s, e) => ShowFileDialog();
this.playListButton.Click += playListButton_Click;
this.timer.Tick += (s, e) => { this.timeLineSlider.Value = (int)Math.Round(this.mediaElement.Position.TotalSeconds); };
this.mediaPlayCollection.CollectionChanged += mediaPlayCollection_CollectionChanged;
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Private
#region 윈도우 키 DOWN 처리하기 - Window_KeyDown(sender, e)
/// <summary>
/// 윈도우 키 DOWN 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void Window_KeyDown(object sender, KeyEventArgs e)
{
if(e.Key == Key.Escape)
{
if(this.isFullScreen)
{
SetFullScreen();
}
else
{
Exit();
}
}
}
#endregion
#region 최대화 버튼 클릭시 처리하기 - maximizeButton_Click(sender, e)
/// <summary>
/// 최대화 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void maximizeButton_Click(object sender, RoutedEventArgs e)
{
if(WindowState == WindowState.Normal)
{
WindowState = WindowState.Maximized;
}
else
{
WindowState = WindowState.Normal;
}
}
#endregion
#region 비디오 테두리 드래그 OVER 처리하기 - videoBorder_DragOver(sender, e)
/// <summary>
/// 비디오 테두리 드래그 OVER 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void videoBorder_DragOver(object sender, DragEventArgs e)
{
if((e.AllowedEffects & DragDropEffects.Copy) == DragDropEffects.Copy)
{
if(e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effects = DragDropEffects.Copy;
}
else
{
e.Effects = DragDropEffects.None;
}
e.Handled = true;
}
}
#endregion
#region 비디오 테두리 DROP 처리하기 - videoBorder_Drop(sender, e)
/// <summary>
/// 비디오 테두리 DROP 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void videoBorder_Drop(object sender, DragEventArgs e)
{
string[] filePathArray = e.Data.GetData(DataFormats.FileDrop) as string[];
bool isClear = false;
foreach(string filePath in filePathArray)
{
FileInfo fileInfo = new FileInfo(filePath);
if(fileInfo.Extension.Equals(".wmv") || fileInfo.Extension.Equals(".avi") || fileInfo.Extension.Equals(".mp4"))
{
if(!isClear)
{
isClear = true;
this.mediaPlayCollection.Clear();
}
this.mediaPlayCollection.Add
(
new MediaPlayListItem()
{
FileName = fileInfo.Name,
FilePath = filePath
}
);
}
}
e.Handled = true;
if(this.mediaPlayCollection.Count > 0)
{
PlayMedia(0);
}
}
#endregion
#region 미디어 엘리먼트 미디어 오픈시 처리하기 - mediaElement_MediaOpened(sender, e)
/// <summary>
/// 미디어 엘리먼트 미디어 오픈시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void mediaElement_MediaOpened(object sender, RoutedEventArgs e)
{
this.titleTextBlock.Text = this.mediaPlayCollection[this.currentPlayIndex].FileName;
this.Width += this.mediaElement.NaturalVideoWidth -
(this.videoBorder.ActualWidth - (this.videoBorder.BorderThickness.Left + this.videoBorder.BorderThickness.Right ));
this.Height += this.mediaElement.NaturalVideoHeight -
(this.videoBorder.ActualHeight - (this.videoBorder.BorderThickness.Top + this.videoBorder.BorderThickness.Bottom));
if(this.mediaElement.NaturalDuration.HasTimeSpan)
{
this.timeLineSlider.Maximum = (int)this.mediaElement.NaturalDuration.TimeSpan.TotalSeconds;
this.totalTimeTextBlock.Text = this.mediaElement.NaturalDuration.TimeSpan.ToString().Substring(0, 8);
}
this.timeLineSlider.IsEnabled = true;
this.playToggleButton.IsChecked = false;
this.isClosed = false;
}
#endregion
#region 미디어 엘리먼트 미디어 종료시 처리하기 - mediaElement_MediaEnded(sender, e)
/// <summary>
/// 미디어 엘리먼트 미디어 종료시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void mediaElement_MediaEnded(object sender, RoutedEventArgs e)
{
if(this.currentPlayIndex + 1 < this.mediaPlayCollection.Count)
{
this.mediaElement.Source = new Uri(this.mediaPlayCollection[++this.currentPlayIndex].FilePath, UriKind.Absolute);
SetMediaPlayListWindowIndex();
}
else
{
CloseMedia();
}
}
#endregion
#region 타임 라인 슬라이더 PREVIEW 마우스 이동시 처리하기 - timeLineSlider_PreviewMouseMove(sender, e)
/// <summary>
/// 타임 라인 슬라이더 PREVIEW 마우스 이동시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void timeLineSlider_PreviewMouseMove(object sender, MouseEventArgs e)
{
if(e.LeftButton == MouseButtonState.Pressed && !this.isTimelineMoving)
{
this.isTimelineMoving = true;
if(!this.isClosed)
{
this.timer.Stop();
this.mediaElement.Pause();
}
}
}
#endregion
#region 타임 라인 슬라이더 PREVIEW 마우스 왼쪽 버튼 UP 처리하기 - timeLineSlider_PreviewMouseLeftButtonUp(sender, e)
/// <summary>
/// 타임 라인 슬라이더 PREVIEW 마우스 왼쪽 버튼 UP 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void timeLineSlider_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
this.isTimelineMoving = false;
if(!this.isPause && !this.isClosed)
{
this.mediaElement.Position = TimeSpan.FromSeconds(this.timeLineSlider.Value);
this.timer.Start();
this.mediaElement.Play();
}
}
#endregion
#region 타임 라인 슬라이더 값 변경시 처리하기 - timeLineSlider_ValueChanged(sender, e)
/// <summary>
/// 타임 라인 슬라이더 값 변경시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void timeLineSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if(this.isTimelineMoving && !this.isClosed)
{
this.mediaElement.Position = TimeSpan.FromSeconds(e.NewValue);
}
this.currentTimeTextBlock.Text = TimeSpan.FromSeconds(e.NewValue).ToString().Substring(0, 8);
}
#endregion
#region 재생 토글 버튼 클릭시 처리하기 - playToggleButton_Click(sender, e)
/// <summary>
/// 재생 토글 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void playToggleButton_Click(object sender, RoutedEventArgs e)
{
if(this.mediaElement.Source == null)
{
this.playToggleButton.IsChecked = true;
ShowFileDialog();
return;
}
if(this.isPause || this.isClosed)
{
PlayMedia();
}
else
{
PauseMedia();
}
}
#endregion
#region 재생 리스트 버튼 클릭시 처리하기 - playListButton_Click(sender, e)
/// <summary>
/// 재생 리스트 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void playListButton_Click(object sender, RoutedEventArgs e)
{
if(Application.Current.Windows.Count > 1)
{
Application.Current.Windows[1].Close();
}
else
{
MediaPlayListWindow window = new MediaPlayListWindow();
window.ItemsSource = this.mediaPlayCollection;
window.ListIndexChanged += (index) => PlayMedia(index);
window.SelectedIndex = 0;
if(WindowState == WindowState.Maximized)
{
window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
}
else
{
window.Left = Left + ActualWidth;
window.Top = Top;
}
window.Show();
}
}
#endregion
#region 미디어 재생 리스트 컬렉션 변경시 처리하기 - mediaPlayListCollection_CollectionChanged(sender, e)
/// <summary>
/// 미디어 재생 리스트 컬렉션 변경시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void mediaPlayCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if(e.Action == NotifyCollectionChangedAction.Remove)
{
if(this.mediaPlayCollection.Count > 0)
{
PlayMedia(this.currentPlayIndex + 1);
}
else
{
CloseMedia();
this.mediaElement.Source = null;
this.timeLineSlider.Value = 0;
this.totalTimeTextBlock.Text = "00:00:00";
}
}
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Function
#region 전체 화면 설정하기 - SetFullScreen()
/// <summary>
/// 전체 화면 설정하기
/// </summary>
private void SetFullScreen()
{
TimeSpan mediaElementPosition = this.mediaElement.Position;
this.isFullScreen = !this.isFullScreen;
if(this.isFullScreen)
{
this.videoBorder.Child = null;
Content = this.mediaElement;
Background = Brushes.Black;
WindowState = WindowState.Maximized;
}
else
{
Content = this.rootGrid;
this.videoBorder.Child = this.mediaElement;
Background = Brushes.White;
WindowState = WindowState.Normal;
}
this.mediaElement.Position = mediaElementPosition;
}
#endregion
#region 종료하기 - Exit()
/// <summary>
/// 종료하기
/// </summary>
private void Exit()
{
this.timer.Stop();
this.mediaElement.Close();
foreach(Window window in Application.Current.Windows)
{
window.Close();
}
}
#endregion
#region 파일 대화 상자 표시하기 - ShowFileDialog()
/// <summary>
/// 파일 대화 상자 표시하기
/// </summary>
private void ShowFileDialog()
{
OpenFileDialog openFileDialog = new OpenFileDialog()
{
Filter = "미디어 파일 (*.wmv, *.avi, *.mp4)|*.wmv;*.avi;*.mp4",
Multiselect = true
};
if((bool)openFileDialog.ShowDialog())
{
this.mediaPlayCollection.Clear();
string[] filePathArray = openFileDialog.FileNames;
string[] fileNameArray = openFileDialog.SafeFileNames;
int i = 0;
foreach(string filePath in filePathArray)
{
this.mediaPlayCollection.Add
(
new MediaPlayListItem()
{
FilePath = filePath,
FileName = fileNameArray[i++]
}
);
}
PlayMedia(0);
}
}
#endregion
#region 미디어 재생 리스트 윈도우 인덱스 설정하기 - SetMediaPlayListWindowIndex()
/// <summary>
/// 미디어 재생 리스트 윈도우 인덱스 설정하기
/// </summary>
private void SetMediaPlayListWindowIndex()
{
if(Application.Current.Windows.Count > 1)
{
(Application.Current.Windows[1] as MediaPlayListWindow).SelectedIndex = this.currentPlayIndex;
}
}
#endregion
#region 미디어 재생하기 - PlayMedia()
/// <summary>
/// 미디어 재생하기
/// </summary>
private void PlayMedia()
{
if(this.isClosed)
{
this.timeLineSlider.Value = 0;
}
this.timer.Start();
this.mediaElement.Play();
this.isPause = false;
}
#endregion
#region 미디어 재생하기 - PlayMedia(index)
/// <summary>
/// 미디어 재생하기
/// </summary>
/// <param name="index">인덱스</param>
private void PlayMedia(int index)
{
if(this.mediaPlayCollection.Count.Equals(0))
{
return;
}
if(index >= this.mediaPlayCollection.Count)
{
index = 0;
}
else if(index < 0)
{
index = this.mediaPlayCollection.Count - 1;
}
this.currentPlayIndex = index;
this.mediaElement.Source = new Uri(this.mediaPlayCollection[this.currentPlayIndex].FilePath, UriKind.Absolute);
PlayMedia();
SetMediaPlayListWindowIndex();
}
#endregion
#region 미디어 정지하기 - PauseMedia()
/// <summary>
/// 미디어 정지하기
/// </summary>
private void PauseMedia()
{
this.timer.Stop();
this.mediaElement.Pause();
this.isPause = true;
}
#endregion
#region 미디어 닫기 - CloseMedia()
/// <summary>
/// 미디어 닫기
/// </summary>
private void CloseMedia()
{
this.timer.Stop();
this.mediaElement.Close();
this.playToggleButton.IsChecked = true;
this.isClosed = true;
}
#endregion
}
}
728x90
반응형
그리드형(광고전용)
'C# > WPF' 카테고리의 다른 글
[C#/WPF] UserControl 엘리먼트 : 로딩 패널 사용하기 (0) | 2021.09.13 |
---|---|
[C#/WPF] Adorner 클래스 : 슬라이딩 어도너 사용하기 (0) | 2021.09.13 |
[C#/WPF] UserControl 클래스 : 로딩 패널 사용하기 (0) | 2021.09.11 |
[C#/WPF] ImageAwesome 엘리먼트 : Spin/SpinDuration 속성을 사용해 아이콘 회전시키기 (0) | 2021.09.11 |
[C#/WPF] 누겟 설치 : FontAwesome.WPF (0) | 2021.09.11 |
[C#/WPF] LinearGradientBrush 엘리먼트 사용하기 (0) | 2021.08.24 |
[C#/WPF] Vector 구조체 : 각도에서 벡터 구하기 (0) | 2021.08.20 |
[C#/WPF] Window 클래스 : 커스텀 윈도우 사용하기 (0) | 2021.08.20 |
[C#/WPF] Application 클래스 : Restart 메소드를 사용해 애플리케이션 재시작하기 (0) | 2021.08.19 |
[C#/WPF] Vector 구조체 : 벡터 각도 구하기 (0) | 2021.08.19 |
댓글을 달아 주세요