diff --git a/ControlWindow.xaml.vb b/ControlWindow.xaml.vb
index e9786ec..6d8cfcb 100644
--- a/ControlWindow.xaml.vb
+++ b/ControlWindow.xaml.vb
@@ -1,10 +1,8 @@
Public Class ControlWindow
- Public Shared reallyclose As Boolean = False
-
Private Sub Window_Closing(sender As Object, e As ComponentModel.CancelEventArgs)
- If Not reallyclose Then
+ If Not MainWindow.reallyclose Then
e.Cancel = True
- Me.Hide()
+ Me.Hide() 'if close, next F1 will throw exception
End If
End Sub
diff --git a/EditWindow.xaml.vb b/EditWindow.xaml.vb
index 0bdc995..b8c9866 100644
--- a/EditWindow.xaml.vb
+++ b/EditWindow.xaml.vb
@@ -4,7 +4,7 @@
Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
- config = XElement.Load("config.xml")
+ config = XElement.Load(MainWindow.config_path)
Try
ListOfPic = MainWindow.ListOfPic.Clone
ListOfPic.ReadXml(New IO.StringReader(config.Element("DocumentElement").ToString))
@@ -46,12 +46,13 @@
Catch
pic = New BitmapImage
Dim encoder As New BmpBitmapEncoder
- Dim bmpsource = BitmapSource.Create(64, 64, 96, 96, PixelFormats.Indexed1, BitmapPalettes.BlackAndWhite, New Byte(64 * 8) {}, 8)
+ Dim bmpsource = BitmapSource.Create(256, 192, 96, 96, PixelFormats.Indexed1, BitmapPalettes.BlackAndWhite, New Byte(192 * 32) {}, 32)
encoder.Frames.Add(BitmapFrame.Create(bmpsource))
Using ms As New IO.MemoryStream
encoder.Save(ms)
ms.Position = 0
pic.BeginInit()
+ pic.CacheOption = BitmapCacheOption.OnLoad
pic.StreamSource = ms
pic.EndInit()
End Using
@@ -76,7 +77,7 @@
With date_tb
.Text = T_DateShown.Text
.FontFamily = New FontFamily("Georgia")
- .FontSize = h / 12
+ .FontSize = 15
.FontStyle = FontStyles.Italic
.Foreground = Brushes.White
.Effect = New Effects.DropShadowEffect With {.ShadowDepth = 2, .Opacity = 0.8}
@@ -90,7 +91,7 @@
.SnapsToDevicePixels = True
.Text = TB_TextShown.Text
.FontFamily = New FontFamily("Georgia")
- .FontSize = h / 12
+ .FontSize = 15
.Foreground = Brushes.White
.Effect = New Effects.DropShadowEffect With {.ShadowDepth = 2, .Opacity = 0.8}
End With
@@ -113,10 +114,10 @@
Dim lop As XElement = XElement.Parse(lop_str.ToString)
config.Elements("DocumentElement").Remove()
config.Add(lop)
- config.Save("config.xml")
+ config.Save(MainWindow.config_path)
End Using
- 'Using wt = Xml.XmlWriter.Create("config.xml")
+ 'Using wt = Xml.XmlWriter.Create(config_path)
' wt.WriteStartElement("ConfigSlideRoot")
' wt.WriteStartElement("folders_image")
' For Each folder In MainWindow.folders_image
diff --git a/Ken Burns Slideshow.v12.suo b/Ken Burns Slideshow.v12.suo
index 5008182..bdcceae 100644
Binary files a/Ken Burns Slideshow.v12.suo and b/Ken Burns Slideshow.v12.suo differ
diff --git a/Localization/StringResources.xaml b/Localization/StringResources.xaml
index 5edf764..4985f29 100644
--- a/Localization/StringResources.xaml
+++ b/Localization/StringResources.xaml
@@ -76,4 +76,8 @@
ExitText shownYou are using an outdated version of configuration file. Please delete config.xml and try again. Program will exit now.
+ Ken Burns Me!
+ Register menu
+ Unregister menu
+ Register right-click menu entry for folders in Windows Explorer.
diff --git a/Localization/StringResources.zh-CN.xaml b/Localization/StringResources.zh-CN.xaml
index 86bf3da..a6c21be 100644
--- a/Localization/StringResources.zh-CN.xaml
+++ b/Localization/StringResources.zh-CN.xaml
@@ -76,4 +76,8 @@
退出显示文本当前配置文件版本过低。请删除config.xml文件再试。程序将退出。
+ 用 Ken Burns Slideshow 播放
+ 注册文件夹关联
+ 解除文件夹关联
+ 在Windows资源管理器的文件夹右键菜单中添加播放选项。
diff --git a/MainWindow.xaml.vb b/MainWindow.xaml.vb
index fa2089e..117aff2 100644
--- a/MainWindow.xaml.vb
+++ b/MainWindow.xaml.vb
@@ -3,6 +3,8 @@
Class MainWindow
Public Shared ListOfPic As New System.Data.DataTable("ImageList")
Public Shared PicFormats() As String = {".jpg", ".jpeg", ".bmp", ".png", ".tif", ".tiff"}
+ Private BGMFormats() As String = {".mp3", ".wma", ".m4a", ".aac", ".wav", "asf"}
+ Public Shared config_path As String = "config.xml"
Dim ListOfMusic As New List(Of String)
Dim ran As New Random
Dim player As New System.Windows.Media.MediaPlayer
@@ -39,6 +41,7 @@ Class MainWindow
Public Shared blurmode As Integer = 0
Private Declare Function SetThreadExecutionState Lib "kernel32" (ByVal esFlags As EXECUTION_STATE) As EXECUTION_STATE
Dim ExecState_Set As Boolean
+ Public Shared reallyclose As Boolean = False
Private Enum EXECUTION_STATE As Integer
'''
''' Informs the system that the state being set should remain in effect until the next call that uses ES_CONTINUOUS and one of the other state flags is cleared.
@@ -71,23 +74,50 @@ Class MainWindow
ScaleMode_Dic.Add(3, Application.Current.Resources("medium"))
ScaleMode_Dic.Add(1, Application.Current.Resources("low"))
- 'loading config.xml
+ 'set working dir
+ IO.Directory.SetCurrentDirectory(IO.Path.GetDirectoryName(Reflection.Assembly.GetExecutingAssembly.Location))
+
+ 'check cmd args and load config
+ Dim cmdargs = Environment.GetCommandLineArgs
+ 'Dim cmdargs() As String = {"asdasd", "F:\Pictures\Giant", "F:\Pictures\Giant\1"}
Dim config As XElement
- Do
- Try
- config = XElement.Load("config.xml")
- Exit Do
- Catch
- If MsgBox(Application.Current.Resources("msg_loadcfgerr"), MsgBoxStyle.Question + MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
- Dim optwin As New OptWindow
- optwin.ShowDialog()
- optwin.Close()
- Else
- Me.Close()
- Exit Sub
- End If
- End Try
- Loop
+ If cmdargs.Length > 1 Then 'parametered start
+ If My.Computer.FileSystem.FileExists("config_instant.xml") Then
+ config = XElement.Load("config_instant.xml")
+ config.Element("PicDir").RemoveAll()
+ config.Element("Music").RemoveAll()
+ ElseIf My.Computer.FileSystem.FileExists(config_path) Then
+ config = XElement.Load(config_path)
+ config.Element("PicDir").RemoveAll()
+ config.Element("Music").RemoveAll()
+ Else 'generate necessary settings
+ config = New XElement("CfgRoot")
+ config.Add(New XElement("Version", FileVersionInfo.GetVersionInfo(Reflection.Assembly.GetExecutingAssembly().Location).FileVersion))
+ config.Add(New XElement("PicDir"))
+ config.Add(New XElement("Music"))
+ End If
+ config_path = "config_instant.xml"
+ For i = 1 To cmdargs.Length - 1
+ config.Element("PicDir").Add(New XElement("dir", New XCData(cmdargs(i))))
+ config.Element("Music").Add(New XElement("dir", New XCData(cmdargs(i))))
+ Next
+ Else 'normal start. loading config.xml
+ Do
+ Try
+ config = XElement.Load(config_path)
+ Exit Do
+ Catch
+ If MsgBox(Application.Current.Resources("msg_loadcfgerr"), MsgBoxStyle.Question + MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
+ Dim optwin As New OptWindow
+ optwin.ShowDialog()
+ optwin.Close()
+ Else
+ Me.Close()
+ Exit Sub
+ End If
+ End Try
+ Loop
+ End If
'config.xml version check
If config.Elements("Version").Any Then
@@ -147,14 +177,7 @@ Class MainWindow
'loading music list
folders_music.Clear()
- For Each ele In config.Element("Music").Elements
- folders_music.Add(ele.Value)
- If My.Computer.FileSystem.DirectoryExists(ele.Value) Then
- For Each f In My.Computer.FileSystem.GetFiles(ele.Value)
- ListOfMusic.Add(f)
- Next
- End If
- Next
+ FillMusic(config.Element("Music"))
'loading ListOfPic
ListOfPic.Clear()
@@ -163,34 +186,8 @@ Class MainWindow
End If
folders_image.Clear()
- For Each ele In config.Element("PicDir").Elements
- folders_image.Add(ele.Value)
- If My.Computer.FileSystem.DirectoryExists(ele.Value) Then
- For Each f In My.Computer.FileSystem.GetFiles(ele.Value)
- Dim filefullname = My.Computer.FileSystem.GetName(f)
- Dim filename = IO.Path.GetFileNameWithoutExtension(filefullname)
- Dim ext = IO.Path.GetExtension(filefullname)
- If PicFormats.Contains(ext.ToLower) Then
- Dim row = ListOfPic.Rows.Find(f)
- If row IsNot Nothing Then
- Dim tmpdate As Date
- If DateTime.TryParse(filename, tmpdate) Then
- row("Date") = DateTime.Parse(filename).ToString
- End If
- Else
- Dim tmprow = ListOfPic.NewRow
- tmprow("Path") = f
- Dim tmpdate As Date
- If DateTime.TryParse(filename, tmpdate) Then
- tmprow("Date") = DateTime.Parse(filename).ToString
- End If
- ListOfPic.Rows.Add(tmprow)
- End If
+ FillPic(config.Element("PicDir"))
- End If
- Next
- End If
- Next
'remove old paths
Dim tmplst As New List(Of System.Data.DataRow)
For Each row As System.Data.DataRow In ListOfPic.Rows
@@ -204,12 +201,13 @@ Class MainWindow
ListOfPic.Rows.Remove(row)
Next
+ 'check if no image
If ListOfPic.Rows.Count = 0 Then
If MsgBox(Application.Current.Resources("msg_noimgerr"), MsgBoxStyle.Question + MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
Dim optwin As New OptWindow
optwin.ShowDialog()
optwin.Close()
- config = XElement.Load("config.xml")
+ config = XElement.Load(config_path)
Else
Me.Close()
Exit Sub
@@ -225,7 +223,7 @@ Class MainWindow
Dim lop = XElement.Parse(lop_str.ToString)
config.Elements("DocumentElement").Remove()
config.Add(lop)
- config.Save("config.xml")
+ config.Save(config_path)
End Using
tb_date0.FontSize = h / 12
@@ -303,6 +301,7 @@ Class MainWindow
encoder.Save(ms)
ms.Position = 0
img.BeginInit()
+ img.CacheOption = BitmapCacheOption.OnLoad
img.StreamSource = ms
img.EndInit()
End Using
@@ -380,6 +379,51 @@ Class MainWindow
ExecState_Set = True
End Sub
+ Private Sub FillPic(PicDir_ele As XElement)
+ For Each ele In PicDir_ele.Elements
+ folders_image.Add(ele.Value)
+ If My.Computer.FileSystem.DirectoryExists(ele.Value) Then
+ For Each f In My.Computer.FileSystem.GetFiles(ele.Value)
+ Dim filefullname = My.Computer.FileSystem.GetName(f)
+ Dim filename = IO.Path.GetFileNameWithoutExtension(filefullname)
+ Dim ext = IO.Path.GetExtension(filefullname)
+ If PicFormats.Contains(ext.ToLower) Then
+ Dim row = ListOfPic.Rows.Find(f)
+ If row IsNot Nothing Then
+ Dim tmpdate As Date
+ If DateTime.TryParse(filename, tmpdate) Then
+ row("Date") = DateTime.Parse(filename).ToString
+ End If
+ Else
+ Dim tmprow = ListOfPic.NewRow
+ tmprow("Path") = f
+ Dim tmpdate As Date
+ If DateTime.TryParse(filename, tmpdate) Then
+ tmprow("Date") = DateTime.Parse(filename).ToString
+ End If
+ ListOfPic.Rows.Add(tmprow)
+ End If
+
+ End If
+ Next
+ End If
+ Next
+ End Sub
+
+ Private Sub FillMusic(Music_ele As XElement)
+ For Each ele In Music_ele.Elements
+ folders_music.Add(ele.Value)
+ If My.Computer.FileSystem.DirectoryExists(ele.Value) Then
+ For Each f In My.Computer.FileSystem.GetFiles(ele.Value)
+ Dim ext = IO.Path.GetExtension(f)
+ If BGMFormats.Contains(ext.ToLower) Then
+ ListOfMusic.Add(f)
+ End If
+ Next
+ End If
+ Next
+ End Sub
+
Private Function RandomNum(min As UInteger, max As UInteger, neg As Boolean)
If neg Then
If ran.Next(2) = 0 Then
@@ -446,7 +490,7 @@ Class MainWindow
.Effect = New Effects.DropShadowEffect With {.ShadowDepth = 2, .Opacity = 0.8}
End With
mainGrid.Children.Add(txt_tb)
- Panel.SetZIndex(txt_tb, 20)
+ Panel.SetZIndex(txt_tb, 8)
Dim anim_tbfadein As New Animation.DoubleAnimation(0, 0.7, New Duration(New TimeSpan(0, 0, 2)))
Dim anim_tbmovex As New Animation.DoubleAnimation(w * 0.7, w * 0.7 + RandomNum(h / 32, h / 25, True), New Duration(New TimeSpan(0, 0, tbmove_sec)))
@@ -979,6 +1023,7 @@ Class MainWindow
encoder.Save(ms)
ms.Position = 0
pic.BeginInit()
+ pic.CacheOption = BitmapCacheOption.OnLoad
pic.StreamSource = ms
pic.EndInit()
End Using
@@ -1132,9 +1177,33 @@ Class MainWindow
End Sub
Private Sub Window_Closing(sender As Object, e As ComponentModel.CancelEventArgs)
- ControlWindow.reallyclose = True
- If ctrlwindow IsNot Nothing Then ctrlwindow.Close()
- If ExecState_Set Then SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS)
+ If Not reallyclose Then
+ e.Cancel = True
+ If worker_pic IsNot Nothing AndAlso worker_pic.IsAlive Then
+ 'closing animation
+ Task.Run(AddressOf FadeoutAudio)
+ Dim black As New Rectangle
+ mainGrid.Children.Add(black)
+ Panel.SetZIndex(black, 9)
+ black.Fill = Windows.Media.Brushes.Black
+ black.Width = w
+ black.Height = h
+ Dim exit_fadeout As New Animation.DoubleAnimation(0, 1, New Duration(New TimeSpan(0, 0, 3)))
+ AddHandler exit_fadeout.Completed, Sub()
+ reallyclose = True
+ Me.Close()
+ End Sub
+ black.BeginAnimation(OpacityProperty, exit_fadeout)
+ Else
+ Dispatcher.BeginInvoke(Sub()
+ reallyclose = True
+ Me.Close()
+ End Sub)
+ End If
+ Else
+ If ctrlwindow IsNot Nothing Then ctrlwindow.Close()
+ If ExecState_Set Then SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS)
+ End If
End Sub
Private Sub ApplyBlur(tgt As Image, easeout As Animation.IEasingFunction, easein As Animation.IEasingFunction,
diff --git a/OptWindow.xaml b/OptWindow.xaml
index 00b1cc9..9d5cbf2 100644
--- a/OptWindow.xaml
+++ b/OptWindow.xaml
@@ -53,8 +53,9 @@
-
-
+
+
+
diff --git a/OptWindow.xaml.vb b/OptWindow.xaml.vb
index 1684727..10348b4 100644
--- a/OptWindow.xaml.vb
+++ b/OptWindow.xaml.vb
@@ -23,6 +23,12 @@
TB_LoadQuality.Text = MainWindow.loadquality
CbB_ScaleMode.SelectedItem = New KeyValuePair(Of Integer, String)(MainWindow.scalemode, MainWindow.ScaleMode_Dic(MainWindow.scalemode))
CbB_BlurMode.SelectedIndex = MainWindow.blurmode
+
+ If Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software\Classes\Directory\shell\OpenWithKenBurns\command") Is Nothing Then
+ Btn_FolderAsso.Content = Application.Current.Resources("register menu")
+ Else
+ Btn_FolderAsso.Content = Application.Current.Resources("unregister menu")
+ End If
End Sub
Private Sub CB_HorOptm_Change() Handles CB_HorOptm.Unchecked, CB_HorOptm.Checked, CB_HorOptm.Loaded
@@ -144,7 +150,7 @@
MainWindow.ListOfPic.WriteXml(lop_str)
Dim lop = XElement.Parse(lop_str.ToString)
config.Add(lop)
- config.Save("config.xml")
+ config.Save(MainWindow.config_path)
End Using
Me.Close()
@@ -225,4 +231,21 @@
End If
End If
End Sub
+
+ Private Sub Btn_FolderAsso_Click(sender As Object, e As RoutedEventArgs) Handles Btn_FolderAsso.Click
+ If Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software\Classes\Directory\shell\OpenWithKenBurns\command") Is Nothing Then
+ Dim shellkey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey("Software\Classes\Directory\shell\OpenWithKenBurns")
+ shellkey.SetValue("", Application.Current.Resources("ken burns me"), Microsoft.Win32.RegistryValueKind.String)
+ shellkey.CreateSubKey("command").SetValue("", """" & Reflection.Assembly.GetExecutingAssembly.Location & """ ""%1")
+ Btn_FolderAsso.Content = Application.Current.Resources("unregister menu")
+ Else
+ Dim dirkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software\Classes\Directory", True)
+ dirkey.DeleteSubKeyTree("shell\OpenWithKenBurns")
+ Dim shellkey = dirkey.OpenSubKey("shell", True)
+ If shellkey.SubKeyCount = 0 AndAlso shellkey.ValueCount = 0 Then
+ dirkey.DeleteSubKeyTree("shell")
+ End If
+ Btn_FolderAsso.Content = Application.Current.Resources("register menu")
+ End If
+ End Sub
End Class
diff --git a/README.md b/README.md
index 2c0f792..1d00607 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,7 @@ This idea came to me while watching a slideshow on iPad. How nice would it be if
- Support audio files to be played in loop at background.
- Options to load large images at lower resolution to improve performance.
- Options for each slide is now available by pressing F11.
+- Support launching slideshow directly from a folder containing images and audio files.
## Updates
- 2016-03-11
@@ -27,6 +28,7 @@ This idea came to me while watching a slideshow on iPad. How nice would it be if
- Added version verification.
- Added output preview in Edit Slide window.
- Improved text / date display loop.
+ - Option to add a shortcut menu entry for folders, from where the show can be launched directly.
- 2016-03-09
- Fixed Random transition not working properly.
- Minor changes on how date animation is handled.
@@ -93,3 +95,4 @@ transitions.
- Preferably a Windows 7 or above PC with a modern discrete GPU gives better / smoother performance.
- Framedrops may occur when certain programs are opened such as Potplayer and Foobar 2000.
- Choose "All at Once" under Load Mode to load all images at program start. It uses more memory but eliminates frame-drops in transition animation.
+- Audio files with URI escape marks in the file name (e.g. This%20is%20a%20song%28I%20am%20kidding%29.mp3) will not be recognized due to .Net won't take strings in Media.MediaPlayer.Open and the only URI it takes just keeps unescaping the file name whenever it can.
diff --git a/bin/Release/Ken Burns Slideshow.exe b/bin/Release/Ken Burns Slideshow.exe
index 7748673..4f99c5a 100644
Binary files a/bin/Release/Ken Burns Slideshow.exe and b/bin/Release/Ken Burns Slideshow.exe differ