diff --git a/QuickLook.Native.Shell32/QuickLook.Native.Shell32.cpp b/QuickLook.Native.Shell32/QuickLook.Native.Shell32.cpp index f8b722b..167ee31 100644 --- a/QuickLook.Native.Shell32/QuickLook.Native.Shell32.cpp +++ b/QuickLook.Native.Shell32/QuickLook.Native.Shell32.cpp @@ -5,22 +5,12 @@ #define EXPORT extern "C" __declspec(dllexport) -EXPORT int GetFocusedWindowType() +EXPORT Shell32::FocusedWindowType GetFocusedWindowType() { return Shell32::GetFocusedWindowType(); } -EXPORT void SaveCurrentSelection() +EXPORT void GetCurrentSelection(PWCHAR buffer) { - Shell32::SaveCurrentSelection(); -} - -EXPORT int GetCurrentSelectionCount() -{ - return Shell32::GetCurrentSelectionCount(); -} - -EXPORT void GetCurrentSelectionBuffer(PWCHAR buffer) -{ - Shell32::GetCurrentSelectionBuffer(buffer); + Shell32::GetCurrentSelection(buffer); } diff --git a/QuickLook.Native.Shell32/Shell32.cpp b/QuickLook.Native.Shell32/Shell32.cpp index a11e62f..9e4409e 100644 --- a/QuickLook.Native.Shell32/Shell32.cpp +++ b/QuickLook.Native.Shell32/Shell32.cpp @@ -1,201 +1,19 @@ #include "stdafx.h" #include "Shell32.h" +#include using namespace std; -vector Shell32::vector_items; - -void Shell32::SaveCurrentSelection() -{ - vector_items.clear(); - - switch (GetFocusedWindowType()) - { - case EXPLORER: - SaveSelectedFromExplorer(); - break; - case DESKTOP: - SaveSelectedFromDesktop(); - break; - default: - break; - } -} - -UINT Shell32::GetCurrentSelectionCount() -{ - return vector_items.size(); -} - -void Shell32::GetCurrentSelectionBuffer(PWCHAR buffer) -{ - PWCHAR pos = buffer; - - for (vector::iterator it = vector_items.begin(); it < vector_items.end(); ++it) - { - int l = it->length(); - wcscpy_s(pos, l + 1, it->c_str()); - - pos += l; - - // overwrite NULL - wcscpy_s(pos++, 2, L"|"); - } - - // remove last "|" - wcscpy_s(pos - 1, 1, L""); -} - -void Shell32::SaveSelectedFromExplorer() -{ - CoInitialize(nullptr); - - CComPtr psw; - HRESULT ret = psw.CoCreateInstance(CLSID_ShellWindows); - - auto hwndFGW = GetForegroundWindow(); - - auto fFound = FALSE; - - for (int i = 0; !fFound; i++) - { - VARIANT vi; - V_VT(&vi) = VT_I4; - V_I4(&vi) = i; - - CComPtr pdisp; - // ReSharper disable once CppSomeObjectMembersMightNotBeInitialized - if (SUCCEEDED(psw->Item(vi, &pdisp))) - { - CComPtr pwba; - if (SUCCEEDED(pdisp->QueryInterface(IID_IWebBrowserApp, reinterpret_cast(&pwba)))) - { - HWND hwndWBA; - if (SUCCEEDED(pwba->get_HWND(reinterpret_cast(&hwndWBA))) && hwndWBA == hwndFGW) - { - fFound = TRUE; - - CComPtr ppdisp; - if (SUCCEEDED(pwba->get_Document(&ppdisp))) - { - CComPtr pshvd; - if (SUCCEEDED(ppdisp->QueryInterface(IID_IShellFolderViewDual2, reinterpret_cast(&pshvd)))) - { - CComPtr pfis; - if (SUCCEEDED(pshvd->SelectedItems(&pfis))) - { - LONG pCount = 0L; - pfis->get_Count(&pCount); - - for (int ii = 0; ii < pCount; ii++) - { - VARIANT vii; - V_VT(&vii) = VT_I4; - V_I4(&vii) = ii; - - CComPtr pfi; - // ReSharper disable once CppSomeObjectMembersMightNotBeInitialized - if (SUCCEEDED(pfis->Item(vii, &pfi))) - { - CComBSTR pbs = SysAllocStringLen(L"", MAX_PATH); - pfi->get_Path(&pbs); - - wstring ws = wstring(pbs); - ws.shrink_to_fit(); - - vector_items.push_back(ws); - } - } - } - } - } - } - } - } - } -} - -CComQIPtr Shell32::AttachDesktopShellWindow() -{ - CoInitialize(nullptr); - - CComPtr psw; - CComQIPtr pdispOut; - - if (SUCCEEDED(psw.CoCreateInstance(CLSID_ShellWindows))) - { - VARIANT pvarLoc = {VT_EMPTY}; - long phwnd; - psw->FindWindowSW(&pvarLoc, &pvarLoc, SWC_DESKTOP, &phwnd, SWFO_NEEDDISPATCH, reinterpret_cast(&pdispOut)); - } - return pdispOut; -} - -void Shell32::SaveSelectedFromDesktop() -{ - auto pWebBrowser2 = AttachDesktopShellWindow(); - - if (!pWebBrowser2) - return; - - CComQIPtr psp(pWebBrowser2); - - if (!psp) return; - - CComPtr psb; - if (SUCCEEDED(psp->QueryService(SID_STopLevelBrowser, IID_IShellBrowser, reinterpret_cast(&psb)))) - { - CComPtr psv; - if (SUCCEEDED(psb->QueryActiveShellView(&psv))) - { - CComPtr pfv; - if (SUCCEEDED(psv->QueryInterface(IID_IFolderView, reinterpret_cast(&pfv)))) - { - CComPtr dao; - if (SUCCEEDED(psv->GetItemObject(SVGIO_SELECTION, IID_IDataObject, reinterpret_cast(&dao)))) - vectorFromDataObject(dao); - } - } - } -} - -void Shell32::vectorFromDataObject(CComPtr dao) -{ - FORMATETC formatetc; - STGMEDIUM medium; - - formatetc.cfFormat = CF_HDROP; - formatetc.ptd = nullptr; - formatetc.dwAspect = DVASPECT_CONTENT; - formatetc.lindex = -1; - formatetc.tymed = TYMED_HGLOBAL; - - medium.tymed = TYMED_HGLOBAL; - - if (SUCCEEDED(dao->GetData(&formatetc, &medium))) - { - int n = DragQueryFile(HDROP(medium.hGlobal), 0xFFFFFFFF, nullptr, 0); - - for (int i = 0; i < n; i++) - { - WCHAR buffer[MAX_PATH]; - DragQueryFile(HDROP(medium.hGlobal), i, buffer, MAX_PATH - 1); - - wstring ws = wstring(buffer); - ws.shrink_to_fit(); - - vector_items.push_back(ws); - } - } -} - Shell32::FocusedWindowType Shell32::GetFocusedWindowType() { auto type = INVALID; auto hwndfg = GetForegroundWindow(); + if (isCursorActivated(hwndfg)) + return INVALID; + auto classBuffer = new WCHAR[MAX_PATH]; if (SUCCEEDED(GetClassName(hwndfg, classBuffer, MAX_PATH))) { @@ -215,3 +33,132 @@ Shell32::FocusedWindowType Shell32::GetFocusedWindowType() return type; } + +void Shell32::GetCurrentSelection(PWCHAR buffer) +{ + switch (GetFocusedWindowType()) + { + case EXPLORER: + getSelectedFromExplorer(buffer); + break; + case DESKTOP: + getSelectedFromDesktop(buffer); + break; + default: + break; + } +} + +void Shell32::getSelectedFromExplorer(PWCHAR buffer) +{ + CoInitialize(nullptr); + + CComPtr psw; + if (FAILED(psw.CoCreateInstance(CLSID_ShellWindows))) + return; + + auto hwndFGW = GetForegroundWindow(); + + auto count = 0L; + psw->get_Count(&count); + + for (auto i = 0; i < count; i++) + { + VARIANT vi; + V_VT(&vi) = VT_I4; + V_I4(&vi) = i; + + CComPtr pdisp; + // ReSharper disable once CppSomeObjectMembersMightNotBeInitialized + if (FAILED(psw->Item(vi, &pdisp))) + continue; + + CComQIPtr pwba; + if (FAILED(pdisp->QueryInterface(IID_IWebBrowserApp, reinterpret_cast(&pwba)))) + continue; + + HWND hwndWBA; + if (FAILED(pwba->get_HWND(reinterpret_cast(&hwndWBA)))) + continue; + + if (hwndWBA != hwndFGW || isCursorActivated(hwndWBA)) + continue; + + getSelectedInternal(pwba, buffer); + } +} + +void Shell32::getSelectedFromDesktop(PWCHAR buffer) +{ + CoInitialize(nullptr); + + CComPtr psw; + CComQIPtr pwba; + + if (FAILED(psw.CoCreateInstance(CLSID_ShellWindows))) + return; + + VARIANT pvarLoc = {VT_EMPTY}; + long phwnd; + if (FAILED(psw->FindWindowSW(&pvarLoc, &pvarLoc, SWC_DESKTOP, &phwnd, SWFO_NEEDDISPATCH, reinterpret_cast(&pwba)))) + return; + + if (isCursorActivated(reinterpret_cast(phwnd))) + return; + + getSelectedInternal(pwba, buffer); +} + +void Shell32::getSelectedInternal(CComQIPtr pwba, PWCHAR buffer) +{ + CComQIPtr psp; + if (FAILED(pwba->QueryInterface(IID_IServiceProvider, reinterpret_cast(&psp)))) + return; + + CComPtr psb; + if (FAILED(psp->QueryService(SID_STopLevelBrowser, IID_IShellBrowser, reinterpret_cast(&psb)))) + return; + + CComPtr psv; + if (FAILED(psb->QueryActiveShellView(&psv))) + return; + + CComPtr dao; + if (FAILED(psv->GetItemObject(SVGIO_SELECTION, IID_IDataObject, reinterpret_cast(&dao)))) + return; + + return obtainFirstItem(dao, buffer); +} + +void Shell32::obtainFirstItem(CComPtr dao, PWCHAR buffer) +{ + FORMATETC formatetc; + STGMEDIUM medium; + + formatetc.cfFormat = CF_HDROP; + formatetc.ptd = nullptr; + formatetc.dwAspect = DVASPECT_CONTENT; + formatetc.lindex = -1; + formatetc.tymed = TYMED_HGLOBAL; + + medium.tymed = TYMED_HGLOBAL; + + if (FAILED(dao->GetData(&formatetc, &medium))) + return; + + int n = DragQueryFile(HDROP(medium.hGlobal), 0xFFFFFFFF, nullptr, 0); + + if (n < 1) + return; + + DragQueryFile(HDROP(medium.hGlobal), 0, buffer, MAX_PATH - 1); +} + +bool Shell32::isCursorActivated(HWND hwnd) +{ + auto tId = GetWindowThreadProcessId(hwnd, nullptr); + + GUITHREADINFO gui = {sizeof gui}; + GetGUIThreadInfo(tId, &gui); + return gui.flags || gui.hwndCaret; +} diff --git a/QuickLook.Native.Shell32/Shell32.h b/QuickLook.Native.Shell32/Shell32.h index 8a9d7f0..2e8936c 100644 --- a/QuickLook.Native.Shell32/Shell32.h +++ b/QuickLook.Native.Shell32/Shell32.h @@ -13,16 +13,13 @@ public: }; static FocusedWindowType GetFocusedWindowType(); - static void SaveCurrentSelection(); - static UINT GetCurrentSelectionCount(); - static void GetCurrentSelectionBuffer(PWCHAR buffer); + static void GetCurrentSelection(PWCHAR buffer); private: - static std::vector vector_items; + static void getSelectedFromDesktop(PWCHAR buffer); + static void getSelectedFromExplorer(PWCHAR buffer); - static void SaveSelectedFromDesktop(); - static void SaveSelectedFromExplorer(); - - static CComQIPtr AttachDesktopShellWindow(); - static void vectorFromDataObject(CComPtr dao); + static void getSelectedInternal(CComQIPtr pWebBrowserApp, PWCHAR buffer); + static void obtainFirstItem(CComPtr dao, PWCHAR buffer); + static bool isCursorActivated(HWND hwndfg); }; diff --git a/QuickLook/App.xaml.cs b/QuickLook/App.xaml.cs index 7eea314..d8ace31 100644 --- a/QuickLook/App.xaml.cs +++ b/QuickLook/App.xaml.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Reflection; using System.Windows; +using QuickLook.Helpers; namespace QuickLook { diff --git a/QuickLook/BackgroundListener.cs b/QuickLook/BackgroundListener.cs index d4fda62..9f6d03e 100644 --- a/QuickLook/BackgroundListener.cs +++ b/QuickLook/BackgroundListener.cs @@ -17,6 +17,7 @@ namespace QuickLook public void Dispose() { _hook?.Dispose(); + _hook = null; } private void HotkeyEventHandler(object sender, KeyEventArgs e) diff --git a/QuickLook/FocusMonitor.cs b/QuickLook/FocusMonitor.cs index 49bfeb9..b539992 100644 --- a/QuickLook/FocusMonitor.cs +++ b/QuickLook/FocusMonitor.cs @@ -1,19 +1,18 @@ using System; using System.Threading; using System.Threading.Tasks; -using QuickLook.Helpers; namespace QuickLook { internal class FocusMonitor { - public delegate void FocusedItemChangedEventHandler(FocusedItemChangedEventArgs e); + public delegate void HeartbeatEventHandler(HeartbeatEventArgs e); private static FocusMonitor _instance; public bool IsRunning { get; private set; } - public event FocusedItemChangedEventHandler FocusedItemChanged; + public event HeartbeatEventHandler Heartbeat; public void Start() { @@ -21,21 +20,16 @@ namespace QuickLook 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; - } - } + if (NativeMethods.QuickLook.GetFocusedWindowType() == + NativeMethods.QuickLook.FocusedWindowType.Invalid) + continue; + + var file = NativeMethods.QuickLook.GetCurrentSelection(); + Heartbeat?.Invoke(new HeartbeatEventArgs(DateTime.Now.Ticks, file)); } }).Start(); } @@ -51,13 +45,15 @@ namespace QuickLook } } - internal class FocusedItemChangedEventArgs : EventArgs + internal class HeartbeatEventArgs : EventArgs { - public FocusedItemChangedEventArgs(string files) + public HeartbeatEventArgs(long tick, string files) { + InvokeTick = tick; FocusedFile = files; } + public long InvokeTick { get; } public string FocusedFile { get; } } } \ No newline at end of file diff --git a/QuickLook/PidHelper.cs b/QuickLook/Helpers/PidHelper.cs similarity index 98% rename from QuickLook/PidHelper.cs rename to QuickLook/Helpers/PidHelper.cs index 28b7721..b646dba 100644 --- a/QuickLook/PidHelper.cs +++ b/QuickLook/Helpers/PidHelper.cs @@ -1,7 +1,7 @@ using System.Diagnostics; using System.IO; -namespace QuickLook +namespace QuickLook.Helpers { internal static class PidHelper { diff --git a/QuickLook/Helpers/WindowHelper.cs b/QuickLook/Helpers/WindowHelper.cs index 1576ec5..96209eb 100644 --- a/QuickLook/Helpers/WindowHelper.cs +++ b/QuickLook/Helpers/WindowHelper.cs @@ -1,6 +1,5 @@ using System; using System.Diagnostics; -using System.Text; using System.Windows; using System.Windows.Forms; using System.Windows.Interop; @@ -61,65 +60,21 @@ namespace QuickLook.Helpers pixelY = (int) (matrix.M22 * unitY); } + internal static bool IsForegroundWindowBelongToSelf() + { + var hwnd = User32.GetForegroundWindow(); + if (hwnd == IntPtr.Zero) + return false; + + User32.GetWindowThreadProcessId(hwnd, out uint procId); + return procId == Process.GetCurrentProcess().Id; + } + 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 IsFocusedWindowSelf() - { - var procId = Process.GetCurrentProcess().Id; - uint activeProcId; - User32.GetWindowThreadProcessId(GetFocusedWindow(), out activeProcId); - - return activeProcId == procId; - } - - internal static bool IsFocusedControlExplorerItem() - { - if (NativeMethods.QuickLook.GetFocusedWindowType() == 0) - return false; - - var focusedWindowClass = GetWindowClassName(GetFocusedWindow()); - var focusedWindowParentClass = - GetWindowClassName(GetParentWindow(GetFocusedWindow())); - - if (focusedWindowClass != "SysListView32" && focusedWindowClass != "DirectUIHWND") - return false; - - if (focusedWindowParentClass != "SHELLDLL_DefView") - return false; - - return true; - } } } \ No newline at end of file diff --git a/QuickLook/MainWindowTransparent.xaml b/QuickLook/MainWindowTransparent.xaml index edbdd30..ad23a5d 100644 --- a/QuickLook/MainWindowTransparent.xaml +++ b/QuickLook/MainWindowTransparent.xaml @@ -62,11 +62,17 @@ WindowChrome.IsHitTestVisibleInChrome="True" Height="15" Margin="10,0" Foreground="Gray" Cursor="Hand" /> - ViewWindowManager.GetInstance() - .InvokeRoutine(new KeyEventArgs(Keys.Escape)); + buttonCloseWindow.MouseLeftButtonUp += (sender, e) => + ViewWindowManager.GetInstance().ClosePreview(); - buttonOpenWith.Click += (sender, e) => ViewWindowManager.GetInstance() - .InvokeRoutine(new KeyEventArgs(Keys.Enter)); + buttonOpenWith.Click += (sender, e) => + ViewWindowManager.GetInstance().RunAndClosePreview(); } public ContextObject ContextObject { get; private set; } - internal void RunAndClose() + internal void RunAndHide() { if (string.IsNullOrEmpty(_path)) return; @@ -83,6 +81,12 @@ namespace QuickLook internal void UnloadPlugin() { + // the focused element will not processed by GC: https://stackoverflow.com/questions/30848939/memory-leak-due-to-window-efectivevalues-retention + FocusManager.SetFocusedElement(this, null); + Keyboard.DefaultRestoreFocusMode = + RestoreFocusMode.None; // WPF will put the focused item into a "_restoreFocus" list ... omg + Keyboard.ClearFocus(); + ContextObject.Reset(); _plugin?.Cleanup(); @@ -151,10 +155,6 @@ namespace QuickLook internal void BeginHide() { - // the focused element will not processed by GC: https://stackoverflow.com/questions/30848939/memory-leak-due-to-window-efectivevalues-retention - FocusManager.SetFocusedElement(this, null); - Keyboard.ClearFocus(); - UnloadPlugin(); Hide(); diff --git a/QuickLook/NativeMethods/QuickLook.cs b/QuickLook/NativeMethods/QuickLook.cs index 65cd5b8..3038a44 100644 --- a/QuickLook/NativeMethods/QuickLook.cs +++ b/QuickLook/NativeMethods/QuickLook.cs @@ -1,5 +1,4 @@ -using System.Linq; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; @@ -8,40 +7,30 @@ namespace QuickLook.NativeMethods internal static class QuickLook { [DllImport("QuickLook.Native.Shell32.dll", CallingConvention = CallingConvention.Cdecl)] - internal static extern int GetFocusedWindowType(); + internal static extern FocusedWindowType GetFocusedWindowType(); - [DllImport("QuickLook.Native.Shell32.dll", CallingConvention = CallingConvention.Cdecl)] - internal static extern void SaveCurrentSelection(); + [DllImport("QuickLook.Native.Shell32.dll", EntryPoint = "GetCurrentSelection", + CallingConvention = CallingConvention.Cdecl)] + internal static extern void GetCurrentSelectionNative([MarshalAs(UnmanagedType.LPWStr)] StringBuilder sb); - [DllImport("QuickLook.Native.Shell32.dll", CallingConvention = CallingConvention.Cdecl)] - internal static extern int GetCurrentSelectionCount(); - - [DllImport("QuickLook.Native.Shell32.dll", CallingConvention = CallingConvention.Cdecl)] - internal static extern void GetCurrentSelectionBuffer([MarshalAs(UnmanagedType.LPWStr)] StringBuilder buffer); - - internal static string[] GetCurrentSelection() + 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); - } + sb = new StringBuilder(255 + 1); + GetCurrentSelectionNative(sb); }).Wait(); - return sb == null || sb.Length == 0 ? new string[0] : sb.ToString().Split('|'); + + return sb?.ToString() ?? string.Empty; } - internal static string GetCurrentSelectionFirst() + internal enum FocusedWindowType { - var files = GetCurrentSelection(); - - return files.Any() ? files.First() : string.Empty; + Invalid, + Desktop, + Explorer } } } \ No newline at end of file diff --git a/QuickLook/Plugin/InfoPanel/InfoPanel.xaml b/QuickLook/Plugin/InfoPanel/InfoPanel.xaml index 136766e..8a21ac4 100644 --- a/QuickLook/Plugin/InfoPanel/InfoPanel.xaml +++ b/QuickLook/Plugin/InfoPanel/InfoPanel.xaml @@ -31,8 +31,9 @@ - + + @@ -42,7 +43,11 @@ - Filename.ext + + FilenameFilenameFilenameFilenameFilenameFilenameFilenameFilenameFilenameFilename.ext + Last modified at 01/01/2017 00:00:00 Calculating size... diff --git a/QuickLook/QuickLook.csproj b/QuickLook/QuickLook.csproj index a17f49e..a8841cd 100644 --- a/QuickLook/QuickLook.csproj +++ b/QuickLook/QuickLook.csproj @@ -116,7 +116,7 @@ - + diff --git a/QuickLook/TrayIconManager.cs b/QuickLook/TrayIconManager.cs index b0efde3..fc0c2f9 100644 --- a/QuickLook/TrayIconManager.cs +++ b/QuickLook/TrayIconManager.cs @@ -3,7 +3,6 @@ using System.Diagnostics; using System.Windows.Forms; using QuickLook.Helpers; using QuickLook.Properties; -using Application = System.Windows.Application; namespace QuickLook { @@ -26,14 +25,17 @@ namespace QuickLook { _icon = new NotifyIcon { + Text = $"QuickLook v{Application.ProductVersion}", Icon = Resources.app, Visible = true, ContextMenu = new ContextMenu(new[] { - new MenuItem($"Check for &Updates ({System.Windows.Forms.Application.ProductVersion})", + new MenuItem($"v{Application.ProductVersion}") {Enabled = false}, + new MenuItem("-"), + new MenuItem("Check for &Updates...", (sender, e) => Process.Start(@"http://pooi.moe/QuickLook/")), _itemAutorun, - new MenuItem("&Quit", (sender, e) => Application.Current.Shutdown()) + new MenuItem("&Quit", (sender, e) => System.Windows.Application.Current.Shutdown()) }) }; diff --git a/QuickLook/ViewWindowManager.cs b/QuickLook/ViewWindowManager.cs index 2b33f65..4ad2f6d 100644 --- a/QuickLook/ViewWindowManager.cs +++ b/QuickLook/ViewWindowManager.cs @@ -9,13 +9,14 @@ using QuickLook.Plugin; namespace QuickLook { - internal class ViewWindowManager + internal class ViewWindowManager : IDisposable { private static ViewWindowManager _instance; private readonly MainWindowNoTransparent _viewWindowNoTransparent; private readonly MainWindowTransparent _viewWindowTransparentTransparent; private MainWindowTransparent _currentMainWindow; + private long _lastSwitchTick; private string _path = string.Empty; @@ -27,10 +28,13 @@ namespace QuickLook _currentMainWindow = _viewWindowTransparentTransparent; } + public void Dispose() + { + StopFocusMonitor(); + } + internal void InvokeRoutine(KeyEventArgs kea) { - Debug.WriteLine(kea.KeyCode); - switch (kea.KeyCode) { case Keys.Up: @@ -53,22 +57,29 @@ namespace QuickLook } } - private void RunAndClosePreview(KeyEventArgs kea = null) + internal void RunAndClosePreview(KeyEventArgs kea = null) { - if (!WindowHelper.IsFocusedControlExplorerItem() && !WindowHelper.IsFocusedWindowSelf()) - return; + if (NativeMethods.QuickLook.GetFocusedWindowType() == + NativeMethods.QuickLook.FocusedWindowType.Invalid) + if (!WindowHelper.IsForegroundWindowBelongToSelf()) + return; if (_currentMainWindow.Visibility != Visibility.Visible) return; StopFocusMonitor(); - _currentMainWindow.RunAndClose(); + _currentMainWindow.RunAndHide(); if (kea != null) kea.Handled = true; } internal void ClosePreview(KeyEventArgs kea = null) { + if (NativeMethods.QuickLook.GetFocusedWindowType() == + NativeMethods.QuickLook.FocusedWindowType.Invalid) + if (!WindowHelper.IsForegroundWindowBelongToSelf()) + return; + StopFocusMonitor(); _currentMainWindow.BeginHide(); @@ -78,8 +89,12 @@ namespace QuickLook private void TogglePreview(KeyEventArgs kea = null) { - if (!WindowHelper.IsFocusedControlExplorerItem() && !WindowHelper.IsFocusedWindowSelf()) - return; + _lastSwitchTick = DateTime.Now.Ticks; + + if (NativeMethods.QuickLook.GetFocusedWindowType() == + NativeMethods.QuickLook.FocusedWindowType.Invalid) + if (!WindowHelper.IsForegroundWindowBelongToSelf()) + return; if (_currentMainWindow.Visibility == Visibility.Visible) { @@ -87,7 +102,7 @@ namespace QuickLook } else { - _path = NativeMethods.QuickLook.GetCurrentSelectionFirst(); + _path = NativeMethods.QuickLook.GetCurrentSelection(); InvokeViewer(); } if (kea != null) @@ -99,38 +114,34 @@ namespace QuickLook if (_currentMainWindow.Visibility != Visibility.Visible) return; - if (!WindowHelper.IsFocusedControlExplorerItem()) + _lastSwitchTick = DateTime.Now.Ticks; + + if (NativeMethods.QuickLook.GetFocusedWindowType() == + NativeMethods.QuickLook.FocusedWindowType.Invalid) return; - _path = NativeMethods.QuickLook.GetCurrentSelectionFirst(); + _path = NativeMethods.QuickLook.GetCurrentSelection(); InvokeViewer(); if (kea != null) kea.Handled = false; } - private void SwitchPreviewRemoteInvoke(FocusedItemChangedEventArgs e) + private void SwitchPreviewRemoteInvoke(HeartbeatEventArgs e) { - Debug.WriteLine("SwitchPreviewRemoteInvoke"); + // sleep for 1.5s + if (e.InvokeTick - _lastSwitchTick < 1.5 * TimeSpan.TicksPerSecond) + return; if (e.FocusedFile == _path) return; + Debug.WriteLine("SwitchPreviewRemoteInvoke:" + (e.InvokeTick - _lastSwitchTick)); + if (string.IsNullOrEmpty(e.FocusedFile)) return; - _currentMainWindow?.Dispatcher.Invoke(() => - { - if (_currentMainWindow.Visibility != Visibility.Visible) - return; - - if (!WindowHelper.IsFocusedControlExplorerItem()) - return; - - _path = NativeMethods.QuickLook.GetCurrentSelectionFirst(); - - InvokeViewer(); - }); + _currentMainWindow?.Dispatcher.Invoke(() => SwitchPreview()); } private void RunFocusMonitor() @@ -138,7 +149,7 @@ namespace QuickLook if (!FocusMonitor.GetInstance().IsRunning) { FocusMonitor.GetInstance().Start(); - FocusMonitor.GetInstance().FocusedItemChanged += SwitchPreviewRemoteInvoke; + FocusMonitor.GetInstance().Heartbeat += SwitchPreviewRemoteInvoke; } } @@ -147,7 +158,7 @@ namespace QuickLook if (FocusMonitor.GetInstance().IsRunning) { FocusMonitor.GetInstance().Stop(); - FocusMonitor.GetInstance().FocusedItemChanged -= SwitchPreviewRemoteInvoke; + FocusMonitor.GetInstance().Heartbeat -= SwitchPreviewRemoteInvoke; } }