mirror of
https://github.com/QL-Win/QuickLook.git
synced 2025-09-13 19:19:10 +00:00
Mooore aggressive GC; rewrite native dll
This commit is contained in:
@@ -5,22 +5,12 @@
|
|||||||
|
|
||||||
#define EXPORT extern "C" __declspec(dllexport)
|
#define EXPORT extern "C" __declspec(dllexport)
|
||||||
|
|
||||||
EXPORT int GetFocusedWindowType()
|
EXPORT Shell32::FocusedWindowType GetFocusedWindowType()
|
||||||
{
|
{
|
||||||
return Shell32::GetFocusedWindowType();
|
return Shell32::GetFocusedWindowType();
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT void SaveCurrentSelection()
|
EXPORT void GetCurrentSelection(PWCHAR buffer)
|
||||||
{
|
{
|
||||||
Shell32::SaveCurrentSelection();
|
Shell32::GetCurrentSelection(buffer);
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT int GetCurrentSelectionCount()
|
|
||||||
{
|
|
||||||
return Shell32::GetCurrentSelectionCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT void GetCurrentSelectionBuffer(PWCHAR buffer)
|
|
||||||
{
|
|
||||||
Shell32::GetCurrentSelectionBuffer(buffer);
|
|
||||||
}
|
}
|
||||||
|
@@ -1,201 +1,19 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
|
||||||
#include "Shell32.h"
|
#include "Shell32.h"
|
||||||
|
#include <atlcomcli.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
vector<wstring> 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<wstring>::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<IShellWindows> 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<IDispatch> pdisp;
|
|
||||||
// ReSharper disable once CppSomeObjectMembersMightNotBeInitialized
|
|
||||||
if (SUCCEEDED(psw->Item(vi, &pdisp)))
|
|
||||||
{
|
|
||||||
CComPtr<IWebBrowserApp> pwba;
|
|
||||||
if (SUCCEEDED(pdisp->QueryInterface(IID_IWebBrowserApp, reinterpret_cast<void**>(&pwba))))
|
|
||||||
{
|
|
||||||
HWND hwndWBA;
|
|
||||||
if (SUCCEEDED(pwba->get_HWND(reinterpret_cast<LONG_PTR*>(&hwndWBA))) && hwndWBA == hwndFGW)
|
|
||||||
{
|
|
||||||
fFound = TRUE;
|
|
||||||
|
|
||||||
CComPtr<IDispatch> ppdisp;
|
|
||||||
if (SUCCEEDED(pwba->get_Document(&ppdisp)))
|
|
||||||
{
|
|
||||||
CComPtr<IShellFolderViewDual2> pshvd;
|
|
||||||
if (SUCCEEDED(ppdisp->QueryInterface(IID_IShellFolderViewDual2, reinterpret_cast<void**>(&pshvd))))
|
|
||||||
{
|
|
||||||
CComPtr<FolderItems> 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<FolderItem> 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<IWebBrowser2> Shell32::AttachDesktopShellWindow()
|
|
||||||
{
|
|
||||||
CoInitialize(nullptr);
|
|
||||||
|
|
||||||
CComPtr<IShellWindows> psw;
|
|
||||||
CComQIPtr<IWebBrowser2> pdispOut;
|
|
||||||
|
|
||||||
if (SUCCEEDED(psw.CoCreateInstance(CLSID_ShellWindows)))
|
|
||||||
{
|
|
||||||
VARIANT pvarLoc = {VT_EMPTY};
|
|
||||||
long phwnd;
|
|
||||||
psw->FindWindowSW(&pvarLoc, &pvarLoc, SWC_DESKTOP, &phwnd, SWFO_NEEDDISPATCH, reinterpret_cast<IDispatch**>(&pdispOut));
|
|
||||||
}
|
|
||||||
return pdispOut;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Shell32::SaveSelectedFromDesktop()
|
|
||||||
{
|
|
||||||
auto pWebBrowser2 = AttachDesktopShellWindow();
|
|
||||||
|
|
||||||
if (!pWebBrowser2)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CComQIPtr<IServiceProvider> psp(pWebBrowser2);
|
|
||||||
|
|
||||||
if (!psp) return;
|
|
||||||
|
|
||||||
CComPtr<IShellBrowser> psb;
|
|
||||||
if (SUCCEEDED(psp->QueryService(SID_STopLevelBrowser, IID_IShellBrowser, reinterpret_cast<LPVOID*>(&psb))))
|
|
||||||
{
|
|
||||||
CComPtr<IShellView> psv;
|
|
||||||
if (SUCCEEDED(psb->QueryActiveShellView(&psv)))
|
|
||||||
{
|
|
||||||
CComPtr<IFolderView> pfv;
|
|
||||||
if (SUCCEEDED(psv->QueryInterface(IID_IFolderView, reinterpret_cast<void**>(&pfv))))
|
|
||||||
{
|
|
||||||
CComPtr<IDataObject> dao;
|
|
||||||
if (SUCCEEDED(psv->GetItemObject(SVGIO_SELECTION, IID_IDataObject, reinterpret_cast<void**>(&dao))))
|
|
||||||
vectorFromDataObject(dao);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Shell32::vectorFromDataObject(CComPtr<IDataObject> 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()
|
Shell32::FocusedWindowType Shell32::GetFocusedWindowType()
|
||||||
{
|
{
|
||||||
auto type = INVALID;
|
auto type = INVALID;
|
||||||
|
|
||||||
auto hwndfg = GetForegroundWindow();
|
auto hwndfg = GetForegroundWindow();
|
||||||
|
|
||||||
|
if (isCursorActivated(hwndfg))
|
||||||
|
return INVALID;
|
||||||
|
|
||||||
auto classBuffer = new WCHAR[MAX_PATH];
|
auto classBuffer = new WCHAR[MAX_PATH];
|
||||||
if (SUCCEEDED(GetClassName(hwndfg, classBuffer, MAX_PATH)))
|
if (SUCCEEDED(GetClassName(hwndfg, classBuffer, MAX_PATH)))
|
||||||
{
|
{
|
||||||
@@ -215,3 +33,132 @@ Shell32::FocusedWindowType Shell32::GetFocusedWindowType()
|
|||||||
|
|
||||||
return type;
|
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<IShellWindows> 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<IDispatch> pdisp;
|
||||||
|
// ReSharper disable once CppSomeObjectMembersMightNotBeInitialized
|
||||||
|
if (FAILED(psw->Item(vi, &pdisp)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
CComQIPtr<IWebBrowserApp> pwba;
|
||||||
|
if (FAILED(pdisp->QueryInterface(IID_IWebBrowserApp, reinterpret_cast<void**>(&pwba))))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
HWND hwndWBA;
|
||||||
|
if (FAILED(pwba->get_HWND(reinterpret_cast<LONG_PTR*>(&hwndWBA))))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (hwndWBA != hwndFGW || isCursorActivated(hwndWBA))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
getSelectedInternal(pwba, buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shell32::getSelectedFromDesktop(PWCHAR buffer)
|
||||||
|
{
|
||||||
|
CoInitialize(nullptr);
|
||||||
|
|
||||||
|
CComPtr<IShellWindows> psw;
|
||||||
|
CComQIPtr<IWebBrowserApp> 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<IDispatch**>(&pwba))))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (isCursorActivated(reinterpret_cast<HWND>(phwnd)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
getSelectedInternal(pwba, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shell32::getSelectedInternal(CComQIPtr<IWebBrowserApp> pwba, PWCHAR buffer)
|
||||||
|
{
|
||||||
|
CComQIPtr<IServiceProvider> psp;
|
||||||
|
if (FAILED(pwba->QueryInterface(IID_IServiceProvider, reinterpret_cast<void**>(&psp))))
|
||||||
|
return;
|
||||||
|
|
||||||
|
CComPtr<IShellBrowser> psb;
|
||||||
|
if (FAILED(psp->QueryService(SID_STopLevelBrowser, IID_IShellBrowser, reinterpret_cast<LPVOID*>(&psb))))
|
||||||
|
return;
|
||||||
|
|
||||||
|
CComPtr<IShellView> psv;
|
||||||
|
if (FAILED(psb->QueryActiveShellView(&psv)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
CComPtr<IDataObject> dao;
|
||||||
|
if (FAILED(psv->GetItemObject(SVGIO_SELECTION, IID_IDataObject, reinterpret_cast<void**>(&dao))))
|
||||||
|
return;
|
||||||
|
|
||||||
|
return obtainFirstItem(dao, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shell32::obtainFirstItem(CComPtr<IDataObject> 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;
|
||||||
|
}
|
||||||
|
@@ -13,16 +13,13 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
static FocusedWindowType GetFocusedWindowType();
|
static FocusedWindowType GetFocusedWindowType();
|
||||||
static void SaveCurrentSelection();
|
static void GetCurrentSelection(PWCHAR buffer);
|
||||||
static UINT GetCurrentSelectionCount();
|
|
||||||
static void GetCurrentSelectionBuffer(PWCHAR buffer);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::vector<std::wstring> vector_items;
|
static void getSelectedFromDesktop(PWCHAR buffer);
|
||||||
|
static void getSelectedFromExplorer(PWCHAR buffer);
|
||||||
|
|
||||||
static void SaveSelectedFromDesktop();
|
static void getSelectedInternal(CComQIPtr<IWebBrowserApp> pWebBrowserApp, PWCHAR buffer);
|
||||||
static void SaveSelectedFromExplorer();
|
static void obtainFirstItem(CComPtr<IDataObject> dao, PWCHAR buffer);
|
||||||
|
static bool isCursorActivated(HWND hwndfg);
|
||||||
static CComQIPtr<IWebBrowser2> AttachDesktopShellWindow();
|
|
||||||
static void vectorFromDataObject(CComPtr<IDataObject> dao);
|
|
||||||
};
|
};
|
||||||
|
@@ -4,6 +4,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using QuickLook.Helpers;
|
||||||
|
|
||||||
namespace QuickLook
|
namespace QuickLook
|
||||||
{
|
{
|
||||||
|
@@ -17,6 +17,7 @@ namespace QuickLook
|
|||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_hook?.Dispose();
|
_hook?.Dispose();
|
||||||
|
_hook = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HotkeyEventHandler(object sender, KeyEventArgs e)
|
private void HotkeyEventHandler(object sender, KeyEventArgs e)
|
||||||
|
@@ -1,19 +1,18 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using QuickLook.Helpers;
|
|
||||||
|
|
||||||
namespace QuickLook
|
namespace QuickLook
|
||||||
{
|
{
|
||||||
internal class FocusMonitor
|
internal class FocusMonitor
|
||||||
{
|
{
|
||||||
public delegate void FocusedItemChangedEventHandler(FocusedItemChangedEventArgs e);
|
public delegate void HeartbeatEventHandler(HeartbeatEventArgs e);
|
||||||
|
|
||||||
private static FocusMonitor _instance;
|
private static FocusMonitor _instance;
|
||||||
|
|
||||||
public bool IsRunning { get; private set; }
|
public bool IsRunning { get; private set; }
|
||||||
|
|
||||||
public event FocusedItemChangedEventHandler FocusedItemChanged;
|
public event HeartbeatEventHandler Heartbeat;
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
@@ -21,21 +20,16 @@ namespace QuickLook
|
|||||||
|
|
||||||
new Task(() =>
|
new Task(() =>
|
||||||
{
|
{
|
||||||
var currentPath = NativeMethods.QuickLook.GetCurrentSelectionFirst();
|
|
||||||
|
|
||||||
while (IsRunning)
|
while (IsRunning)
|
||||||
{
|
{
|
||||||
Thread.Sleep(500);
|
Thread.Sleep(500);
|
||||||
|
|
||||||
if (WindowHelper.IsFocusedControlExplorerItem())
|
if (NativeMethods.QuickLook.GetFocusedWindowType() ==
|
||||||
{
|
NativeMethods.QuickLook.FocusedWindowType.Invalid)
|
||||||
var file = NativeMethods.QuickLook.GetCurrentSelectionFirst();
|
continue;
|
||||||
if (file != currentPath)
|
|
||||||
{
|
var file = NativeMethods.QuickLook.GetCurrentSelection();
|
||||||
FocusedItemChanged?.Invoke(new FocusedItemChangedEventArgs(file));
|
Heartbeat?.Invoke(new HeartbeatEventArgs(DateTime.Now.Ticks, file));
|
||||||
currentPath = file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}).Start();
|
}).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;
|
FocusedFile = files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long InvokeTick { get; }
|
||||||
public string FocusedFile { get; }
|
public string FocusedFile { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace QuickLook
|
namespace QuickLook.Helpers
|
||||||
{
|
{
|
||||||
internal static class PidHelper
|
internal static class PidHelper
|
||||||
{
|
{
|
@@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Text;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using System.Windows.Interop;
|
using System.Windows.Interop;
|
||||||
@@ -61,65 +60,21 @@ namespace QuickLook.Helpers
|
|||||||
pixelY = (int) (matrix.M22 * unitY);
|
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)
|
internal static void SetNoactivate(WindowInteropHelper window)
|
||||||
{
|
{
|
||||||
User32.SetWindowLong(window.Handle, User32.GWL_EXSTYLE,
|
User32.SetWindowLong(window.Handle, User32.GWL_EXSTYLE,
|
||||||
User32.GetWindowLong(window.Handle, User32.GWL_EXSTYLE) |
|
User32.GetWindowLong(window.Handle, User32.GWL_EXSTYLE) |
|
||||||
User32.WS_EX_NOACTIVATE);
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -62,11 +62,17 @@
|
|||||||
WindowChrome.IsHitTestVisibleInChrome="True"
|
WindowChrome.IsHitTestVisibleInChrome="True"
|
||||||
Height="15" Margin="10,0" Foreground="Gray"
|
Height="15" Margin="10,0" Foreground="Gray"
|
||||||
Cursor="Hand" />
|
Cursor="Hand" />
|
||||||
<Button x:Name="buttonOpenWith" DockPanel.Dock="Right" Content="Open with ..." Height="20"
|
<Button x:Name="buttonOpenWith" DockPanel.Dock="Right" Content="Open with..." Height="20"
|
||||||
Margin="10,0,0,0" Padding="5,0"
|
Margin="10,0,0,0" Padding="5,0"
|
||||||
Focusable="False" Cursor="Hand"
|
Focusable="False" Cursor="Hand"
|
||||||
Background="#E5EEEEEE" BorderBrush="#E59A9A9A"
|
Background="#E5EEEEEE" BorderBrush="#E59A9A9A"
|
||||||
WindowChrome.IsHitTestVisibleInChrome="True" Foreground="#FF404040" />
|
WindowChrome.IsHitTestVisibleInChrome="True" Foreground="#FF404040">
|
||||||
|
<Button.ContentTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<ContentPresenter Content="{Binding}" RecognizesAccessKey="False" />
|
||||||
|
</DataTemplate>
|
||||||
|
</Button.ContentTemplate>
|
||||||
|
</Button>
|
||||||
<!-- set grid.background colour makes it clickable -->
|
<!-- set grid.background colour makes it clickable -->
|
||||||
<Grid x:Name="titleArea" Background="Transparent">
|
<Grid x:Name="titleArea" Background="Transparent">
|
||||||
<TextBlock Text="{Binding ContextObject.Title, ElementName=mainWindow}" FontSize="14"
|
<TextBlock Text="{Binding ContextObject.Title, ElementName=mainWindow}" FontSize="14"
|
||||||
|
@@ -3,13 +3,11 @@ using System.Diagnostics;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.ExceptionServices;
|
using System.Runtime.ExceptionServices;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Forms;
|
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Threading;
|
using System.Windows.Threading;
|
||||||
using QuickLook.Helpers;
|
using QuickLook.Helpers;
|
||||||
using QuickLook.Helpers.BlurLibrary;
|
using QuickLook.Helpers.BlurLibrary;
|
||||||
using QuickLook.Plugin;
|
using QuickLook.Plugin;
|
||||||
using KeyEventArgs = System.Windows.Forms.KeyEventArgs;
|
|
||||||
|
|
||||||
namespace QuickLook
|
namespace QuickLook
|
||||||
{
|
{
|
||||||
@@ -38,16 +36,16 @@ namespace QuickLook
|
|||||||
BlurWindow.EnableWindowBlur(this);
|
BlurWindow.EnableWindowBlur(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
buttonCloseWindow.MouseLeftButtonUp += (sender, e) => ViewWindowManager.GetInstance()
|
buttonCloseWindow.MouseLeftButtonUp += (sender, e) =>
|
||||||
.InvokeRoutine(new KeyEventArgs(Keys.Escape));
|
ViewWindowManager.GetInstance().ClosePreview();
|
||||||
|
|
||||||
buttonOpenWith.Click += (sender, e) => ViewWindowManager.GetInstance()
|
buttonOpenWith.Click += (sender, e) =>
|
||||||
.InvokeRoutine(new KeyEventArgs(Keys.Enter));
|
ViewWindowManager.GetInstance().RunAndClosePreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContextObject ContextObject { get; private set; }
|
public ContextObject ContextObject { get; private set; }
|
||||||
|
|
||||||
internal void RunAndClose()
|
internal void RunAndHide()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(_path))
|
if (string.IsNullOrEmpty(_path))
|
||||||
return;
|
return;
|
||||||
@@ -83,6 +81,12 @@ namespace QuickLook
|
|||||||
|
|
||||||
internal void UnloadPlugin()
|
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();
|
ContextObject.Reset();
|
||||||
|
|
||||||
_plugin?.Cleanup();
|
_plugin?.Cleanup();
|
||||||
@@ -151,10 +155,6 @@ namespace QuickLook
|
|||||||
|
|
||||||
internal void BeginHide()
|
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();
|
UnloadPlugin();
|
||||||
Hide();
|
Hide();
|
||||||
|
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
using System.Linq;
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@@ -8,40 +7,30 @@ namespace QuickLook.NativeMethods
|
|||||||
internal static class QuickLook
|
internal static class QuickLook
|
||||||
{
|
{
|
||||||
[DllImport("QuickLook.Native.Shell32.dll", CallingConvention = CallingConvention.Cdecl)]
|
[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)]
|
[DllImport("QuickLook.Native.Shell32.dll", EntryPoint = "GetCurrentSelection",
|
||||||
internal static extern void SaveCurrentSelection();
|
CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static extern void GetCurrentSelectionNative([MarshalAs(UnmanagedType.LPWStr)] StringBuilder sb);
|
||||||
|
|
||||||
[DllImport("QuickLook.Native.Shell32.dll", CallingConvention = CallingConvention.Cdecl)]
|
internal static string GetCurrentSelection()
|
||||||
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()
|
|
||||||
{
|
{
|
||||||
StringBuilder sb = null;
|
StringBuilder sb = null;
|
||||||
// communicate with COM in a separate thread
|
// communicate with COM in a separate thread
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
SaveCurrentSelection();
|
sb = new StringBuilder(255 + 1);
|
||||||
|
GetCurrentSelectionNative(sb);
|
||||||
var n = GetCurrentSelectionCount();
|
|
||||||
if (n != 0)
|
|
||||||
{
|
|
||||||
sb = new StringBuilder(n * 261); // MAX_PATH + NULL = 261
|
|
||||||
GetCurrentSelectionBuffer(sb);
|
|
||||||
}
|
|
||||||
}).Wait();
|
}).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();
|
Invalid,
|
||||||
|
Desktop,
|
||||||
return files.Any() ? files.First() : string.Empty;
|
Explorer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -31,8 +31,9 @@
|
|||||||
</Image>
|
</Image>
|
||||||
<Grid Grid.Column="1">
|
<Grid Grid.Column="1">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="20" />
|
<ColumnDefinition Width="5" />
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="10" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="10" />
|
<RowDefinition Height="10" />
|
||||||
@@ -42,7 +43,11 @@
|
|||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<TextBlock x:Name="filename" Grid.Row="1" Grid.Column="1" FontSize="19" FontWeight="SemiBold" Padding="3">Filename.ext</TextBlock>
|
<TextBlock x:Name="filename" Grid.Row="1" Grid.Column="1" FontSize="19" FontWeight="SemiBold" Padding="3"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
LineHeight="25" MaxHeight="60" TextTrimming="CharacterEllipsis">
|
||||||
|
FilenameFilenameFilenameFilenameFilenameFilenameFilenameFilenameFilenameFilename.ext
|
||||||
|
</TextBlock>
|
||||||
<TextBlock x:Name="modDate" Grid.Row="3" Grid.Column="1" Padding="3">Last modified at 01/01/2017 00:00:00</TextBlock>
|
<TextBlock x:Name="modDate" Grid.Row="3" Grid.Column="1" Padding="3">Last modified at 01/01/2017 00:00:00</TextBlock>
|
||||||
<TextBlock x:Name="totalSize" Grid.Row="4" Grid.Column="1" Padding="3">Calculating size...</TextBlock>
|
<TextBlock x:Name="totalSize" Grid.Row="4" Grid.Column="1" Padding="3">Calculating size...</TextBlock>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
@@ -116,7 +116,7 @@
|
|||||||
<Compile Include="NativeMethods\Shell32\IWshShortcut.cs" />
|
<Compile Include="NativeMethods\Shell32\IWshShortcut.cs" />
|
||||||
<Compile Include="NativeMethods\Shell32\ShellLink.cs" />
|
<Compile Include="NativeMethods\Shell32\ShellLink.cs" />
|
||||||
<Compile Include="NativeMethods\Shell32\WshShell.cs" />
|
<Compile Include="NativeMethods\Shell32\WshShell.cs" />
|
||||||
<Compile Include="PidHelper.cs" />
|
<Compile Include="Helpers\PidHelper.cs" />
|
||||||
<Compile Include="PluginManager.cs" />
|
<Compile Include="PluginManager.cs" />
|
||||||
<Compile Include="Plugin\InfoPanel\DpiHelpers.cs" />
|
<Compile Include="Plugin\InfoPanel\DpiHelpers.cs" />
|
||||||
<Compile Include="Plugin\InfoPanel\Extensions.cs" />
|
<Compile Include="Plugin\InfoPanel\Extensions.cs" />
|
||||||
|
@@ -3,7 +3,6 @@ using System.Diagnostics;
|
|||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using QuickLook.Helpers;
|
using QuickLook.Helpers;
|
||||||
using QuickLook.Properties;
|
using QuickLook.Properties;
|
||||||
using Application = System.Windows.Application;
|
|
||||||
|
|
||||||
namespace QuickLook
|
namespace QuickLook
|
||||||
{
|
{
|
||||||
@@ -26,14 +25,17 @@ namespace QuickLook
|
|||||||
{
|
{
|
||||||
_icon = new NotifyIcon
|
_icon = new NotifyIcon
|
||||||
{
|
{
|
||||||
|
Text = $"QuickLook v{Application.ProductVersion}",
|
||||||
Icon = Resources.app,
|
Icon = Resources.app,
|
||||||
Visible = true,
|
Visible = true,
|
||||||
ContextMenu = new ContextMenu(new[]
|
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/")),
|
(sender, e) => Process.Start(@"http://pooi.moe/QuickLook/")),
|
||||||
_itemAutorun,
|
_itemAutorun,
|
||||||
new MenuItem("&Quit", (sender, e) => Application.Current.Shutdown())
|
new MenuItem("&Quit", (sender, e) => System.Windows.Application.Current.Shutdown())
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -9,13 +9,14 @@ using QuickLook.Plugin;
|
|||||||
|
|
||||||
namespace QuickLook
|
namespace QuickLook
|
||||||
{
|
{
|
||||||
internal class ViewWindowManager
|
internal class ViewWindowManager : IDisposable
|
||||||
{
|
{
|
||||||
private static ViewWindowManager _instance;
|
private static ViewWindowManager _instance;
|
||||||
|
|
||||||
private readonly MainWindowNoTransparent _viewWindowNoTransparent;
|
private readonly MainWindowNoTransparent _viewWindowNoTransparent;
|
||||||
private readonly MainWindowTransparent _viewWindowTransparentTransparent;
|
private readonly MainWindowTransparent _viewWindowTransparentTransparent;
|
||||||
private MainWindowTransparent _currentMainWindow;
|
private MainWindowTransparent _currentMainWindow;
|
||||||
|
private long _lastSwitchTick;
|
||||||
|
|
||||||
private string _path = string.Empty;
|
private string _path = string.Empty;
|
||||||
|
|
||||||
@@ -27,10 +28,13 @@ namespace QuickLook
|
|||||||
_currentMainWindow = _viewWindowTransparentTransparent;
|
_currentMainWindow = _viewWindowTransparentTransparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
StopFocusMonitor();
|
||||||
|
}
|
||||||
|
|
||||||
internal void InvokeRoutine(KeyEventArgs kea)
|
internal void InvokeRoutine(KeyEventArgs kea)
|
||||||
{
|
{
|
||||||
Debug.WriteLine(kea.KeyCode);
|
|
||||||
|
|
||||||
switch (kea.KeyCode)
|
switch (kea.KeyCode)
|
||||||
{
|
{
|
||||||
case Keys.Up:
|
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())
|
if (NativeMethods.QuickLook.GetFocusedWindowType() ==
|
||||||
|
NativeMethods.QuickLook.FocusedWindowType.Invalid)
|
||||||
|
if (!WindowHelper.IsForegroundWindowBelongToSelf())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_currentMainWindow.Visibility != Visibility.Visible)
|
if (_currentMainWindow.Visibility != Visibility.Visible)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
StopFocusMonitor();
|
StopFocusMonitor();
|
||||||
_currentMainWindow.RunAndClose();
|
_currentMainWindow.RunAndHide();
|
||||||
if (kea != null)
|
if (kea != null)
|
||||||
kea.Handled = true;
|
kea.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void ClosePreview(KeyEventArgs kea = null)
|
internal void ClosePreview(KeyEventArgs kea = null)
|
||||||
{
|
{
|
||||||
|
if (NativeMethods.QuickLook.GetFocusedWindowType() ==
|
||||||
|
NativeMethods.QuickLook.FocusedWindowType.Invalid)
|
||||||
|
if (!WindowHelper.IsForegroundWindowBelongToSelf())
|
||||||
|
return;
|
||||||
|
|
||||||
StopFocusMonitor();
|
StopFocusMonitor();
|
||||||
_currentMainWindow.BeginHide();
|
_currentMainWindow.BeginHide();
|
||||||
|
|
||||||
@@ -78,7 +89,11 @@ namespace QuickLook
|
|||||||
|
|
||||||
private void TogglePreview(KeyEventArgs kea = null)
|
private void TogglePreview(KeyEventArgs kea = null)
|
||||||
{
|
{
|
||||||
if (!WindowHelper.IsFocusedControlExplorerItem() && !WindowHelper.IsFocusedWindowSelf())
|
_lastSwitchTick = DateTime.Now.Ticks;
|
||||||
|
|
||||||
|
if (NativeMethods.QuickLook.GetFocusedWindowType() ==
|
||||||
|
NativeMethods.QuickLook.FocusedWindowType.Invalid)
|
||||||
|
if (!WindowHelper.IsForegroundWindowBelongToSelf())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_currentMainWindow.Visibility == Visibility.Visible)
|
if (_currentMainWindow.Visibility == Visibility.Visible)
|
||||||
@@ -87,7 +102,7 @@ namespace QuickLook
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_path = NativeMethods.QuickLook.GetCurrentSelectionFirst();
|
_path = NativeMethods.QuickLook.GetCurrentSelection();
|
||||||
InvokeViewer();
|
InvokeViewer();
|
||||||
}
|
}
|
||||||
if (kea != null)
|
if (kea != null)
|
||||||
@@ -99,38 +114,34 @@ namespace QuickLook
|
|||||||
if (_currentMainWindow.Visibility != Visibility.Visible)
|
if (_currentMainWindow.Visibility != Visibility.Visible)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!WindowHelper.IsFocusedControlExplorerItem())
|
_lastSwitchTick = DateTime.Now.Ticks;
|
||||||
|
|
||||||
|
if (NativeMethods.QuickLook.GetFocusedWindowType() ==
|
||||||
|
NativeMethods.QuickLook.FocusedWindowType.Invalid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_path = NativeMethods.QuickLook.GetCurrentSelectionFirst();
|
_path = NativeMethods.QuickLook.GetCurrentSelection();
|
||||||
|
|
||||||
InvokeViewer();
|
InvokeViewer();
|
||||||
if (kea != null)
|
if (kea != null)
|
||||||
kea.Handled = false;
|
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)
|
if (e.FocusedFile == _path)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Debug.WriteLine("SwitchPreviewRemoteInvoke:" + (e.InvokeTick - _lastSwitchTick));
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(e.FocusedFile))
|
if (string.IsNullOrEmpty(e.FocusedFile))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_currentMainWindow?.Dispatcher.Invoke(() =>
|
_currentMainWindow?.Dispatcher.Invoke(() => SwitchPreview());
|
||||||
{
|
|
||||||
if (_currentMainWindow.Visibility != Visibility.Visible)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!WindowHelper.IsFocusedControlExplorerItem())
|
|
||||||
return;
|
|
||||||
|
|
||||||
_path = NativeMethods.QuickLook.GetCurrentSelectionFirst();
|
|
||||||
|
|
||||||
InvokeViewer();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RunFocusMonitor()
|
private void RunFocusMonitor()
|
||||||
@@ -138,7 +149,7 @@ namespace QuickLook
|
|||||||
if (!FocusMonitor.GetInstance().IsRunning)
|
if (!FocusMonitor.GetInstance().IsRunning)
|
||||||
{
|
{
|
||||||
FocusMonitor.GetInstance().Start();
|
FocusMonitor.GetInstance().Start();
|
||||||
FocusMonitor.GetInstance().FocusedItemChanged += SwitchPreviewRemoteInvoke;
|
FocusMonitor.GetInstance().Heartbeat += SwitchPreviewRemoteInvoke;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +158,7 @@ namespace QuickLook
|
|||||||
if (FocusMonitor.GetInstance().IsRunning)
|
if (FocusMonitor.GetInstance().IsRunning)
|
||||||
{
|
{
|
||||||
FocusMonitor.GetInstance().Stop();
|
FocusMonitor.GetInstance().Stop();
|
||||||
FocusMonitor.GetInstance().FocusedItemChanged -= SwitchPreviewRemoteInvoke;
|
FocusMonitor.GetInstance().Heartbeat -= SwitchPreviewRemoteInvoke;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user