첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

TestProject.zip
0.10MB

▶ 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
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요