728x90
반응형
728x170
[TestProject 프로젝트]
▶ 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:library="clr-namespace:TestLibrary;assembly=TestLibrary"
Width="800"
Height="600"
Title="NAUDIO 라이브러리를 사용해 음악 재생하기">
<Grid Background="{DynamicResource WindowBackgroundBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="100" />
<RowDefinition Height="*" />
<RowDefinition Height="100" />
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30*" />
<ColumnDefinition Width="60*" />
</Grid.ColumnDefinitions>
<Menu Grid.Row="0" Grid.ColumnSpan="2">
<MenuItem Header="파일">
<MenuItem Name="openFileMenuItem"
Header="파일 열기" />
<Separator />
<MenuItem Name="closeMenuItem"
Header="종료" />
</MenuItem>
<MenuItem Header="테마">
<MenuItem Name="defaultThemeMenuItem"
Header="디폴트 (테마 없음)"
IsCheckable="True" />
<MenuItem Name="expressionDarkThemeMenuItem"
Header="다크 테마"
IsCheckable="True" />
<MenuItem Name="expressionLightThemeMenuItem"
Header="라이트 테마"
IsCheckable="True" />
</MenuItem>
</Menu>
<library:DigitalClock x:Name="digitalClock" Grid.Row="1" Grid.ColumnSpan="2"
Margin="5"
HorizontalAlignment="Center"
ShowHours="False"
ShowSubSeconds="True" />
<library:AlbumArtDisplay x:Name="albumArtDisplay" Grid.Column="0" Grid.Row="2"
Margin="5" />
<Grid Grid.Row="2" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<library:SpectrumAnalyzer x:Name="spectrumAnalyzer"
Margin="5"
BarCount="16" />
<library:Equalizer x:Name="equalizer" Grid.Column="1"
BandCount="7" />
</Grid>
<Grid Grid.Row="3" Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<library:WaveformTimeline x:Name="waveformTimeline"
Margin="5"
BorderThickness="1" />
<StackPanel Grid.Column="1"
Orientation="Vertical"
VerticalAlignment="Center">
<library:TimeEditor Name="repeatStartTimeEdit"
Margin="5"
IsReadOnly="True" />
<library:TimeEditor Name="repeatStopTimeEdit"
Margin="5"
IsReadOnly="True" />
</StackPanel>
</Grid>
<Grid Grid.Row="4" Grid.ColumnSpan="2"
Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox Name="filePathTextBox" Grid.Column="0"
Margin="5"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
IsReadOnly="True" />
<StackPanel Grid.Column="1"
HorizontalAlignment="Right"
Orientation="Horizontal">
<Button Name="browseButton"
Margin="2 2 10 2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Height="24"
Width="50"
Content="선곡" />
<Button Name="playButton"
Margin="2"
Width="50"
VerticalAlignment="Center"
Height="24"
IsEnabled="False"
Content="재생" />
<Button Name="pauseButton"
Margin="2"
VerticalAlignment="Center"
Width="50"
Height="24"
IsEnabled="False"
Content="중지" />
<Button Name="stopButton"
Margin="2"
VerticalAlignment="Center"
Width="50"
Height="24"
IsEnabled="False"
Content="중단" />
</StackPanel>
</Grid>
</Grid>
</Window>
728x90
▶ MainWindow.xaml.cs
using Microsoft.Win32;
using System;
using System.ComponentModel;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using System.Windows.Data;
using TestLibrary;
namespace TestProject
{
/// <summary>
/// 메인 윈도우
/// </summary>
public partial class MainWindow : Window
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainWindow()
/// <summary>
/// 생성자
/// </summary>
public MainWindow()
{
InitializeComponent();
NAudioEngine naudioEngine = NAudioEngine.Instance;
UIHelper.Bind(naudioEngine, "CanStop" , this.stopButton , Button.IsEnabledProperty );
UIHelper.Bind(naudioEngine, "CanPlay" , this.playButton , Button.IsEnabledProperty );
UIHelper.Bind(naudioEngine, "CanPause" , this.pauseButton , Button.IsEnabledProperty );
UIHelper.Bind(naudioEngine, "SelectionBegin", this.repeatStartTimeEdit, TimeEditor.ValueProperty, BindingMode.TwoWay);
UIHelper.Bind(naudioEngine, "SelectionEnd" , this.repeatStopTimeEdit , TimeEditor.ValueProperty, BindingMode.TwoWay);
this.spectrumAnalyzer.RegisterSpectrumPlayer(naudioEngine);
this.waveformTimeline.RegisterSoundPlayer(naudioEngine);
LoadExpressionDarkTheme();
naudioEngine.PropertyChanged += naudioEngine_PropertyChanged;
this.openFileMenuItem.Click += openFileMenuItem_Click;
this.closeMenuItem.Click += closeMenuItem_Click;
this.defaultThemeMenuItem.Checked += defaultThemeMenuItem_Checked;
this.expressionDarkThemeMenuItem.Checked += expressionDarkThemeMenuItem_Checked;
this.expressionLightThemeMenuItem.Checked += expressionLightThemeMenuItem_Checked;
this.browseButton.Click += browseButton_Click;
this.playButton.Click += playButton_Click;
this.pauseButton.Click += pauseButton_Click;
this.stopButton.Click += stopButton_Click;
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Protected
#region 닫을 경우 처리하기 - OnClosing(e)
/// <summary>
/// 닫을 경우 처리하기
/// </summary>
/// <param name="e">이벤트 인자</param>
protected override void OnClosing(CancelEventArgs e)
{
NAudioEngine.Instance.Dispose();
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Private
//////////////////////////////////////////////////////////////////////////////// Event
#region NAUDIO 엔진 속성 변경시 처리하기 - naudioEngine_PropertyChanged(sender, e)
/// <summary>
/// NAUDIO 엔진 속성 변경시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void naudioEngine_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
NAudioEngine naudioEngine = NAudioEngine.Instance;
switch(e.PropertyName)
{
case "FileTag" :
if(naudioEngine.FileTag != null)
{
TagLib.Tag tag = naudioEngine.FileTag.Tag;
if(tag.Pictures.Length > 0)
{
using(MemoryStream memoryStream = new MemoryStream(tag.Pictures[0].Data.Data))
{
try
{
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = memoryStream;
bitmapImage.EndInit();
this.albumArtDisplay.AlbumArtImage = bitmapImage;
}
catch(NotSupportedException)
{
this.albumArtDisplay.AlbumArtImage = null;
}
memoryStream.Close();
}
}
else
{
this.albumArtDisplay.AlbumArtImage = null;
}
}
else
{
this.albumArtDisplay.AlbumArtImage = null;
}
break;
case "ChannelPosition" :
this.digitalClock.Time = TimeSpan.FromSeconds(naudioEngine.ChannelPosition);
break;
default:
break;
}
}
#endregion
#region 파일 열기 메뉴 항목 클릭시 처리하기 - openFileMenuItem_Click(sender, e)
/// <summary>
/// 파일 열기 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void openFileMenuItem_Click(object sender, RoutedEventArgs e)
{
OpenFile();
}
#endregion
#region 닫기 메뉴 항목 클릭시 처리하기 - closeMenuItem_Click(sender, e)
/// <summary>
/// 닫기 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void closeMenuItem_Click(object sender, RoutedEventArgs e)
{
Close();
}
#endregion
#region 디폴트 테마 메뉴 항목 클릭시 처리하기 - defaultThemeMenuItem_Checked(sender, e)
/// <summary>
/// 디폴트 테마 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void defaultThemeMenuItem_Checked(object sender, RoutedEventArgs e)
{
LoadDefaultTheme();
}
#endregion
#region 익스프레션 다크 테마 메뉴 항목 클릭시 처리하기 - expressionDarkThemeMenuItem_Checked(sender, e)
/// <summary>
/// 익스프레션 다크 테마 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void expressionDarkThemeMenuItem_Checked(object sender, RoutedEventArgs e)
{
LoadExpressionDarkTheme();
}
#endregion
#region 익스프레션 라이트 테마 메뉴 항목 클릭시 처리하기 - expressionLightThemeMenuItem_Checked(sender, e)
/// <summary>
/// 익스프레션 라이트 테마 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void expressionLightThemeMenuItem_Checked(object sender, RoutedEventArgs e)
{
LoadExpressionLightTheme();
}
#endregion
#region 선곡 버튼 클릭시 처리하기 - browseButton_Click(sender, e)
/// <summary>
/// 선곡 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void browseButton_Click(object sender, RoutedEventArgs e)
{
OpenFile();
}
#endregion
#region 재생 버튼 클릭시 처리하기 - playButton_Click(sender, e)
/// <summary>
/// 재생 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void playButton_Click(object sender, RoutedEventArgs e)
{
if(NAudioEngine.Instance.CanPlay)
{
NAudioEngine.Instance.Play();
}
}
#endregion
#region 중지 버튼 클릭시 처리하기 - pauseButton_Click(sender, e)
/// <summary>
/// 중지 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void pauseButton_Click(object sender, RoutedEventArgs e)
{
if(NAudioEngine.Instance.CanPause)
{
NAudioEngine.Instance.Pause();
}
}
#endregion
#region 중단 버튼 클릭시 처리하기 - stopButton_Click(sender, e)
/// <summary>
/// 중단 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void stopButton_Click(object sender, RoutedEventArgs e)
{
if(NAudioEngine.Instance.CanStop)
{
NAudioEngine.Instance.Stop();
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Event
#region 파일 열기 - OpenFile()
/// <summary>
/// 파일 열기
/// </summary>
private void OpenFile()
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "MP3 파일|*.mp3";
if(openFileDialog.ShowDialog() == true)
{
NAudioEngine.Instance.OpenFile(openFileDialog.FileName);
this.filePathTextBox.Text = openFileDialog.FileName;
}
}
#endregion
#region 디폴트 테마 로드하기 - LoadDefaultTheme()
/// <summary>
/// 디폴트 테마 로드하기
/// </summary>
private void LoadDefaultTheme()
{
this.defaultThemeMenuItem.IsChecked = true;
this.defaultThemeMenuItem.IsEnabled = false;
this.expressionDarkThemeMenuItem.IsChecked = false;
this.expressionDarkThemeMenuItem.IsEnabled = true;
this.expressionLightThemeMenuItem.IsChecked = false;
this.expressionLightThemeMenuItem.IsEnabled = true;
Resources.MergedDictionaries.Clear();
}
#endregion
#region 익스프레션 다크 테마 로드하기 - LoadExpressionDarkTheme()
/// <summary>
/// 익스프레션 다크 테마 로드하기
/// </summary>
private void LoadExpressionDarkTheme()
{
this.defaultThemeMenuItem.IsChecked = false;
this.defaultThemeMenuItem.IsEnabled = true;
this.expressionDarkThemeMenuItem.IsChecked = true;
this.expressionDarkThemeMenuItem.IsEnabled = false;
this.expressionLightThemeMenuItem.IsChecked = false;
this.expressionLightThemeMenuItem.IsEnabled = true;
Resources.MergedDictionaries.Clear();
ResourceDictionary resourceDictionary = Application.LoadComponent(new Uri("ExpressionDark.xaml", UriKind.Relative)) as ResourceDictionary;
Resources.MergedDictionaries.Add(resourceDictionary);
}
#endregion
#region 익스프레션 라이트 테마 로드하기 - LoadExpressionLightTheme()
/// <summary>
/// 익스프레션 라이트 테마 로드하기
/// </summary>
private void LoadExpressionLightTheme()
{
this.defaultThemeMenuItem.IsChecked = false;
this.defaultThemeMenuItem.IsEnabled = true;
this.expressionDarkThemeMenuItem.IsChecked = false;
this.expressionDarkThemeMenuItem.IsEnabled = true;
this.expressionLightThemeMenuItem.IsChecked = true;
this.expressionLightThemeMenuItem.IsEnabled = false;
Resources.MergedDictionaries.Clear();
ResourceDictionary themeResources = Application.LoadComponent(new Uri("ExpressionLight.xaml", UriKind.Relative)) as ResourceDictionary;
Resources.MergedDictionaries.Add(themeResources);
}
#endregion
}
}
※ 컴파일시 TestProject 프로젝트의 플랫폼 대상을 x86으로 설정해야 한다.
728x90
반응형
그리드형(광고전용)
'C# > WPF' 카테고리의 다른 글
[C#/WPF] Polyline 클래스 : 싸인 곡선 그리기 (0) | 2020.07.06 |
---|---|
[C#/WPF] Canvas 클래스 : 사용자 선 그리기 (0) | 2020.07.05 |
[C#/WPF] WindowInteropHelper 클래스 : Handle 속성을 사용해 윈도우 핸들 구하기 (0) | 2020.05.20 |
[C#/WPF] Application 클래스 : Shutdown 메소드를 사용해 애플리케이션 종료하기 (0) | 2020.02.29 |
[C#/WPF] MeshGeometry3D 클래스 : 구체 애니메이션 만들기 (0) | 2019.09.08 |
[C#/WPF] MeshGeometry3D 클래스 : 수레바퀴 만들기 (0) | 2019.09.02 |
[C#/WPF] ModelVisual3D 클래스 상속하기 (0) | 2019.09.01 |
[C#/WPF] object 객체에서 XAML 구하기 (0) | 2019.09.01 |
[C#/WPF] MeshGeometry3D 클래스 : 리소스 사용하기 (0) | 2019.09.01 |
[C#/WPF] MeshGeometry3D 클래스 : 리소스 사용하기 (0) | 2019.08.28 |
댓글을 달아 주세요