This commit is contained in:
Paddy Xu
2017-04-12 17:58:52 +03:00
commit 7e2001bc4d
42 changed files with 1935 additions and 0 deletions

290
.gitignore vendored Normal file
View File

@@ -0,0 +1,290 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Typescript v1 declaration files
typings/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
/QuickLook.Plugin.PDFViewer/MoonPdfLib

View File

@@ -0,0 +1,21 @@
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include "Shell32.h"
#define EXPORT extern "C" __declspec(dllexport)
EXPORT void SaveCurrentSelection()
{
Shell32::SaveCurrentSelection();
}
EXPORT int GetCurrentSelectionCount()
{
return Shell32::GetCurrentSelectionCount();
}
EXPORT void GetCurrentSelectionBuffer(PWCHAR buffer)
{
Shell32::GetCurrentSelectionBuffer(buffer);
}

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{D31EE321-C2B0-4984-B749-736F7DE509F1}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>QuickLookShell32Helper</RootNamespace>
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
<ProjectName>QuickLook.Native.Shell32</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)Build\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)Build\$(Configuration)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;QUICKLOOKSHELL32HELPER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;QUICKLOOKSHELL32HELPER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Shell32.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="QuickLook.Native.Shell32.cpp" />
<ClCompile Include="Shell32.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Shell32.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="QuickLook.Native.Shell32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Shell32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,220 @@
#include "stdafx.h"
#include "Shell32.h"
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);
CComPtr<IShellBrowser> psb;
CComPtr<IShellView> psv;
CComPtr<IFolderView> pfv;
CComPtr<IPersistFolder2> ppf2;
if (!psp) return;
if (SUCCEEDED(psp->QueryService(SID_STopLevelBrowser, IID_IShellBrowser, reinterpret_cast<LPVOID*>(&psb))))
{
if (SUCCEEDED(psb->QueryActiveShellView(&psv)))
{
if (SUCCEEDED(psv->QueryInterface(IID_IFolderView, reinterpret_cast<void**>(&pfv))))
{
if (SUCCEEDED(pfv->GetFolder(IID_IPersistFolder2, reinterpret_cast<void**>(&ppf2))))
{
LPITEMIDLIST pidlFolder;
if (SUCCEEDED(ppf2->GetCurFolder(&pidlFolder)))
{
CComPtr<IDataObject> dao;
if (SUCCEEDED(psv->GetItemObject(SVGIO_SELECTION, IID_IDataObject, reinterpret_cast<void**>(&dao))))
vectorFromDataObject(dao);
}
CoTaskMemFree(pidlFolder);
}
}
}
}
}
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()
{
auto type = INVALID;
auto hwndfg = GetForegroundWindow();
auto classBuffer = new WCHAR[MAX_PATH];
if (SUCCEEDED(GetClassName(hwndfg, classBuffer, MAX_PATH)))
{
if (wcscmp(classBuffer, L"WorkerW") == 0 || wcscmp(classBuffer, L"Progman") == 0)
{
if (FindWindowEx(hwndfg, nullptr, L"SHELLDLL_DefView", nullptr) != nullptr)
{
type = DESKTOP;
}
}
else if (wcscmp(classBuffer, L"ExploreWClass") == 0 || wcscmp(classBuffer, L"CabinetWClass") == 0)
{
type = EXPLORER;
}
}
delete[] classBuffer;
return type;
}

View File

@@ -0,0 +1,29 @@
#pragma once
#include "stdafx.h"
class Shell32
{
public:
static void SaveCurrentSelection();
static UINT GetCurrentSelectionCount();
static void GetCurrentSelectionBuffer(PWCHAR buffer);
private:
enum FocusedWindowType
{
INVALID,
DESKTOP,
EXPLORER,
};
static std::vector<std::wstring> vector_items;
static void SaveSelectedFromDesktop();
static void SaveSelectedFromExplorer();
static FocusedWindowType GetFocusedWindowType();
static CComQIPtr<IWebBrowser2> AttachDesktopShellWindow();
static void vectorFromDataObject(CComPtr<IDataObject> dao);
};

View File

@@ -0,0 +1,18 @@
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include "Shell32.h"
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
default:
break;
}
return TRUE;
}

View File

@@ -0,0 +1,8 @@
// stdafx.cpp : source file that includes just the standard includes
// QuickLook.Shell32Helper.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

View File

@@ -0,0 +1,23 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>
// TODO: reference additional headers your program requires here
#include<atlcomcli.h>
#include<Exdisp.h>
#include<Shobjidl.h>
#include<shlguid.h>
#include<Shlobj.h>
#include<Shellapi.h>
#include<vector>

View File

@@ -0,0 +1,8 @@
#pragma once
// Including SDKDDKVer.h defines the highest available Windows platform.
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
#include <SDKDDKVer.h>

View File

@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;
using MoonPdfLib;
namespace QuickLook.Plugin.PDFViewer
{
public class Class1:IViewer
{
public bool CanView(string path, byte[] sample)
{
if (String.IsNullOrEmpty(path))
return false;
if (Path.GetExtension(path).ToLower() == ".pdf")
return true;
if (Encoding.ASCII.GetString(sample.Take(4).ToArray()) == "%PDF")
return true;
return false;
}
public void View(string path, ViewContentContainer container)
{
MoonPdfPanel pdfPanel = new MoonPdfPanel
{
ViewType = ViewType.SinglePage,
PageRowDisplay = PageRowDisplayType.ContinuousPageRows,
PageMargin = new System.Windows.Thickness(0, 2, 4, 2),
Background = new SolidColorBrush(Colors.LightGray)
};
container.SetContent(pdfPanel);
Task.Delay(200).ContinueWith(t => container.Dispatcher.Invoke(() => pdfPanel.OpenFile(path)));
Task.Delay(400).ContinueWith(t => container.Dispatcher.Invoke(() => pdfPanel.ZoomToWidth()));
}
public void Close()
{
return;
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("QuickLook.Plugin.PDFViewer")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("QuickLook.Plugin.PDFViewer")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("a82ac69c-edf5-4f0d-8cbd-8e5e3c06e64d")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{A82AC69C-EDF5-4F0D-8CBD-8E5E3C06E64D}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>QuickLook.Plugin.PDFViewer</RootNamespace>
<AssemblyName>QuickLook.Plugin.PDFViewer</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\Build\Debug\Plugins\PDFViewer\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\Build\Release\Plugins\PDFViewer\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="MoonPdfLib, Version=0.3.0.0, Culture=neutral, processorArchitecture=x86">
<HintPath>..\packages\MoonPdfLib-x86.0.3.0\lib\MoonPdfLib.dll</HintPath>
</Reference>
<Reference Include="MouseKeyboardActivityMonitor, Version=3.0.1.29653, Culture=neutral, processorArchitecture=x86">
<HintPath>..\packages\MoonPdfLib-x86.0.3.0\lib\MouseKeyboardActivityMonitor.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xaml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="Class1.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\QuickLook\QuickLook.csproj">
<Project>{8b4a9ce5-67b5-4a94-81cb-3771f688fdeb}</Project>
<Name>QuickLook</Name>
<Private>False</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="MoonPdfLib\README" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Content Include="libmupdf.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=references/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

Binary file not shown.

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MoonPdfLib-x86" version="0.3.0" targetFramework="net452" />
</packages>

63
QuickLook.sln Normal file
View File

@@ -0,0 +1,63 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26403.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuickLook", "QuickLook\QuickLook.csproj", "{8B4A9CE5-67B5-4A94-81CB-3771F688FDEB}"
ProjectSection(ProjectDependencies) = postProject
{D31EE321-C2B0-4984-B749-736F7DE509F1} = {D31EE321-C2B0-4984-B749-736F7DE509F1}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QuickLook.Native.Shell32", "QuickLook.Native.Shell32\QuickLook.Native.Shell32.vcxproj", "{D31EE321-C2B0-4984-B749-736F7DE509F1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuickLook.Plugin.PDFViewer", "QuickLook.Plugin.PDFViewer\QuickLook.Plugin.PDFViewer.csproj", "{A82AC69C-EDF5-4F0D-8CBD-8E5E3C06E64D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8B4A9CE5-67B5-4A94-81CB-3771F688FDEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8B4A9CE5-67B5-4A94-81CB-3771F688FDEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8B4A9CE5-67B5-4A94-81CB-3771F688FDEB}.Debug|x64.ActiveCfg = Debug|Any CPU
{8B4A9CE5-67B5-4A94-81CB-3771F688FDEB}.Debug|x64.Build.0 = Debug|Any CPU
{8B4A9CE5-67B5-4A94-81CB-3771F688FDEB}.Debug|x86.ActiveCfg = Debug|Any CPU
{8B4A9CE5-67B5-4A94-81CB-3771F688FDEB}.Debug|x86.Build.0 = Debug|Any CPU
{8B4A9CE5-67B5-4A94-81CB-3771F688FDEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B4A9CE5-67B5-4A94-81CB-3771F688FDEB}.Release|Any CPU.Build.0 = Release|Any CPU
{8B4A9CE5-67B5-4A94-81CB-3771F688FDEB}.Release|x64.ActiveCfg = Release|Any CPU
{8B4A9CE5-67B5-4A94-81CB-3771F688FDEB}.Release|x64.Build.0 = Release|Any CPU
{8B4A9CE5-67B5-4A94-81CB-3771F688FDEB}.Release|x86.ActiveCfg = Release|Any CPU
{8B4A9CE5-67B5-4A94-81CB-3771F688FDEB}.Release|x86.Build.0 = Release|Any CPU
{D31EE321-C2B0-4984-B749-736F7DE509F1}.Debug|Any CPU.ActiveCfg = Debug|Win32
{D31EE321-C2B0-4984-B749-736F7DE509F1}.Debug|Any CPU.Build.0 = Debug|Win32
{D31EE321-C2B0-4984-B749-736F7DE509F1}.Debug|x64.ActiveCfg = Debug|Win32
{D31EE321-C2B0-4984-B749-736F7DE509F1}.Debug|x86.ActiveCfg = Debug|Win32
{D31EE321-C2B0-4984-B749-736F7DE509F1}.Debug|x86.Build.0 = Debug|Win32
{D31EE321-C2B0-4984-B749-736F7DE509F1}.Release|Any CPU.ActiveCfg = Release|Win32
{D31EE321-C2B0-4984-B749-736F7DE509F1}.Release|Any CPU.Build.0 = Release|Win32
{D31EE321-C2B0-4984-B749-736F7DE509F1}.Release|x64.ActiveCfg = Release|Win32
{D31EE321-C2B0-4984-B749-736F7DE509F1}.Release|x86.ActiveCfg = Release|Win32
{D31EE321-C2B0-4984-B749-736F7DE509F1}.Release|x86.Build.0 = Release|Win32
{A82AC69C-EDF5-4F0D-8CBD-8E5E3C06E64D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A82AC69C-EDF5-4F0D-8CBD-8E5E3C06E64D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A82AC69C-EDF5-4F0D-8CBD-8E5E3C06E64D}.Debug|x64.ActiveCfg = Debug|Any CPU
{A82AC69C-EDF5-4F0D-8CBD-8E5E3C06E64D}.Debug|x64.Build.0 = Debug|Any CPU
{A82AC69C-EDF5-4F0D-8CBD-8E5E3C06E64D}.Debug|x86.ActiveCfg = Debug|Any CPU
{A82AC69C-EDF5-4F0D-8CBD-8E5E3C06E64D}.Debug|x86.Build.0 = Debug|Any CPU
{A82AC69C-EDF5-4F0D-8CBD-8E5E3C06E64D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A82AC69C-EDF5-4F0D-8CBD-8E5E3C06E64D}.Release|Any CPU.Build.0 = Release|Any CPU
{A82AC69C-EDF5-4F0D-8CBD-8E5E3C06E64D}.Release|x64.ActiveCfg = Release|Any CPU
{A82AC69C-EDF5-4F0D-8CBD-8E5E3C06E64D}.Release|x64.Build.0 = Release|Any CPU
{A82AC69C-EDF5-4F0D-8CBD-8E5E3C06E64D}.Release|x86.ActiveCfg = Release|Any CPU
{A82AC69C-EDF5-4F0D-8CBD-8E5E3C06E64D}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

23
QuickLook.sln.DotSettings Normal file
View File

@@ -0,0 +1,23 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeEditing/Intellisense/CodeCompletion/IntelliSenseCompletingCharacters/CSharpCompletingCharacters/UpgradedFromVSSettings/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeCleanup/RecentlyUsedProfile/@EntryValue">Default: Reformat Code</s:String>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_AROUND_AUTO_PROPERTY/@EntryValue">0</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_AROUND_FIELD/@EntryValue">0</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_AROUND_PROPERTY/@EntryValue">0</s:Int64>
<s:Boolean x:Key="/Default/Environment/ExternalSources/FirstTimeFormShown/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/ExternalSources/Decompiler/DecompileMethodBodies/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/Environment/Feedback/ShouldPrompt/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/Environment/Hierarchy/PsiConfigurationSettingsKey/CustomLocation/@EntryValue">C:\Users\Paddy\AppData\Local\JetBrains\Transient\ReSharperPlatformVs15\v08_4c97e4a7\SolutionCaches</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
<s:String x:Key="/Default/Environment/UpdatesManger/LastUpdateCheck/@EntryValue">04/11/2017 18:22:55</s:String>
<s:String x:Key="/Default/Environment/UserInterface/ShortcutSchemeName/@EntryValue">VS</s:String>
<s:String x:Key="/Default/Housekeeping/FeedbackReport/SelectedUserIdentificator/@EntryValue">anonymous</s:String>
<s:Boolean x:Key="/Default/Housekeeping/GlobalSettingsUpgraded/IsUpgraded/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/Housekeeping/Layout/DialogWindows/OptionsDialog/Position/@EntryValue">[19,13](1024,768)</s:String>
<s:String x:Key="/Default/Housekeeping/Layout/DialogWindows/OptionsDialog/SelectedPageId/@EntryValue">CSharpBlankLinesPage</s:String>
<s:String x:Key="/Default/Housekeeping/Layout/DialogWindows/RefactoringWizardWindow/Location/@EntryValue">-941,-110</s:String>
<s:Boolean x:Key="/Default/Housekeeping/LiveTemplatesHousekeeping/HotspotSessionHintIsShown/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Housekeeping/RefactoringsMru/UseInline/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/Housekeeping/UpgradeFromExceptionReport/UpgradePerformed/@EntryValue">True</s:Boolean></wpf:ResourceDictionary>

6
QuickLook/App.config Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>

9
QuickLook/App.xaml Normal file
View File

@@ -0,0 +1,9 @@
<Application x:Class="QuickLook.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:QuickLook"
Startup="Application_Startup">
<Application.Resources>
</Application.Resources>
</Application>

29
QuickLook/App.xaml.cs Normal file
View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows;
using QuickLook.Plugin;
using QuickLook.Utilities;
namespace QuickLook
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public static string AppPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
private void Application_Startup(object sender, StartupEventArgs e)
{
PluginManager.GetInstance();
BackgroundListener.GetInstance();
}
}
}

View File

@@ -0,0 +1,60 @@
using System.Text;
using System.Threading;
using System.Windows.Forms;
using QuickLook.Utilities;
namespace QuickLook
{
internal class BackgroundListener
{
private static BackgroundListener _instance;
private GlobalKeyboardHook _hook;
protected BackgroundListener()
{
InstallHook(HotkeyEventHandler);
}
private void HotkeyEventHandler(object sender, KeyEventArgs e)
{
string[] paths;
// communicate with COM in a separate thread
var tCom = new Thread(() => paths = GetCurrentSelection());
tCom.Start();
tCom.Join();
var mw = new MainWindow();
mw.Show();
}
private void InstallHook(KeyEventHandler handler)
{
_hook = GlobalKeyboardHook.GetInstance();
_hook.HookedKeys.Add(Keys.Space);
_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()
{
return _instance ?? (_instance = new BackgroundListener());
}
}
}

View File

@@ -0,0 +1,30 @@
using System;
using System.Threading.Tasks;
using System.Windows.Threading;
namespace QuickLook.ExtensionMethods
{
internal static class DispatcherExtensions
{
public static void Delay(this Dispatcher disp, int delayMs,
Action<object> action, object parm = null)
{
Task.Delay(delayMs).ContinueWith(t => { disp.Invoke(action, parm); });
}
public static void DelayWithPriority(this Dispatcher disp, int delayMs,
Action<object> action, object parm = null,
DispatcherPriority priority = DispatcherPriority.ApplicationIdle)
{
Task.Delay(delayMs).ContinueWith(t => { disp.BeginInvoke(action, priority, parm); });
}
public static async Task DelayAsync(this Dispatcher disp, int delayMs,
Action<object> action, object parm = null,
DispatcherPriority priority = DispatcherPriority.ApplicationIdle)
{
await Task.Delay(delayMs);
await disp.BeginInvoke(action, priority, parm);
}
}
}

29
QuickLook/MainWindow.xaml Normal file
View File

@@ -0,0 +1,29 @@
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:fa="http://schemas.fontawesome.io/icons/"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:QuickLook"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:plugin="clr-namespace:QuickLook.Plugin"
mc:Ignorable="d" x:Class="QuickLook.MainWindow" x:Name="mainWindow" AllowsTransparency="True" WindowStyle="None"
UseLayoutRounding="True"
Topmost="True" d:DesignWidth="624" d:DesignHeight="700" Width="624" Height="700" WindowStartupLocation="CenterScreen"
x:ClassModifier="internal">
<Window.Background>
<SolidColorBrush Color="#00FFFFFF" />
</Window.Background>
<Grid Name="WindowContainer">
<Grid.Background>
<SolidColorBrush Color="#AAB0B0B0" />
</Grid.Background>
<Grid Name="LoadingIcon" Height="50" Width="50" HorizontalAlignment="Center" VerticalAlignment="Center" >
<fa:ImageAwesome Icon="CircleOutlineNotch" Spin="True" SpinDuration="2" />
</Grid>
<Grid Name="ContentContainer" Width="624" Height="700">
<plugin:ViewContentContainer x:Name="ViewContentContainer"/>
</Grid>
<Button Content="Button" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click" />
</Grid>
</Window>

View File

@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Channels;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using QuickLook.ExtensionMethods;
using QuickLook.Plugin;
using QuickLook.Utilities;
using MessageBox = System.Windows.MessageBox;
using Path = System.IO.Path;
namespace QuickLook
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
internal partial class MainWindow : Window
{
internal MainWindow()
{
InitializeComponent();
WindowContainer.Width = LoadingIcon.Width;
WindowContainer.Height = LoadingIcon.Height;
ContentContainer.Visibility = Visibility.Hidden;
}
private void ZoomToPreferedSize()
{
Storyboard sb = new Storyboard { };
ParallelTimeline ptl = new ParallelTimeline();
DoubleAnimation animationWidth = new DoubleAnimation
{
From = WindowContainer.Width,
To = ContentContainer.Width,
Duration = TimeSpan.FromSeconds(0.2),
DecelerationRatio = 0.3
};
DoubleAnimation animationHeight = new DoubleAnimation
{
From = WindowContainer.Height,
To = ContentContainer.Height,
Duration = TimeSpan.FromSeconds(0.2),
DecelerationRatio = 0.3
};
Storyboard.SetTarget(animationWidth, WindowContainer);
Storyboard.SetTarget(animationHeight, WindowContainer);
Storyboard.SetTargetProperty(animationWidth, new PropertyPath(WidthProperty));
Storyboard.SetTargetProperty(animationHeight, new PropertyPath(HeightProperty));
ptl.Children.Add(animationWidth);
ptl.Children.Add(animationHeight);
sb.Children.Add(ptl);
sb.Begin();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
ZoomToPreferedSize();
}
}
}

View File

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

View File

@@ -0,0 +1,17 @@
using System.Runtime.InteropServices;
using System.Text;
namespace QuickLook.NativeMethods
{
internal class QuickLook
{
[DllImport("QuickLook.Native.Shell32.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern void SaveCurrentSelection();
[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);
}
}

View File

@@ -0,0 +1,39 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
namespace QuickLook.NativeMethods
{
internal class User32
{
[DllImport("user32.dll")]
internal static extern IntPtr SetWindowsHookEx(int idHook, KeyboardHookProc callback, IntPtr hInstance,
uint threadId);
[DllImport("user32.dll")]
internal static extern bool UnhookWindowsHookEx(IntPtr hInstance);
[DllImport("user32.dll")]
internal static extern int CallNextHookEx(IntPtr idHook, int nCode, int wParam, ref KeyboardHookStruct lParam);
internal delegate int KeyboardHookProc(int code, int wParam, ref KeyboardHookStruct lParam);
[SuppressMessage("ReSharper", "InconsistentNaming")]
internal struct KeyboardHookStruct
{
internal int vkCode;
internal int scanCode;
internal int flags;
internal int time;
internal int dwExtraInfo;
}
// ReSharper disable InconsistentNaming
internal const int WH_KEYBOARD_LL = 13;
internal const int WM_KEYDOWN = 0x100;
internal const int WM_KEYUP = 0x101;
internal const int WM_SYSKEYDOWN = 0x104;
internal const int WM_SYSKEYUP = 0x105;
// ReSharper restore InconsistentNaming
}
}

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace QuickLook
{
class PathToPluginMatcher
{
}
}

View File

@@ -0,0 +1,9 @@
namespace QuickLook.Plugin
{
public interface IViewer
{
bool CanView(string path, byte[] sample);
void View(string path, ViewContentContainer container);
void Close();
}
}

View File

@@ -0,0 +1,14 @@
<UserControl x:Class="QuickLook.Plugin.ViewContentContainer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:QuickLook"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<ContentControl Name="Container" >
<Label Content="ContentControl Placeholder" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Background="LightGray" />
</ContentControl>
</Grid>
</UserControl>

View File

@@ -0,0 +1,20 @@
using System.Windows.Controls;
namespace QuickLook.Plugin
{
/// <summary>
/// Interaction logic for ViewContentContainer.xaml
/// </summary>
public partial class ViewContentContainer : UserControl
{
public ViewContentContainer()
{
InitializeComponent();
}
public void SetContent(object content)
{
Container.Content = content;
}
}
}

View File

@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using QuickLook.Plugin;
namespace QuickLook
{
internal class PluginManager
{
private static PluginManager _instance;
internal PluginManager()
{
LoadPlugins();
}
internal List<IViewer> LoadedPlugins { get; } = new List<IViewer>();
internal static PluginManager GetInstance()
{
return _instance ?? (_instance = new PluginManager());
}
private void LoadPlugins()
{
Directory.GetFiles(Path.Combine(App.AppPath, "Plugins\\"), "QuickLook.Plugin.*.dll",
SearchOption.AllDirectories)
.ToList()
.ForEach(
lib =>
{
(from t in Assembly.LoadFrom(lib).GetExportedTypes()
where !t.IsInterface && !t.IsAbstract
where typeof(IViewer).IsAssignableFrom(t)
select t).ToList()
.ForEach(type => LoadedPlugins.Add((IViewer) Activator.CreateInstance(type)));
});
}
}
}

View File

@@ -0,0 +1,55 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("QuickLook")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("QuickLook")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace QuickLook.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("QuickLook.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace QuickLook.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}

View File

@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

145
QuickLook/QuickLook.csproj Normal file
View File

@@ -0,0 +1,145 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{8B4A9CE5-67B5-4A94-81CB-3771F688FDEB}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>QuickLook</RootNamespace>
<AssemblyName>QuickLook</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\Build\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\Build\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="FontAwesome.WPF, Version=4.7.0.37774, Culture=neutral, PublicKeyToken=0758b07a11a4f466, processorArchitecture=MSIL">
<HintPath>..\packages\FontAwesome.WPF.4.7.0.9\lib\net40\FontAwesome.WPF.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="PathToPluginMatcher.cs" />
<Compile Include="PluginManager.cs" />
<Compile Include="Plugin\IViewer.cs" />
<Compile Include="Plugin\ViewContentContainer.xaml.cs">
<DependentUpon>ViewContentContainer.xaml</DependentUpon>
</Compile>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="ExtensionMethods\DispatcherExtensions.cs" />
<Compile Include="BackgroundListener.cs" />
<Compile Include="NativeMethods\Kernel32.cs" />
<Compile Include="NativeMethods\User32.cs" />
<Compile Include="Utilities\GlobalKeyboardHook.cs" />
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="Plugin\ViewContentContainer.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<Compile Include="NativeMethods\QuickLook.cs" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.5.2">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.5.2 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using QuickLook.NativeMethods;
namespace QuickLook.Utilities
{
internal class GlobalKeyboardHook
{
private static GlobalKeyboardHook _instance;
private User32.KeyboardHookProc _callback;
private IntPtr _hhook = IntPtr.Zero;
internal List<Keys> HookedKeys = new List<Keys>();
protected GlobalKeyboardHook()
{
Hook();
}
internal event KeyEventHandler KeyDown;
internal event KeyEventHandler KeyUp;
~GlobalKeyboardHook()
{
Unhook();
}
internal static GlobalKeyboardHook GetInstance()
{
return _instance ?? (_instance = new GlobalKeyboardHook());
}
private void Hook()
{
_callback = HookProc;
var hInstance = Kernel32.LoadLibrary("user32.dll");
_hhook = User32.SetWindowsHookEx(User32.WH_KEYBOARD_LL, _callback, hInstance, 0);
}
private void Unhook()
{
if (_callback == null) return;
User32.UnhookWindowsHookEx(_hhook);
_callback = null;
}
private int HookProc(int code, int wParam, ref User32.KeyboardHookStruct lParam)
{
if (code >= 0)
{
var key = (Keys) lParam.vkCode;
if (HookedKeys.Contains(key))
{
var kea = new KeyEventArgs(key);
if (wParam == User32.WM_KEYDOWN || wParam == User32.WM_SYSKEYDOWN)
KeyDown?.Invoke(this, kea);
if (wParam == User32.WM_KEYUP || wParam == User32.WM_SYSKEYUP)
KeyUp?.Invoke(this, kea);
if (kea.Handled)
return 1;
}
}
return User32.CallNextHookEx(_hhook, code, wParam, ref lParam);
}
}
}

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FontAwesome.WPF" version="4.7.0.9" targetFramework="net452" />
</packages>