diff --git a/.pipelines/pipeline.user.windows.yml b/.pipelines/pipeline.user.windows.yml
index 636c090b2a..1c6d883455 100644
--- a/.pipelines/pipeline.user.windows.yml
+++ b/.pipelines/pipeline.user.windows.yml
@@ -42,8 +42,6 @@ restore:
name: 'Restore Tools packages'
command: '.pipelines\restore-tools.cmd'
-
-
build:
commands:
# Localize the files before the Build PowerToys step to generate translated resx files from the lcl files
@@ -113,6 +111,8 @@ build:
- 'modules\FileExplorerPreview\MarkdownPreviewHandler.comhost.dll'
- 'modules\FileExplorerPreview\PdfPreviewHandler.dll'
- 'modules\FileExplorerPreview\PdfPreviewHandler.comhost.dll'
+ - 'modules\FileExplorerPreview\PdfThumbnailProvider.dll'
+ - 'modules\FileExplorerPreview\PdfThumbnailProvider.comhost.dll'
- 'modules\FileExplorerPreview\powerpreview.dll'
- 'modules\FileExplorerPreview\PreviewHandlerCommon.dll'
- 'modules\FileExplorerPreview\SvgPreviewHandler.dll'
@@ -229,7 +229,6 @@ build:
signing_options:
sign_inline: true # This does signing as soon as this command completes
-
#package:
# commands:
# - !!buildcommand
diff --git a/PowerToys.sln b/PowerToys.sln
index d58e52fadd..b17039b9fd 100644
--- a/PowerToys.sln
+++ b/PowerToys.sln
@@ -17,6 +17,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "runner", "src\runner\runner
{0B593A6C-4143-4337-860E-DB5710FB87DB} = {0B593A6C-4143-4337-860E-DB5710FB87DB}
{E364F67B-BB12-4E91-B639-355866EBCD8B} = {E364F67B-BB12-4E91-B639-355866EBCD8B}
{D940E07F-532C-4FF3-883F-790DA014F19A} = {D940E07F-532C-4FF3-883F-790DA014F19A}
+ {69E1EE8D-143A-4060-9129-4658ACF14AAF} = {69E1EE8D-143A-4060-9129-4658ACF14AAF}
{DA425894-6E13-404F-8DCB-78584EC0557A} = {DA425894-6E13-404F-8DCB-78584EC0557A}
{2BE46397-4DFA-414C-9BD4-41E4BBF8CB34} = {2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}
{A7D5099E-F0FD-4BF3-8522-5A682759F915} = {A7D5099E-F0FD-4BF3-8522-5A682759F915}
@@ -362,6 +363,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VideoConferenceProxyFilter"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "VideoConference", "VideoConference", "{470FBAF9-E1F8-4F3E-8786-198A1C81C8A8}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PdfThumbnailProvider", "src\modules\previewpane\PdfThumbnailProvider\PdfThumbnailProvider.csproj", "{11491FD8-F921-48BF-880C-7FEA185B80A1}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-PdfThumbnailProvider", "src\modules\previewpane\UnitTests-PdfThumbnailProvider\UnitTests-PdfThumbnailProvider.csproj", "{F40C3397-1834-4530-B2D9-8F8B8456BCDF}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -948,6 +953,18 @@ Global
{AC2857B4-103D-4D6D-9740-926EBF785042}.Release|x64.Build.0 = Release|x64
{AC2857B4-103D-4D6D-9740-926EBF785042}.Release|x86.ActiveCfg = Release|Win32
{AC2857B4-103D-4D6D-9740-926EBF785042}.Release|x86.Build.0 = Release|Win32
+ {11491FD8-F921-48BF-880C-7FEA185B80A1}.Debug|x64.ActiveCfg = Debug|x64
+ {11491FD8-F921-48BF-880C-7FEA185B80A1}.Debug|x64.Build.0 = Debug|x64
+ {11491FD8-F921-48BF-880C-7FEA185B80A1}.Debug|x86.ActiveCfg = Debug|x64
+ {11491FD8-F921-48BF-880C-7FEA185B80A1}.Release|x64.ActiveCfg = Release|x64
+ {11491FD8-F921-48BF-880C-7FEA185B80A1}.Release|x64.Build.0 = Release|x64
+ {11491FD8-F921-48BF-880C-7FEA185B80A1}.Release|x86.ActiveCfg = Release|x64
+ {F40C3397-1834-4530-B2D9-8F8B8456BCDF}.Debug|x64.ActiveCfg = Debug|x64
+ {F40C3397-1834-4530-B2D9-8F8B8456BCDF}.Debug|x64.Build.0 = Debug|x64
+ {F40C3397-1834-4530-B2D9-8F8B8456BCDF}.Debug|x86.ActiveCfg = Debug|x64
+ {F40C3397-1834-4530-B2D9-8F8B8456BCDF}.Release|x64.ActiveCfg = Release|x64
+ {F40C3397-1834-4530-B2D9-8F8B8456BCDF}.Release|x64.Build.0 = Release|x64
+ {F40C3397-1834-4530-B2D9-8F8B8456BCDF}.Release|x86.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1061,6 +1078,8 @@ Global
{5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB} = {470FBAF9-E1F8-4F3E-8786-198A1C81C8A8}
{AC2857B4-103D-4D6D-9740-926EBF785042} = {470FBAF9-E1F8-4F3E-8786-198A1C81C8A8}
{470FBAF9-E1F8-4F3E-8786-198A1C81C8A8} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
+ {11491FD8-F921-48BF-880C-7FEA185B80A1} = {2F305555-C296-497E-AC20-5FA1B237996A}
+ {F40C3397-1834-4530-B2D9-8F8B8456BCDF} = {2F305555-C296-497E-AC20-5FA1B237996A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
diff --git a/installer/PowerToysSetup/Product.wxs b/installer/PowerToysSetup/Product.wxs
index 164a248b19..3790b05b13 100644
--- a/installer/PowerToysSetup/Product.wxs
+++ b/installer/PowerToysSetup/Product.wxs
@@ -511,6 +511,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -543,6 +556,10 @@
+
+
+
+
@@ -791,7 +808,7 @@
-
+
@@ -809,6 +826,11 @@
+
+
+
+
+
diff --git a/src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandler.csproj b/src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandler.csproj
index a49bb3b7b3..b6e6a59aa4 100644
--- a/src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandler.csproj
+++ b/src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandler.csproj
@@ -65,7 +65,7 @@
- $(MSBuildProgramFiles32)\Windows Kits\10\UnionMetadata\10.0.17134.0\Windows.winmd
+ $(MSBuildProgramFiles32)\Windows Kits\10\UnionMetadata\10.0.18362.0\Windows.winmd
true
diff --git a/src/modules/previewpane/PdfThumbnailProvider/PdfThumbnailProvider.cs b/src/modules/previewpane/PdfThumbnailProvider/PdfThumbnailProvider.cs
new file mode 100644
index 0000000000..c12152e673
--- /dev/null
+++ b/src/modules/previewpane/PdfThumbnailProvider/PdfThumbnailProvider.cs
@@ -0,0 +1,96 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+using System.Drawing;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using Common.ComInterlop;
+using Common.Utilities;
+using Windows.Data.Pdf;
+using Windows.Storage.Streams;
+
+namespace Microsoft.PowerToys.ThumbnailHandler.Pdf
+{
+ ///
+ /// PDF Thumbnail Provider.
+ ///
+ [Guid("BCC13D15-9720-4CC4-8371-EA74A274741E")]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComVisible(true)]
+ public class PdfThumbnailProvider : IInitializeWithStream, IThumbnailProvider
+ {
+ ///
+ /// Gets the stream object to access file.
+ ///
+ public IStream Stream { get; private set; }
+
+ ///
+ /// The maximum dimension (width or height) thumbnail we will generate.
+ ///
+ private const uint MaxThumbnailSize = 10000;
+
+ ///
+ public void Initialize(IStream pstream, uint grfMode)
+ {
+ // Ignore the grfMode always use read mode to access the file.
+ this.Stream = pstream;
+ }
+
+ ///
+ public void GetThumbnail(uint cx, out IntPtr phbmp, out WTS_ALPHATYPE pdwAlpha)
+ {
+ phbmp = IntPtr.Zero;
+ pdwAlpha = WTS_ALPHATYPE.WTSAT_UNKNOWN;
+
+ if (cx == 0 || cx > MaxThumbnailSize)
+ {
+ return;
+ }
+
+ using var dataStream = new ReadonlyStream(this.Stream as IStream);
+ using var memStream = new MemoryStream();
+
+ dataStream.CopyTo(memStream);
+ memStream.Position = 0;
+
+ // AsRandomAccessStream() extension method from System.Runtime.WindowsRuntime
+ var pdf = PdfDocument.LoadFromStreamAsync(memStream.AsRandomAccessStream()).GetAwaiter().GetResult();
+
+ if (pdf.PageCount > 0)
+ {
+ using var page = pdf.GetPage(0);
+
+ var image = PageToImage(page, cx);
+
+ using Bitmap thumbnail = new Bitmap(image);
+
+ phbmp = thumbnail.GetHbitmap();
+ pdwAlpha = WTS_ALPHATYPE.WTSAT_RGB;
+ }
+ }
+
+ ///
+ /// Transform the PdfPage to an Image.
+ ///
+ /// The page to transform to an Image.
+ /// The height of the page.
+ /// An object of type
+ private static Image PageToImage(PdfPage page, uint height)
+ {
+ Image imageOfPage;
+
+ using var stream = new InMemoryRandomAccessStream();
+
+ page.RenderToStreamAsync(stream, new PdfPageRenderOptions()
+ {
+ DestinationHeight = height,
+ }).GetAwaiter().GetResult();
+
+ imageOfPage = Image.FromStream(stream.AsStream());
+
+ return imageOfPage;
+ }
+ }
+}
diff --git a/src/modules/previewpane/PdfThumbnailProvider/PdfThumbnailProvider.csproj b/src/modules/previewpane/PdfThumbnailProvider/PdfThumbnailProvider.csproj
new file mode 100644
index 0000000000..dd026f4b54
--- /dev/null
+++ b/src/modules/previewpane/PdfThumbnailProvider/PdfThumbnailProvider.csproj
@@ -0,0 +1,71 @@
+
+
+ x64
+ true
+ {11491FD8-F921-48BF-880C-7FEA185B80A1}
+ Microsoft.PowerToys.ThumbnailHandler.Pdf
+ PdfThumbnailProvider
+ PdfThumbnailProvider
+ PowerToys PdfPreviewHandler
+ Microsoft Corporation
+ Copyright (C) 2020 Microsoft Corporation
+ PowerToys
+ netcoreapp3.1
+ true
+ true
+ Microsoft Corporation
+ PowerToys
+ en-US
+ PowerToys PdfPreviewHandler
+ Copyright (C) 2020 Microsoft Corporation
+ $(SolutionDir)$(Platform)\$(Configuration)\modules\FileExplorerPreview\
+ true
+ false
+ false
+ true
+
+
+
+
+
+
+ all
+
+
+ all
+
+
+ all
+
+
+ all
+
+
+ all
+
+
+ all
+
+
+
+
+
+
+
+
+
+
+
+
+ StyleCop.json
+
+
+
+
+
+ $(MSBuildProgramFiles32)\Windows Kits\10\UnionMetadata\10.0.18362.0\Windows.winmd
+ true
+
+
+
+
\ No newline at end of file
diff --git a/src/modules/previewpane/SvgThumbnailProvider/SvgThumbnailProvider.cs b/src/modules/previewpane/SvgThumbnailProvider/SvgThumbnailProvider.cs
index 73810bbc60..a3c9ff4005 100644
--- a/src/modules/previewpane/SvgThumbnailProvider/SvgThumbnailProvider.cs
+++ b/src/modules/previewpane/SvgThumbnailProvider/SvgThumbnailProvider.cs
@@ -12,7 +12,6 @@ using System.Runtime.InteropServices.ComTypes;
using System.Windows.Forms;
using Common.ComInterlop;
using Common.Utilities;
-using Microsoft.PowerToys.Telemetry;
using PreviewHandlerCommon;
namespace Microsoft.PowerToys.ThumbnailHandler.Svg
diff --git a/src/modules/previewpane/UnitTests-PdfThumbnailProvider/HelperFiles/sample.pdf b/src/modules/previewpane/UnitTests-PdfThumbnailProvider/HelperFiles/sample.pdf
new file mode 100644
index 0000000000..96304d9b21
Binary files /dev/null and b/src/modules/previewpane/UnitTests-PdfThumbnailProvider/HelperFiles/sample.pdf differ
diff --git a/src/modules/previewpane/UnitTests-PdfThumbnailProvider/PdfThumbnailProviderTests.cs b/src/modules/previewpane/UnitTests-PdfThumbnailProvider/PdfThumbnailProviderTests.cs
new file mode 100644
index 0000000000..482aa94dcd
--- /dev/null
+++ b/src/modules/previewpane/UnitTests-PdfThumbnailProvider/PdfThumbnailProviderTests.cs
@@ -0,0 +1,93 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Drawing;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+using Common.ComInterlop;
+using Microsoft.PowerToys.STATestExtension;
+using Microsoft.PowerToys.ThumbnailHandler.Pdf;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+
+namespace PdfThumbnailProviderUnitTests
+{
+ [STATestClass]
+ public class PdfThumbnailProviderTests
+ {
+ [TestMethod]
+ public void GetThumbnailValidStreamPDF()
+ {
+ // Act
+ var file = File.ReadAllBytes("HelperFiles/sample.pdf");
+
+ PdfThumbnailProvider provider = new PdfThumbnailProvider();
+
+ provider.Initialize(GetMockStream(file), 0);
+
+ provider.GetThumbnail(256, out IntPtr bitmap, out WTS_ALPHATYPE alphaType);
+
+ Assert.IsTrue(bitmap != IntPtr.Zero);
+ Assert.IsTrue(alphaType == WTS_ALPHATYPE.WTSAT_RGB);
+ }
+
+ [TestMethod]
+ public void GetThumbnailInValidSizePDF()
+ {
+ // Act
+ var file = File.ReadAllBytes("HelperFiles/sample.pdf");
+
+ PdfThumbnailProvider provider = new PdfThumbnailProvider();
+
+ provider.Initialize(GetMockStream(file), 0);
+
+ provider.GetThumbnail(0, out IntPtr bitmap, out WTS_ALPHATYPE alphaType);
+
+ Assert.IsTrue(bitmap == IntPtr.Zero);
+ Assert.IsTrue(alphaType == WTS_ALPHATYPE.WTSAT_UNKNOWN);
+ }
+
+ [TestMethod]
+ public void GetThumbnailToBigPDF()
+ {
+ // Act
+ var file = File.ReadAllBytes("HelperFiles/sample.pdf");
+
+ PdfThumbnailProvider provider = new PdfThumbnailProvider();
+
+ provider.Initialize(GetMockStream(file), 0);
+
+ provider.GetThumbnail(10001, out IntPtr bitmap, out WTS_ALPHATYPE alphaType);
+
+ Assert.IsTrue(bitmap == IntPtr.Zero);
+ Assert.IsTrue(alphaType == WTS_ALPHATYPE.WTSAT_UNKNOWN);
+ }
+
+ private static IStream GetMockStream(byte[] sourceArray)
+ {
+ var streamMock = new Mock();
+ var firstCall = true;
+ streamMock
+ .Setup(x => x.Read(It.IsAny(), It.IsAny(), It.IsAny()))
+ .Callback((buffer, countToRead, bytesReadPtr) =>
+ {
+ if (firstCall)
+ {
+ Array.Copy(sourceArray, 0, buffer, 0, sourceArray.Length);
+ Marshal.WriteInt32(bytesReadPtr, sourceArray.Length);
+ firstCall = false;
+ }
+ else
+ {
+ Marshal.WriteInt32(bytesReadPtr, 0);
+ }
+ });
+
+ return streamMock.Object;
+ }
+ }
+}
diff --git a/src/modules/previewpane/UnitTests-PdfThumbnailProvider/UnitTests-PdfThumbnailProvider.csproj b/src/modules/previewpane/UnitTests-PdfThumbnailProvider/UnitTests-PdfThumbnailProvider.csproj
new file mode 100644
index 0000000000..c6360e675a
--- /dev/null
+++ b/src/modules/previewpane/UnitTests-PdfThumbnailProvider/UnitTests-PdfThumbnailProvider.csproj
@@ -0,0 +1,78 @@
+
+
+ x64
+ UnitTests-PdfThumbnailProvider
+ PowerToys UnitTests-PdfThumbnailProvider
+ Microsoft Corporation
+ Copyright (C) 2021 Microsoft Corporation
+ PowerToys
+ UnitTests-PdfThumbnailProvider
+ Microsoft Corporation
+ PowerToys
+ en-US
+ PowerToys UnitTests-PdfThumbnailProvider
+ Copyright (C) 2021 Microsoft Corporation
+
+
+
+ {F40C3397-1834-4530-B2D9-8F8B8456BCDF}
+ PdfThumbnailProviderUnitTests
+ netcoreapp3.1
+ {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+ $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
+ False
+ UnitTest
+
+
+
+
+
+
+
+
+
+
+
+ all
+
+
+ all
+
+
+ all
+
+
+ all
+
+
+ all
+
+
+
+
+
+ all
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ StyleCop.json
+
+
+
+
+ Always
+
+
+
\ No newline at end of file
diff --git a/src/modules/previewpane/UnitTests-PdfThumbnailProvider/app.config b/src/modules/previewpane/UnitTests-PdfThumbnailProvider/app.config
new file mode 100644
index 0000000000..74312e4551
--- /dev/null
+++ b/src/modules/previewpane/UnitTests-PdfThumbnailProvider/app.config
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/modules/previewpane/powerpreview/CLSID.h b/src/modules/previewpane/powerpreview/CLSID.h
index 104e2d8ef8..ce6e5bc5dc 100644
--- a/src/modules/previewpane/powerpreview/CLSID.h
+++ b/src/modules/previewpane/powerpreview/CLSID.h
@@ -28,6 +28,9 @@ const CLSID CLSID_SHIMActivateSvgThumbnailProvider = { 0x9C723B8C, 0x4F5C, 0x414
// 36B27788-A8BB-4698-A756-DF9F11F64F84
const CLSID CLSID_SvgThumbnailProvider = { 0x36B27788, 0xA8BB, 0x4698, { 0xA7, 0x56, 0xDF, 0x9F, 0x11, 0xF6, 0x4F, 0x84 } };
+// BCC13D15-9720-4CC4-8371-EA74A274741E
+const GUID CLSID_PdfThumbnailProvider = { 0xbcc13d15, 0x9720, 0x4cc4, { 0x83, 0x71, 0xea, 0x74, 0xa2, 0x74, 0x74, 0x1e } };
+
// Pairs of NativeClsid vs ManagedClsid used for preview handlers.
const std::vector> NativeToManagedClsid({
{ CLSID_SHIMActivateMdPreviewHandler, CLSID_MdPreviewHandler },
diff --git a/src/modules/previewpane/powerpreview/Resources.resx b/src/modules/previewpane/powerpreview/Resources.resx
index 7af9b5effe..203a0bfc3f 100644
--- a/src/modules/previewpane/powerpreview/Resources.resx
+++ b/src/modules/previewpane/powerpreview/Resources.resx
@@ -174,4 +174,7 @@
PDF Previewer
+
+ Pdf Thumbnail Provider
+
\ No newline at end of file
diff --git a/src/modules/previewpane/powerpreview/powerpreview.cpp b/src/modules/previewpane/powerpreview/powerpreview.cpp
index 27e6a482f6..8bec06e0a3 100644
--- a/src/modules/previewpane/powerpreview/powerpreview.cpp
+++ b/src/modules/previewpane/powerpreview/powerpreview.cpp
@@ -50,6 +50,16 @@ PowerPreviewModule::PowerPreviewModule() :
std::make_unique(),
L".svg\\shellex\\{E357FCCD-A995-4576-B01F-234630154E96}"));
+ // PDF
+ m_fileExplorerModules.emplace_back(std::make_unique(
+ true,
+ L"pdf-thumbnail-toggle-setting",
+ GET_RESOURCE_STRING(IDS_PDF_THUMBNAIL_PROVIDER_SETTINGS_DESCRIPTION),
+ L"{BCC13D15-9720-4CC4-8371-EA74A274741E}",
+ L"Pdf Thumbnail Provider",
+ std::make_unique(),
+ L".pdf\\shellex\\{E357FCCD-A995-4576-B01F-234630154E96}"));
+
// Initialize the toggle states for each module.
init_settings();
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/PowerPreviewProperties.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/PowerPreviewProperties.cs
index 8a5b5f7c83..a1607b2c86 100644
--- a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/PowerPreviewProperties.cs
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/PowerPreviewProperties.cs
@@ -80,6 +80,23 @@ namespace Microsoft.PowerToys.Settings.UI.Library
}
}
+ private bool enablePdfThumbnail = true;
+
+ [JsonPropertyName("pdf-thumbnail-toggle-setting")]
+ [JsonConverter(typeof(BoolPropertyJsonConverter))]
+ public bool EnablePdfThumbnail
+ {
+ get => enablePdfThumbnail;
+ set
+ {
+ if (value != enablePdfThumbnail)
+ {
+ LogTelemetryEvent(value);
+ enablePdfThumbnail = value;
+ }
+ }
+ }
+
public PowerPreviewProperties()
{
}
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/PowerPreviewViewModel.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/PowerPreviewViewModel.cs
index ea1f22ea2a..71d7112cdb 100644
--- a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/PowerPreviewViewModel.cs
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/PowerPreviewViewModel.cs
@@ -50,12 +50,14 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
_svgThumbnailIsEnabled = Settings.Properties.EnableSvgThumbnail;
_mdRenderIsEnabled = Settings.Properties.EnableMdPreview;
_pdfRenderIsEnabled = Settings.Properties.EnablePdfPreview;
+ _pdfThumbnailIsEnabled = Settings.Properties.EnablePdfThumbnail;
}
private bool _svgRenderIsEnabled;
private bool _mdRenderIsEnabled;
private bool _pdfRenderIsEnabled;
private bool _svgThumbnailIsEnabled;
+ private bool _pdfThumbnailIsEnabled;
public bool SVGRenderIsEnabled
{
@@ -129,6 +131,24 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
}
}
+ public bool PDFThumbnailIsEnabled
+ {
+ get
+ {
+ return _pdfThumbnailIsEnabled;
+ }
+
+ set
+ {
+ if (value != _pdfThumbnailIsEnabled)
+ {
+ _pdfThumbnailIsEnabled = value;
+ Settings.Properties.EnablePdfThumbnail = value;
+ RaisePropertyChanged();
+ }
+ }
+ }
+
public string GetSettingsSubPath()
{
return _settingsConfigFileFolder + "\\" + ModuleName;
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerPreview.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerPreview.cs
index 878069c8a9..7fc7cba302 100644
--- a/src/settings-ui/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerPreview.cs
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerPreview.cs
@@ -60,6 +60,7 @@ namespace ViewModelTests
Assert.AreEqual(originalSettings.Properties.EnablePdfPreview, viewModel.PDFRenderIsEnabled);
Assert.AreEqual(originalSettings.Properties.EnableSvgPreview, viewModel.SVGRenderIsEnabled);
Assert.AreEqual(originalSettings.Properties.EnableSvgThumbnail, viewModel.SVGThumbnailIsEnabled);
+ Assert.AreEqual(originalSettings.Properties.EnablePdfThumbnail, viewModel.PDFThumbnailIsEnabled);
// Verify that the stub file was used
var expectedCallCount = 2; // once via the view model, and once by the test (GetSettings)
@@ -102,6 +103,24 @@ namespace ViewModelTests
viewModel.SVGThumbnailIsEnabled = true;
}
+ [TestMethod]
+ public void PDFThumbnailIsEnabledShouldPrevHandlerWhenSuccessful()
+ {
+ // Assert
+ Func sendMockIPCConfigMSG = msg =>
+ {
+ SndModuleSettings snd = JsonSerializer.Deserialize>(msg);
+ Assert.IsTrue(snd.PowertoysSetting.FileExplorerPreviewSettings.Properties.EnablePdfThumbnail);
+ return 0;
+ };
+
+ // arrange
+ PowerPreviewViewModel viewModel = new PowerPreviewViewModel(SettingsRepository.GetInstance(mockPowerPreviewSettingsUtils.Object), SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), sendMockIPCConfigMSG, PowerPreviewSettings.ModuleName);
+
+ // act
+ viewModel.PDFThumbnailIsEnabled = true;
+ }
+
[TestMethod]
public void MDRenderIsEnabledShouldPrevHandlerWhenSuccessful()
{
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw
index d51f5eba1a..09e1f3aba8 100644
--- a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw
@@ -586,6 +586,10 @@
Enable SVG (.svg) thumbnails
Do you want this feature on / off
+
+ Enable PDF (.pdf) thumbnails
+ Do you want this feature on / off
+
These settings allow you to manage your Windows File Explorer custom preview handlers.
@@ -1194,7 +1198,7 @@ Made with 💗 by Microsoft and the PowerToys community.
FancyZones is a window manager that makes it easy to create complex window layouts and quickly position windows into those layouts.
- PowerToys introduces add-ons to the Window’s File Explorer that will currently enable Markdown files (.md) and SVG icons (.svg) to be viewed in the preview pane.
+ PowerToys introduces add-ons to the Window’s File Explorer that will currently enable Markdown files (.md), PDF files (.pdf) and SVG icons (.svg) to be viewed in the preview pane.
Image Resizer is a Windows shell extension for simple bulk image-resizing.
@@ -1245,7 +1249,7 @@ Take a moment to preview the various utilities listed or view our comprehensive
Open File Explorer, **select the View tab** in the File Explorer ribbon, then **select Preview Pane**.
-From there, simply click on a Markdown file or SVG icon in the File Explorer and observe the content on the preview pane!
+From there, simply click on a Markdown file, PDF file or SVG icon in the File Explorer and observe the content on the preview pane!
How to create mappings
diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/PowerPreviewPage.xaml b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/PowerPreviewPage.xaml
index 5693f88554..04e7411a5b 100644
--- a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/PowerPreviewPage.xaml
+++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/PowerPreviewPage.xaml
@@ -67,6 +67,13 @@
IsEnabled="{Binding Mode=OneWay, Path=IsElevated}"/>
+
+
+
+
+
+
diff --git a/tools/BugReportTool/BugReportTool/RegistryUtils.cpp b/tools/BugReportTool/BugReportTool/RegistryUtils.cpp
index 6acad09576..b205bb0ab4 100644
--- a/tools/BugReportTool/BugReportTool/RegistryUtils.cpp
+++ b/tools/BugReportTool/BugReportTool/RegistryUtils.cpp
@@ -13,6 +13,8 @@ namespace
{ HKEY_CLASSES_ROOT, L"CLSID\\{36B27788-A8BB-4698-A756-DF9F11F64F84}" },
{ HKEY_CLASSES_ROOT, L"CLSID\\{45769bcc-e8fd-42d0-947e-02beef77a1f5}" },
{ HKEY_CLASSES_ROOT, L"AppID\\{CF142243-F059-45AF-8842-DBBE9783DB14}" },
+ { HKEY_CLASSES_ROOT, L"CLSID\\{07665729-6243-4746-95b7-79579308d1b2}" },
+ { HKEY_CLASSES_ROOT, L"CLSID\\{BCC13D15-9720-4CC4-8371-EA74A274741E}" },
{ HKEY_CLASSES_ROOT, L"CLSID\\{51B4D7E5-7568-4234-B4BB-47FB3C016A69}\\InprocServer32" },
{ HKEY_CLASSES_ROOT, L"CLSID\\{0440049F-D1DC-4E46-B27B-98393D79486B}" },
{ HKEY_CLASSES_ROOT, L"AllFileSystemObjects\\ShellEx\\ContextMenuHandlers\\PowerRenameExt" },
@@ -20,7 +22,8 @@ namespace
{ HKEY_CLASSES_ROOT, L".svg\\shellex\\{8895b1c6-b41f-4c1c-a562-0d564250836f}" },
{ HKEY_CLASSES_ROOT, L".svg\\shellex\\{E357FCCD-A995-4576-B01F-234630154E96}" },
{ HKEY_CLASSES_ROOT, L".md\\shellex\\{8895b1c6-b41f-4c1c-a562-0d564250836f}" },
- { HKEY_CLASSES_ROOT, L".pdf\\shellex\\{8895b1c6-b41f-4c1c-a562-0d564250836f}" }
+ { HKEY_CLASSES_ROOT, L".pdf\\shellex\\{8895b1c6-b41f-4c1c-a562-0d564250836f}" },
+ { HKEY_CLASSES_ROOT, L".pdf\\shellex\\{E357FCCD-A995-4576-B01F-234630154E96}" }
};
vector> registryValues = {