do not show preview window on every SPACE key; code refactoring

This commit is contained in:
Paddy Xu
2017-04-26 23:15:06 +03:00
parent fa764b2e69
commit fc5b2742d1
13 changed files with 217 additions and 96 deletions

View File

@@ -5,6 +5,11 @@
#define EXPORT extern "C" __declspec(dllexport) #define EXPORT extern "C" __declspec(dllexport)
EXPORT int GetFocusedWindowType()
{
return Shell32::GetFocusedWindowType();
}
EXPORT void SaveCurrentSelection() EXPORT void SaveCurrentSelection()
{ {
Shell32::SaveCurrentSelection(); Shell32::SaveCurrentSelection();

View File

@@ -5,24 +5,23 @@
class Shell32 class Shell32
{ {
public: public:
enum FocusedWindowType
{
INVALID = 0,
DESKTOP = 1,
EXPLORER = 2,
};
static FocusedWindowType GetFocusedWindowType();
static void SaveCurrentSelection(); static void SaveCurrentSelection();
static UINT GetCurrentSelectionCount(); static UINT GetCurrentSelectionCount();
static void GetCurrentSelectionBuffer(PWCHAR buffer); static void GetCurrentSelectionBuffer(PWCHAR buffer);
private: private:
enum FocusedWindowType
{
INVALID,
DESKTOP,
EXPLORER,
};
static std::vector<std::wstring> vector_items; static std::vector<std::wstring> vector_items;
static void SaveSelectedFromDesktop(); static void SaveSelectedFromDesktop();
static void SaveSelectedFromExplorer(); static void SaveSelectedFromExplorer();
static FocusedWindowType GetFocusedWindowType();
static CComQIPtr<IWebBrowser2> AttachDesktopShellWindow(); static CComQIPtr<IWebBrowser2> AttachDesktopShellWindow();
static void vectorFromDataObject(CComPtr<IDataObject> dao); static void vectorFromDataObject(CComPtr<IDataObject> dao);
}; };

View File

@@ -7,7 +7,7 @@ using System.Runtime.InteropServices;
namespace QuickLook.Plugin.LastResort namespace QuickLook.Plugin.LastResort
{ {
public class IconHelper public static class IconHelper
{ {
public enum IconSizeEnum public enum IconSizeEnum
{ {

View File

@@ -1,8 +1,4 @@
using System; using System.Windows.Forms;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using QuickLook.Utilities; using QuickLook.Utilities;
namespace QuickLook namespace QuickLook
@@ -13,8 +9,6 @@ namespace QuickLook
private GlobalKeyboardHook _hook; private GlobalKeyboardHook _hook;
private MainWindow _showingWindow;
protected BackgroundListener() protected BackgroundListener()
{ {
InstallHook(HotkeyEventHandler); InstallHook(HotkeyEventHandler);
@@ -22,49 +16,7 @@ namespace QuickLook
private void HotkeyEventHandler(object sender, KeyEventArgs e) private void HotkeyEventHandler(object sender, KeyEventArgs e)
{ {
if (_showingWindow != null) ViewWindowManager.GetInstance().InvokeRoutine();
{
_showingWindow.Close();
_showingWindow = null;
GC.Collect();
return;
}
var path = string.Empty;
// communicate with COM in a separate thread
Task.Run(() =>
{
var paths = GetCurrentSelection();
if (paths.Any())
path = paths.First();
})
.Wait();
if (string.IsNullOrEmpty(path))
return;
var matched = PluginManager.FindMatch(path);
if (matched == null)
return;
_showingWindow = new MainWindow();
_showingWindow.Closed += (sender2, e2) => { _showingWindow = null; };
_showingWindow.viewContentContainer.ViewerPlugin = matched;
// get window size before showing it
matched.Prepare(path, _showingWindow.viewContentContainer);
_showingWindow.Show();
matched.View(path, _showingWindow.viewContentContainer);
_showingWindow.ShowFinishLoadingAnimation();
} }
private void InstallHook(KeyEventHandler handler) private void InstallHook(KeyEventHandler handler)
@@ -76,19 +28,6 @@ namespace QuickLook
_hook.KeyUp += handler; _hook.KeyUp += handler;
} }
private string[] GetCurrentSelection()
{
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 BackgroundListener GetInstance() internal static BackgroundListener GetInstance()
{ {
return _instance ?? (_instance = new BackgroundListener()); return _instance ?? (_instance = new BackgroundListener());

View File

@@ -8,6 +8,7 @@ using System.Windows.Media.Animation;
using System.Windows.Threading; using System.Windows.Threading;
using QuickLook.Annotations; using QuickLook.Annotations;
using QuickLook.ExtensionMethods; using QuickLook.ExtensionMethods;
using QuickLook.Plugin;
using QuickLook.Utilities; using QuickLook.Utilities;
namespace QuickLook namespace QuickLook
@@ -53,10 +54,24 @@ namespace QuickLook
base.Show(); base.Show();
NoactivateWindowHelper.SetNoactivate(new WindowInteropHelper(this)); WindowHelper.SetNoactivate(new WindowInteropHelper(this));
} }
internal void ShowFinishLoadingAnimation() internal void BeginShow(IViewer matchedPlugin, string path)
{
viewContentContainer.ViewerPlugin = matchedPlugin;
// get window size before showing it
matchedPlugin.Prepare(path, viewContentContainer);
Show();
matchedPlugin.View(path, viewContentContainer);
ShowFinishLoadingAnimation();
}
private void ShowFinishLoadingAnimation()
{ {
var speed = 100; var speed = 100;

View File

@@ -3,9 +3,12 @@ using System.Runtime.InteropServices;
namespace QuickLook.NativeMethods namespace QuickLook.NativeMethods
{ {
internal class Kernel32 internal static class Kernel32
{ {
[DllImport("kernel32.dll")] [DllImport("kernel32.dll")]
internal static extern IntPtr LoadLibrary(string lpFileName); internal static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll")]
internal static extern IntPtr GetCurrentThreadId();
} }
} }

View File

@@ -3,8 +3,11 @@ using System.Text;
namespace QuickLook.NativeMethods namespace QuickLook.NativeMethods
{ {
internal class QuickLook internal static class QuickLook
{ {
[DllImport("QuickLook.Native.Shell32.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern int GetFocusedWindowType();
[DllImport("QuickLook.Native.Shell32.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("QuickLook.Native.Shell32.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern void SaveCurrentSelection(); internal static extern void SaveCurrentSelection();

View File

@@ -1,10 +1,11 @@
using System; using System;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text;
namespace QuickLook.NativeMethods namespace QuickLook.NativeMethods
{ {
internal class User32 internal static class User32
{ {
[DllImport("user32.dll")] [DllImport("user32.dll")]
internal static extern IntPtr SetWindowsHookEx(int idHook, KeyboardHookProc callback, IntPtr hInstance, internal static extern IntPtr SetWindowsHookEx(int idHook, KeyboardHookProc callback, IntPtr hInstance,
@@ -17,10 +18,28 @@ namespace QuickLook.NativeMethods
internal static extern int CallNextHookEx(IntPtr idHook, int nCode, int wParam, ref KeyboardHookStruct lParam); internal static extern int CallNextHookEx(IntPtr idHook, int nCode, int wParam, ref KeyboardHookStruct lParam);
[DllImport("user32.dll")] [DllImport("user32.dll")]
public static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); internal static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll")] [DllImport("user32.dll")]
public static extern int GetWindowLong(IntPtr hWnd, int nIndex); internal static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
internal static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
internal static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
[DllImport("user32.dll")]
internal static extern IntPtr AttachThreadInput(IntPtr idAttach, IntPtr idAttachTo, bool fAttach);
[DllImport("user32.dll")]
internal static extern IntPtr GetFocus();
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll")]
internal static extern IntPtr GetParent(IntPtr hWnd);
internal delegate int KeyboardHookProc(int code, int wParam, ref KeyboardHookStruct lParam); internal delegate int KeyboardHookProc(int code, int wParam, ref KeyboardHookStruct lParam);

View File

@@ -79,7 +79,8 @@
<Compile Include="Plugin\ViewContentContainer.xaml.cs"> <Compile Include="Plugin\ViewContentContainer.xaml.cs">
<DependentUpon>ViewContentContainer.xaml</DependentUpon> <DependentUpon>ViewContentContainer.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Utilities\NoactivateWindowHelper.cs" /> <Compile Include="Utilities\WindowHelper.cs" />
<Compile Include="ViewWindowManager.cs" />
<Page Include="Styles\ScrollBarStyleDictionary.xaml"> <Page Include="Styles\ScrollBarStyleDictionary.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>

View File

@@ -5,7 +5,7 @@ using System.Windows.Interop;
namespace QuickLook.Utilities namespace QuickLook.Utilities
{ {
internal class AeroGlass internal static class AeroGlass
{ {
internal static void EnableBlur(Window window) internal static void EnableBlur(Window window)
{ {

View File

@@ -1,15 +0,0 @@
using System.Windows.Interop;
using QuickLook.NativeMethods;
namespace QuickLook.Utilities
{
internal class NoactivateWindowHelper
{
internal static void SetNoactivate(WindowInteropHelper window)
{
User32.SetWindowLong(window.Handle, User32.GWL_EXSTYLE,
User32.GetWindowLong(window.Handle, User32.GWL_EXSTYLE) |
User32.WS_EX_NOACTIVATE);
}
}
}

View File

@@ -0,0 +1,62 @@
using System;
using System.Text;
using System.Windows.Interop;
using QuickLook.NativeMethods;
namespace QuickLook.Utilities
{
internal static class WindowHelper
{
internal static void SetNoactivate(WindowInteropHelper window)
{
User32.SetWindowLong(window.Handle, User32.GWL_EXSTYLE,
User32.GetWindowLong(window.Handle, User32.GWL_EXSTYLE) |
User32.WS_EX_NOACTIVATE);
}
internal static string GetWindowClassName(IntPtr window)
{
var pClassName = new StringBuilder(256);
User32.GetClassName(window, pClassName, pClassName.Capacity);
return pClassName.ToString();
}
internal static IntPtr GetParentWindow(IntPtr child)
{
return User32.GetParent(child);
}
internal static IntPtr GetFocusedWindow()
{
var activeWindowHandle = User32.GetForegroundWindow();
var activeWindowThread = User32.GetWindowThreadProcessId(activeWindowHandle, IntPtr.Zero);
var currentThread = Kernel32.GetCurrentThreadId();
User32.AttachThreadInput(activeWindowThread, currentThread, true);
var focusedControlHandle = User32.GetFocus();
User32.AttachThreadInput(activeWindowThread, currentThread, false);
return focusedControlHandle;
}
internal static bool IsFocusedControlExplorerItem()
{
if (NativeMethods.QuickLook.GetFocusedWindowType() == 0)
return false;
var focusedWindowClass = GetWindowClassName(GetFocusedWindow());
var focusedWindowParentClass =
GetWindowClassName(GetParentWindow(GetFocusedWindow()));
if (focusedWindowParentClass != "SHELLDLL_DefView")
return false;
if (focusedWindowClass != "SysListView32" && focusedWindowClass != "DirectUIHWND")
return false;
return true;
}
}
}

View File

@@ -0,0 +1,90 @@
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using QuickLook.Plugin;
using QuickLook.Utilities;
namespace QuickLook
{
internal class ViewWindowManager
{
private static ViewWindowManager _instance;
private MainWindow _viewWindow;
internal void InvokeRoutine()
{
if (CloseCurrentWindow())
return;
if (!WindowHelper.IsFocusedControlExplorerItem())
return;
var path = GetCurrentSelection();
if (string.IsNullOrEmpty(path))
return;
var matchedPlugin = PluginManager.FindMatch(path);
if (matchedPlugin == null)
return;
BeginShowNewWindow(matchedPlugin, path);
}
private void BeginShowNewWindow(IViewer matchedPlugin, string path)
{
_viewWindow = new MainWindow();
_viewWindow.Closed += (sender2, e2) => { _viewWindow = null; };
_viewWindow.BeginShow(matchedPlugin, path);
}
private bool CloseCurrentWindow()
{
if (_viewWindow != null)
{
_viewWindow.Close();
_viewWindow = null;
GC.Collect();
return true;
}
return false;
}
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());
}
}
}