handle ENTER key and refactoring invoke routine

This commit is contained in:
Paddy Xu
2017-05-27 00:35:52 +03:00
parent 9fbf33b4aa
commit 4c82f1a9f4
7 changed files with 111 additions and 79 deletions

View File

@@ -11,7 +11,7 @@ namespace QuickLook
protected BackgroundListener() protected BackgroundListener()
{ {
InstallHook(HotkeyEventHandler); InstallKeyHook(HotkeyEventHandler);
} }
public void Dispose() public void Dispose()
@@ -27,18 +27,19 @@ namespace QuickLook
ViewWindowManager.GetInstance().InvokeRoutine(e.KeyCode); ViewWindowManager.GetInstance().InvokeRoutine(e.KeyCode);
} }
private void InstallHook(KeyEventHandler handler) private void InstallKeyHook(KeyEventHandler handler)
{ {
_hook = GlobalKeyboardHook.GetInstance(); _hook = GlobalKeyboardHook.GetInstance();
_hook.HookedKeys.Add(Keys.Space); _hook.HookedDownKeys.Add(Keys.Enter);
//_hook.HookedKeys.Add(Keys.Enter); _hook.KeyDown += handler;
_hook.HookedKeys.Add(Keys.Up);
_hook.HookedKeys.Add(Keys.Down);
_hook.HookedKeys.Add(Keys.Left);
_hook.HookedKeys.Add(Keys.Right);
_hook.HookedUpKeys.Add(Keys.Space);
_hook.HookedUpKeys.Add(Keys.Escape);
_hook.HookedUpKeys.Add(Keys.Up);
_hook.HookedUpKeys.Add(Keys.Down);
_hook.HookedUpKeys.Add(Keys.Left);
_hook.HookedUpKeys.Add(Keys.Right);
_hook.KeyUp += handler; _hook.KeyUp += handler;
} }

View File

@@ -14,7 +14,8 @@ namespace QuickLook
private User32.KeyboardHookProc _callback; private User32.KeyboardHookProc _callback;
private IntPtr _hhook = IntPtr.Zero; private IntPtr _hhook = IntPtr.Zero;
internal List<Keys> HookedKeys = new List<Keys>(); internal List<Keys> HookedDownKeys = new List<Keys>();
internal List<Keys> HookedUpKeys = new List<Keys>();
protected GlobalKeyboardHook() protected GlobalKeyboardHook()
{ {
@@ -63,13 +64,21 @@ namespace QuickLook
if (code >= 0) if (code >= 0)
{ {
var key = (Keys) lParam.vkCode; var key = (Keys) lParam.vkCode;
if (HookedKeys.Contains(key)) if (HookedDownKeys.Contains(key))
{ {
key = AddModifiers(key); key = AddModifiers(key);
var kea = new KeyEventArgs(key); var kea = new KeyEventArgs(key);
if (wParam == User32.WM_KEYDOWN || wParam == User32.WM_SYSKEYDOWN) if (wParam == User32.WM_KEYDOWN || wParam == User32.WM_SYSKEYDOWN)
KeyDown?.Invoke(this, kea); KeyDown?.Invoke(this, kea);
if (kea.Handled)
return 1;
}
else if (HookedUpKeys.Contains(key))
{
key = AddModifiers(key);
var kea = new KeyEventArgs(key);
if (wParam == User32.WM_KEYUP || wParam == User32.WM_SYSKEYUP) if (wParam == User32.WM_KEYUP || wParam == User32.WM_SYSKEYUP)
KeyUp?.Invoke(this, kea); KeyUp?.Invoke(this, kea);
if (kea.Handled) if (kea.Handled)

View File

@@ -2,6 +2,7 @@
using System.Diagnostics; using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using QuickLook.NativeMethods; using QuickLook.NativeMethods;
@@ -20,9 +21,8 @@ namespace QuickLook.Helpers
return ret[0]; return ret[0];
} }
public static bool? GetAssocApplication(string path, out string executePath, out string appFriendlyName) public static bool? GetAssocApplication(string path, out string appFriendlyName)
{ {
executePath = string.Empty;
appFriendlyName = string.Empty; appFriendlyName = string.Empty;
if (string.IsNullOrEmpty(path)) if (string.IsNullOrEmpty(path))
@@ -42,14 +42,13 @@ namespace QuickLook.Helpers
} }
var ext = Path.GetExtension(path).ToLower(); var ext = Path.GetExtension(path).ToLower();
var isExe = ext.ToLower() == ".exe"; var isExe = new[] {".cmd", ".bat", ".pif", ".scf", ".exe", ".com", ".scr"}.Contains(ext.ToLower());
// no assoc. app. found // no assoc. app. found
if (string.IsNullOrEmpty(GetAssocApplicationNative(ext, AssocStr.Command))) if (string.IsNullOrEmpty(GetAssocApplicationNative(ext, AssocStr.Command)))
if (string.IsNullOrEmpty(GetAssocApplicationNative(ext, AssocStr.AppId))) // UWP if (string.IsNullOrEmpty(GetAssocApplicationNative(ext, AssocStr.AppId))) // UWP
return null; return null;
executePath = path;
appFriendlyName = isExe appFriendlyName = isExe
? FileVersionInfo.GetVersionInfo(path).FileDescription ? FileVersionInfo.GetVersionInfo(path).FileDescription
: GetAssocApplicationNative(ext, AssocStr.FriendlyAppName); : GetAssocApplicationNative(ext, AssocStr.FriendlyAppName);

View File

@@ -75,7 +75,8 @@
</Grid> </Grid>
</DockPanel> </DockPanel>
<Grid> <Grid>
<ContentControl x:Name="container" /> <ContentControl x:Name="container"
Content="{Binding ContextObject.ViewerContent, ElementName=mainWindow}" />
</Grid> </Grid>
</DockPanel> </DockPanel>
<Grid x:Name="busyIndicatorLayer"> <Grid x:Name="busyIndicatorLayer">

View File

@@ -15,6 +15,7 @@ namespace QuickLook
public partial class MainWindowTransparent : Window public partial class MainWindowTransparent : Window
{ {
private string _path = string.Empty; private string _path = string.Empty;
private IViewer _plugin;
internal MainWindowTransparent() internal MainWindowTransparent()
{ {
@@ -33,7 +34,7 @@ namespace QuickLook
BlurWindow.EnableWindowBlur(this); BlurWindow.EnableWindowBlur(this);
}; };
buttonCloseWindow.MouseLeftButtonUp += (sender, e) => BeginHide(true); buttonCloseWindow.MouseLeftButtonUp += (sender, e) => BeginHide();
/*PreviewKeyUp += (sender, e) => /*PreviewKeyUp += (sender, e) =>
{ {
@@ -46,13 +47,16 @@ namespace QuickLook
public ContextObject ContextObject { get; private set; } public ContextObject ContextObject { get; private set; }
private void OpenWithAssocApp() internal void OpenWithAssocApp()
{ {
if (string.IsNullOrEmpty(_path)) if (string.IsNullOrEmpty(_path))
return; return;
Process.Start(new ProcessStartInfo(_path) {WorkingDirectory = Path.GetDirectoryName(_path)}); Process.Start(new ProcessStartInfo(_path)
BeginHide(true); {
WorkingDirectory = Path.GetDirectoryName(_path)
});
BeginHide();
} }
private void ResizeAndCenter(Size size) private void ResizeAndCenter(Size size)
@@ -79,22 +83,26 @@ namespace QuickLook
internal void UnloadPlugin() internal void UnloadPlugin()
{ {
container.Content = null; // clear ref to control
//container.Content = null;
// clean up plugin and refresh ContextObject for next use ContextObject.Reset();
ContextObject.ViewerPlugin?.Cleanup();
_plugin?.Cleanup();
_plugin = null;
GC.Collect();
} }
internal void BeginShow(IViewer matchedPlugin, string path) internal void BeginShow(IViewer matchedPlugin, string path)
{ {
ContextObject.CurrentContentContainer = container; _path = path;
ContextObject.ViewerPlugin = matchedPlugin; _plugin = matchedPlugin;
ContextObject.ViewerWindow = this;
// get window size before showing it // get window size before showing it
ContextObject.ViewerPlugin.Prepare(path, ContextObject); _plugin.Prepare(path, ContextObject);
SetOpenWithButtonAndPath(path); SetOpenWithButtonAndPath();
// revert UI changes // revert UI changes
ContextObject.IsBusy = true; ContextObject.IsBusy = true;
@@ -116,7 +124,7 @@ namespace QuickLook
{ {
try try
{ {
ContextObject.ViewerPlugin.View(path, ContextObject); _plugin.View(path, ContextObject);
} }
catch (Exception e) catch (Exception e)
{ {
@@ -129,40 +137,23 @@ namespace QuickLook
throw thrown; throw thrown;
} }
private void SetOpenWithButtonAndPath(string path) private void SetOpenWithButtonAndPath()
{ {
var isExe = FileHelper.GetAssocApplication(path, out string executePath, out string appFriendlyName); var isExe = FileHelper.GetAssocApplication(_path, out string appFriendlyName);
_path = executePath; buttonOpenWith.Content = isExe == null
buttonOpenWith.Visibility = isExe == null ? Visibility.Collapsed : Visibility.Visible; ? Directory.Exists(_path)
buttonOpenWith.Content = isExe == true ? $"Run {appFriendlyName}" : $"Open with {appFriendlyName}"; ? $"Browse “{Path.GetFileName(_path)}”"
: "Select ..."
: isExe == true
? $"Run “{appFriendlyName}”"
: $"Open with “{appFriendlyName}”";
} }
internal bool BeginHide(bool quitIfViewer = false, bool disposePluginOnly = false) internal void BeginHide()
{ {
if (quitIfViewer && App.RunningAsViewer)
{
Application.Current.Shutdown();
return true;
}
if (Visibility != Visibility.Visible)
return false;
UnloadPlugin(); UnloadPlugin();
ContextObject.Reset(); Hide();
GC.Collect();
// revert UI changes
ContextObject.IsBusy = true;
if (!disposePluginOnly)
{
Hide();
return true;
}
return false;
} }
} }
} }

View File

@@ -2,7 +2,6 @@
using System.ComponentModel; using System.ComponentModel;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Windows; using System.Windows;
using System.Windows.Controls;
using QuickLook.Annotations; using QuickLook.Annotations;
using QuickLook.Helpers; using QuickLook.Helpers;
@@ -18,8 +17,7 @@ namespace QuickLook.Plugin
private bool _isBusy = true; private bool _isBusy = true;
private string _title = ""; private string _title = "";
internal ContentControl CurrentContentContainer; private object _viewerContent;
internal IViewer ViewerPlugin;
/// <summary> /// <summary>
/// Get the viewer window. /// Get the viewer window.
@@ -44,8 +42,12 @@ namespace QuickLook.Plugin
/// </summary> /// </summary>
public object ViewerContent public object ViewerContent
{ {
get => CurrentContentContainer.Content; get => _viewerContent;
set => CurrentContentContainer.Content = value; set
{
_viewerContent = value;
OnPropertyChanged();
}
} }
/// <summary> /// <summary>
@@ -94,12 +96,6 @@ namespace QuickLook.Plugin
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
public void DisposePlugin()
{
ViewerPlugin?.Cleanup();
ViewerPlugin = null;
}
/// <summary> /// <summary>
/// Show a notification balloon. /// Show a notification balloon.
/// </summary> /// </summary>

View File

@@ -29,23 +29,58 @@ namespace QuickLook
internal void InvokeRoutine(Keys key) internal void InvokeRoutine(Keys key)
{ {
// do we need switch to another file? Debug.WriteLine(key);
var replaceView = key == Keys.Up || key == Keys.Down || key == Keys.Left || key == Keys.Right;
if (replaceView && _currentMainWindow.Visibility != Visibility.Visible) switch (key)
{
case Keys.Up:
case Keys.Down:
case Keys.Left:
case Keys.Right:
SwitchPreviewToAnotherFile();
break;
case Keys.Space:
TogglePreview();
break;
case Keys.Escape:
case Keys.Enter:
ClosePreview();
break;
default:
break;
}
}
private void ClosePreview()
{
if (!WindowHelper.IsFocusedControlExplorerItem() && !WindowHelper.IsFocusedWindowSelf())
return;
if (_currentMainWindow.Visibility == Visibility.Visible)
_currentMainWindow.BeginHide();
}
private void TogglePreview()
{
if (!WindowHelper.IsFocusedControlExplorerItem() && !WindowHelper.IsFocusedWindowSelf())
return;
if (_currentMainWindow.Visibility == Visibility.Visible)
_currentMainWindow.BeginHide();
else
InvokeViewer(GetCurrentSelection());
}
private void SwitchPreviewToAnotherFile()
{
if (_currentMainWindow.Visibility != Visibility.Visible)
return; return;
if (!WindowHelper.IsFocusedControlExplorerItem()) if (!WindowHelper.IsFocusedControlExplorerItem())
if (replaceView || !WindowHelper.IsFocusedWindowSelf())
return;
// should the window be closed (replaceView == false), return without showing new one
if (_currentMainWindow.BeginHide(disposePluginOnly: replaceView))
return; return;
var path = GetCurrentSelection(); _currentMainWindow.UnloadPlugin();
InvokeViewer(GetCurrentSelection());
InvokeViewer(path);
} }
internal void InvokeViewer(string path) internal void InvokeViewer(string path)