diff --git a/QuickLook/FocusMonitor.cs b/QuickLook/FocusMonitor.cs
new file mode 100644
index 0000000..49bfeb9
--- /dev/null
+++ b/QuickLook/FocusMonitor.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using QuickLook.Helpers;
+
+namespace QuickLook
+{
+ internal class FocusMonitor
+ {
+ public delegate void FocusedItemChangedEventHandler(FocusedItemChangedEventArgs e);
+
+ private static FocusMonitor _instance;
+
+ public bool IsRunning { get; private set; }
+
+ public event FocusedItemChangedEventHandler FocusedItemChanged;
+
+ public void Start()
+ {
+ IsRunning = true;
+
+ new Task(() =>
+ {
+ var currentPath = NativeMethods.QuickLook.GetCurrentSelectionFirst();
+
+ while (IsRunning)
+ {
+ Thread.Sleep(500);
+
+ if (WindowHelper.IsFocusedControlExplorerItem())
+ {
+ var file = NativeMethods.QuickLook.GetCurrentSelectionFirst();
+ if (file != currentPath)
+ {
+ FocusedItemChanged?.Invoke(new FocusedItemChangedEventArgs(file));
+ currentPath = file;
+ }
+ }
+ }
+ }).Start();
+ }
+
+ public void Stop()
+ {
+ IsRunning = false;
+ }
+
+ internal static FocusMonitor GetInstance()
+ {
+ return _instance ?? (_instance = new FocusMonitor());
+ }
+ }
+
+ internal class FocusedItemChangedEventArgs : EventArgs
+ {
+ public FocusedItemChangedEventArgs(string files)
+ {
+ FocusedFile = files;
+ }
+
+ public string FocusedFile { get; }
+ }
+}
\ No newline at end of file
diff --git a/QuickLook/Helpers/AutoStartupHelper.cs b/QuickLook/Helpers/AutoStartupHelper.cs
index c30c483..62cee1f 100644
--- a/QuickLook/Helpers/AutoStartupHelper.cs
+++ b/QuickLook/Helpers/AutoStartupHelper.cs
@@ -1,7 +1,7 @@
using System;
using System.IO;
using System.Runtime.InteropServices.ComTypes;
-using QuickLook.NativeMethods;
+using QuickLook.NativeMethods.Shell32;
namespace QuickLook.Helpers
{
diff --git a/QuickLook/Helpers/FileHelper.cs b/QuickLook/Helpers/FileHelper.cs
index af5b8c2..cb164d9 100644
--- a/QuickLook/Helpers/FileHelper.cs
+++ b/QuickLook/Helpers/FileHelper.cs
@@ -5,7 +5,7 @@ using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
-using QuickLook.NativeMethods;
+using QuickLook.NativeMethods.Shell32;
namespace QuickLook.Helpers
{
diff --git a/QuickLook/MainWindowTransparent.xaml.cs b/QuickLook/MainWindowTransparent.xaml.cs
index 7e7c88e..1cdb049 100644
--- a/QuickLook/MainWindowTransparent.xaml.cs
+++ b/QuickLook/MainWindowTransparent.xaml.cs
@@ -2,6 +2,7 @@
using System.Diagnostics;
using System.IO;
using System.Windows;
+using System.Windows.Forms;
using System.Windows.Threading;
using QuickLook.Helpers;
using QuickLook.Helpers.BlurLibrary;
@@ -42,7 +43,8 @@ namespace QuickLook
OpenWithAssocApp();
};*/
- buttonOpenWith.Click += (sender, e) => RunAndClose();
+ buttonOpenWith.Click += (sender, e) => ViewWindowManager.GetInstance()
+ .InvokeRoutine(new KeyEventArgs(Keys.Escape));
}
public ContextObject ContextObject { get; private set; }
diff --git a/QuickLook/NativeMethods/QuickLook.cs b/QuickLook/NativeMethods/QuickLook.cs
index 5c0dee3..65cd5b8 100644
--- a/QuickLook/NativeMethods/QuickLook.cs
+++ b/QuickLook/NativeMethods/QuickLook.cs
@@ -1,5 +1,7 @@
-using System.Runtime.InteropServices;
+using System.Linq;
+using System.Runtime.InteropServices;
using System.Text;
+using System.Threading.Tasks;
namespace QuickLook.NativeMethods
{
@@ -16,5 +18,30 @@ namespace QuickLook.NativeMethods
[DllImport("QuickLook.Native.Shell32.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern void GetCurrentSelectionBuffer([MarshalAs(UnmanagedType.LPWStr)] StringBuilder buffer);
+
+ internal static string[] GetCurrentSelection()
+ {
+ StringBuilder sb = null;
+ // communicate with COM in a separate thread
+ Task.Run(() =>
+ {
+ SaveCurrentSelection();
+
+ var n = GetCurrentSelectionCount();
+ if (n != 0)
+ {
+ sb = new StringBuilder(n * 261); // MAX_PATH + NULL = 261
+ GetCurrentSelectionBuffer(sb);
+ }
+ }).Wait();
+ return sb == null || sb.Length == 0 ? new string[0] : sb.ToString().Split('|');
+ }
+
+ internal static string GetCurrentSelectionFirst()
+ {
+ var files = GetCurrentSelection();
+
+ return files.Any() ? files.First() : string.Empty;
+ }
}
}
\ No newline at end of file
diff --git a/QuickLook/NativeMethods/ShellLink.cs b/QuickLook/NativeMethods/Shell32/IShellLink.cs
similarity index 61%
rename from QuickLook/NativeMethods/ShellLink.cs
rename to QuickLook/NativeMethods/Shell32/IShellLink.cs
index 574f7d6..bc136c6 100644
--- a/QuickLook/NativeMethods/ShellLink.cs
+++ b/QuickLook/NativeMethods/Shell32/IShellLink.cs
@@ -2,14 +2,8 @@
using System.Runtime.InteropServices;
using System.Text;
-namespace QuickLook.NativeMethods
+namespace QuickLook.NativeMethods.Shell32
{
- [ComImport]
- [Guid("00021401-0000-0000-C000-000000000046")]
- internal class ShellLink
- {
- }
-
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("000214F9-0000-0000-C000-000000000046")]
@@ -42,36 +36,4 @@ namespace QuickLook.NativeMethods
void Resolve(IntPtr hwnd, int fFlags);
void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
}
-
- [ComImport]
- [Guid("72C24DD5-D70A-438B-8A42-98424B88AFB8")]
- internal class WshShell
- {
- }
-
- [ComImport]
- [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
- [Guid("F935DC21-1CF0-11D0-ADB9-00C04FD58A0B")]
- internal interface IWshShell
- {
- IWshShortcut CreateShortcut(string pathLink);
- }
-
- [ComImport]
- [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
- [Guid("F935DC23-1CF0-11D0-ADB9-00C04FD58A0B")]
- internal interface IWshShortcut
- {
- string FullName { get; }
- string Arguments { get; set; }
- string Description { get; set; }
- string Hotkey { get; set; }
- string IconLocation { get; set; }
- string RelativePath { set; }
- string TargetPath { get; set; }
- int WindowStyle { get; set; }
- string WorkingDirectory { get; set; }
- void Load([In] string pathLink);
- void Save();
- }
}
\ No newline at end of file
diff --git a/QuickLook/NativeMethods/Shell32/IWshShell.cs b/QuickLook/NativeMethods/Shell32/IWshShell.cs
new file mode 100644
index 0000000..174e59d
--- /dev/null
+++ b/QuickLook/NativeMethods/Shell32/IWshShell.cs
@@ -0,0 +1,12 @@
+using System.Runtime.InteropServices;
+
+namespace QuickLook.NativeMethods.Shell32
+{
+ [ComImport]
+ [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
+ [Guid("F935DC21-1CF0-11D0-ADB9-00C04FD58A0B")]
+ internal interface IWshShell
+ {
+ IWshShortcut CreateShortcut(string pathLink);
+ }
+}
\ No newline at end of file
diff --git a/QuickLook/NativeMethods/Shell32/IWshShortcut.cs b/QuickLook/NativeMethods/Shell32/IWshShortcut.cs
new file mode 100644
index 0000000..bd25b16
--- /dev/null
+++ b/QuickLook/NativeMethods/Shell32/IWshShortcut.cs
@@ -0,0 +1,22 @@
+using System.Runtime.InteropServices;
+
+namespace QuickLook.NativeMethods.Shell32
+{
+ [ComImport]
+ [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
+ [Guid("F935DC23-1CF0-11D0-ADB9-00C04FD58A0B")]
+ internal interface IWshShortcut
+ {
+ string FullName { get; }
+ string Arguments { get; set; }
+ string Description { get; set; }
+ string Hotkey { get; set; }
+ string IconLocation { get; set; }
+ string RelativePath { set; }
+ string TargetPath { get; set; }
+ int WindowStyle { get; set; }
+ string WorkingDirectory { get; set; }
+ void Load([In] string pathLink);
+ void Save();
+ }
+}
\ No newline at end of file
diff --git a/QuickLook/NativeMethods/Shell32/ShellLink.cs b/QuickLook/NativeMethods/Shell32/ShellLink.cs
new file mode 100644
index 0000000..f637363
--- /dev/null
+++ b/QuickLook/NativeMethods/Shell32/ShellLink.cs
@@ -0,0 +1,10 @@
+using System.Runtime.InteropServices;
+
+namespace QuickLook.NativeMethods.Shell32
+{
+ [ComImport]
+ [Guid("00021401-0000-0000-C000-000000000046")]
+ internal class ShellLink
+ {
+ }
+}
\ No newline at end of file
diff --git a/QuickLook/NativeMethods/Shell32/WshShell.cs b/QuickLook/NativeMethods/Shell32/WshShell.cs
new file mode 100644
index 0000000..49ecfb2
--- /dev/null
+++ b/QuickLook/NativeMethods/Shell32/WshShell.cs
@@ -0,0 +1,10 @@
+using System.Runtime.InteropServices;
+
+namespace QuickLook.NativeMethods.Shell32
+{
+ [ComImport]
+ [Guid("72C24DD5-D70A-438B-8A42-98424B88AFB8")]
+ internal class WshShell
+ {
+ }
+}
\ No newline at end of file
diff --git a/QuickLook/QuickLook.csproj b/QuickLook/QuickLook.csproj
index 28f5406..d1298b9 100644
--- a/QuickLook/QuickLook.csproj
+++ b/QuickLook/QuickLook.csproj
@@ -83,6 +83,7 @@
+
@@ -108,7 +109,11 @@
-
+
+
+
+
+
diff --git a/QuickLook/ViewWindowManager.cs b/QuickLook/ViewWindowManager.cs
index 6389718..51e808b 100644
--- a/QuickLook/ViewWindowManager.cs
+++ b/QuickLook/ViewWindowManager.cs
@@ -1,9 +1,6 @@
using System;
using System.Diagnostics;
using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using QuickLook.Helpers;
@@ -14,11 +11,13 @@ namespace QuickLook
internal class ViewWindowManager
{
private static ViewWindowManager _instance;
+
private readonly MainWindowNoTransparent _viewWindowNoTransparent;
private readonly MainWindowTransparent _viewWindowTransparentTransparent;
-
private MainWindowTransparent _currentMainWindow;
+ private string _path = string.Empty;
+
internal ViewWindowManager()
{
_viewWindowTransparentTransparent = new MainWindowTransparent();
@@ -43,17 +42,17 @@ namespace QuickLook
TogglePreview(kea);
break;
case Keys.Escape:
- ClosePreview(kea, false);
+ ClosePreview(kea);
break;
case Keys.Enter:
- ClosePreview(kea, true);
+ RunAndClosePreview(kea);
break;
default:
break;
}
}
- private void ClosePreview(KeyEventArgs kea, bool runBeforeClose)
+ private void RunAndClosePreview(KeyEventArgs kea = null)
{
if (!WindowHelper.IsFocusedControlExplorerItem() && !WindowHelper.IsFocusedWindowSelf())
return;
@@ -61,26 +60,40 @@ namespace QuickLook
if (_currentMainWindow.Visibility != Visibility.Visible)
return;
- if (runBeforeClose)
- _currentMainWindow.RunAndClose();
- else
- _currentMainWindow.BeginHide();
- kea.Handled = true;
+ StopFocusMonitor();
+ _currentMainWindow.RunAndClose();
+ if (kea != null)
+ kea.Handled = true;
}
- private void TogglePreview(KeyEventArgs kea)
+ internal void ClosePreview(KeyEventArgs kea = null)
+ {
+ StopFocusMonitor();
+ _currentMainWindow.BeginHide();
+
+ if (kea != null)
+ kea.Handled = true;
+ }
+
+ private void TogglePreview(KeyEventArgs kea = null)
{
if (!WindowHelper.IsFocusedControlExplorerItem() && !WindowHelper.IsFocusedWindowSelf())
return;
if (_currentMainWindow.Visibility == Visibility.Visible)
- _currentMainWindow.BeginHide();
+ {
+ ClosePreview();
+ }
else
- InvokeViewer(GetCurrentSelection());
- kea.Handled = true;
+ {
+ _path = NativeMethods.QuickLook.GetCurrentSelectionFirst();
+ InvokeViewer();
+ }
+ if (kea != null)
+ kea.Handled = true;
}
- private void SwitchPreview(KeyEventArgs kea)
+ private void SwitchPreview(KeyEventArgs kea = null)
{
if (_currentMainWindow.Visibility != Visibility.Visible)
return;
@@ -88,21 +101,72 @@ namespace QuickLook
if (!WindowHelper.IsFocusedControlExplorerItem())
return;
- _currentMainWindow.UnloadPlugin();
- InvokeViewer(GetCurrentSelection());
- kea.Handled = false;
+ _path = NativeMethods.QuickLook.GetCurrentSelectionFirst();
+
+ InvokeViewer();
+ if (kea != null)
+ kea.Handled = false;
}
- internal void InvokeViewer(string path)
+ private void SwitchPreviewRemoteInvoke(FocusedItemChangedEventArgs e)
{
+ Debug.WriteLine("SwitchPreviewRemoteInvoke");
+
+ if (e.FocusedFile == _path)
+ return;
+
+ if (string.IsNullOrEmpty(e.FocusedFile))
+ return;
+
+ _currentMainWindow?.Dispatcher.Invoke(() =>
+ {
+ if (_currentMainWindow.Visibility != Visibility.Visible)
+ return;
+
+ if (!WindowHelper.IsFocusedControlExplorerItem())
+ return;
+
+ _path = NativeMethods.QuickLook.GetCurrentSelectionFirst();
+
+ InvokeViewer();
+ });
+ }
+
+ private void RunFocusMonitor()
+ {
+ if (!FocusMonitor.GetInstance().IsRunning)
+ {
+ FocusMonitor.GetInstance().Start();
+ FocusMonitor.GetInstance().FocusedItemChanged += SwitchPreviewRemoteInvoke;
+ }
+ }
+
+ private void StopFocusMonitor()
+ {
+ if (FocusMonitor.GetInstance().IsRunning)
+ {
+ FocusMonitor.GetInstance().Stop();
+ FocusMonitor.GetInstance().FocusedItemChanged -= SwitchPreviewRemoteInvoke;
+ }
+ }
+
+ internal bool InvokeViewer(string path = null)
+ {
+ if (path == null)
+ path = _path;
+
if (string.IsNullOrEmpty(path))
- return;
+ return false;
if (!Directory.Exists(path) && !File.Exists(path))
- return;
+ return false;
+
+ RunFocusMonitor();
var matchedPlugin = PluginManager.GetInstance().FindMatch(path);
BeginShowNewWindow(matchedPlugin, path);
+
+ return true;
}
private void BeginShowNewWindow(IViewer matchedPlugin, string path)
@@ -143,34 +207,6 @@ namespace QuickLook
}
}
- private string GetCurrentSelection()
- {
- var path = string.Empty;
-
- // communicate with COM in a separate thread
- Task.Run(() =>
- {
- var paths = GetCurrentSelectionNative();
-
- if (paths.Any())
- path = paths.First();
- })
- .Wait();
-
- return string.IsNullOrEmpty(path) ? string.Empty : path;
- }
-
- private string[] GetCurrentSelectionNative()
- {
- NativeMethods.QuickLook.SaveCurrentSelection();
-
- var n = NativeMethods.QuickLook.GetCurrentSelectionCount();
- var sb = new StringBuilder(n * 261); // MAX_PATH + NULL = 261
- NativeMethods.QuickLook.GetCurrentSelectionBuffer(sb);
-
- return sb.Length == 0 ? new string[0] : sb.ToString().Split('|');
- }
-
internal static ViewWindowManager GetInstance()
{
return _instance ?? (_instance = new ViewWindowManager());