mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 11:48:06 +01:00
[Peek] show thumbnail and fallback to icon on unsupported files (#27979)
This commit is contained in:
@@ -17,12 +17,23 @@ namespace Peek.FilePreviewer.Previewers.Helpers
|
|||||||
{
|
{
|
||||||
public static async Task<BitmapSource> GetBitmapFromHBitmapAsync(IntPtr hbitmap, bool isSupportingTransparency, CancellationToken cancellationToken)
|
public static async Task<BitmapSource> GetBitmapFromHBitmapAsync(IntPtr hbitmap, bool isSupportingTransparency, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
Bitmap? bitmap = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var bitmap = Image.FromHbitmap(hbitmap);
|
bitmap = Image.FromHbitmap(hbitmap);
|
||||||
if (isSupportingTransparency)
|
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
if (isSupportingTransparency && bitmap.PixelFormat == PixelFormat.Format32bppRgb)
|
||||||
{
|
{
|
||||||
bitmap.MakeTransparent();
|
var bitmapRectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
|
||||||
|
var bitmapData = bitmap.LockBits(bitmapRectangle, ImageLockMode.ReadOnly, bitmap.PixelFormat);
|
||||||
|
|
||||||
|
var transparentBitmap = new Bitmap(bitmapData.Width, bitmapData.Height, bitmapData.Stride, PixelFormat.Format32bppArgb, bitmapData.Scan0);
|
||||||
|
|
||||||
|
bitmap.Dispose();
|
||||||
|
bitmap = transparentBitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
var bitmapImage = new BitmapImage();
|
var bitmapImage = new BitmapImage();
|
||||||
@@ -41,6 +52,8 @@ namespace Peek.FilePreviewer.Previewers.Helpers
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
bitmap?.Dispose();
|
||||||
|
|
||||||
// delete HBitmap to avoid memory leaks
|
// delete HBitmap to avoid memory leaks
|
||||||
NativeMethods.DeleteObject(hbitmap);
|
NativeMethods.DeleteObject(hbitmap);
|
||||||
}
|
}
|
||||||
@@ -50,8 +63,8 @@ namespace Peek.FilePreviewer.Previewers.Helpers
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var icon = (Icon)Icon.FromHandle(hicon).Clone();
|
using var icon = (Icon)Icon.FromHandle(hicon).Clone();
|
||||||
var bitmap = icon.ToBitmap();
|
using var bitmap = icon.ToBitmap();
|
||||||
|
|
||||||
var bitmapImage = new BitmapImage();
|
var bitmapImage = new BitmapImage();
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ using System.Runtime.InteropServices;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.UI.Xaml.Media;
|
using Microsoft.UI.Xaml.Media;
|
||||||
using Microsoft.UI.Xaml.Media.Imaging;
|
|
||||||
using Peek.Common;
|
using Peek.Common;
|
||||||
using Peek.Common.Extensions;
|
|
||||||
using Peek.Common.Models;
|
using Peek.Common.Models;
|
||||||
|
|
||||||
namespace Peek.FilePreviewer.Previewers.Helpers
|
namespace Peek.FilePreviewer.Previewers.Helpers
|
||||||
@@ -20,6 +18,16 @@ namespace Peek.FilePreviewer.Previewers.Helpers
|
|||||||
private const string IShellItem2Guid = "7E9FB0D3-919F-4307-AB2E-9B1860310C93";
|
private const string IShellItem2Guid = "7E9FB0D3-919F-4307-AB2E-9B1860310C93";
|
||||||
|
|
||||||
public static async Task<ImageSource?> GetIconAsync(string fileName, CancellationToken cancellationToken)
|
public static async Task<ImageSource?> GetIconAsync(string fileName, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return await GetImageAsync(fileName, ThumbnailOptions.BiggerSizeOk | ThumbnailOptions.IconOnly, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<ImageSource?> GetThumbnailAsync(string fileName, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return await GetImageAsync(fileName, ThumbnailOptions.ThumbnailOnly, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<ImageSource?> GetImageAsync(string fileName, ThumbnailOptions options, bool isSupportingTransparency, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(fileName))
|
if (string.IsNullOrEmpty(fileName))
|
||||||
{
|
{
|
||||||
@@ -28,6 +36,7 @@ namespace Peek.FilePreviewer.Previewers.Helpers
|
|||||||
|
|
||||||
ImageSource? imageSource = null;
|
ImageSource? imageSource = null;
|
||||||
IShellItem? nativeShellItem = null;
|
IShellItem? nativeShellItem = null;
|
||||||
|
IntPtr hbitmap = IntPtr.Zero;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -40,16 +49,22 @@ namespace Peek.FilePreviewer.Previewers.Helpers
|
|||||||
}
|
}
|
||||||
|
|
||||||
NativeSize large = new NativeSize { Width = 256, Height = 256 };
|
NativeSize large = new NativeSize { Width = 256, Height = 256 };
|
||||||
var options = ThumbnailOptions.BiggerSizeOk | ThumbnailOptions.IconOnly;
|
|
||||||
|
|
||||||
HResult hr = ((IShellItemImageFactory)nativeShellItem).GetImage(large, options, out IntPtr hbitmap);
|
HResult hr = ((IShellItemImageFactory)nativeShellItem).GetImage(large, options, out hbitmap);
|
||||||
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
imageSource = hr == HResult.Ok ? await BitmapHelper.GetBitmapFromHBitmapAsync(hbitmap, true, cancellationToken) : null;
|
imageSource = hr == HResult.Ok ? await BitmapHelper.GetBitmapFromHBitmapAsync(hbitmap, isSupportingTransparency, cancellationToken) : null;
|
||||||
|
|
||||||
|
hbitmap = IntPtr.Zero;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
if (hbitmap != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
NativeMethods.DeleteObject(hbitmap);
|
||||||
|
}
|
||||||
|
|
||||||
if (nativeShellItem != null)
|
if (nativeShellItem != null)
|
||||||
{
|
{
|
||||||
Marshal.ReleaseComObject(nativeShellItem);
|
Marshal.ReleaseComObject(nativeShellItem);
|
||||||
|
|||||||
@@ -4,11 +4,9 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using Microsoft.PowerToys.Settings.UI.Library;
|
|
||||||
using Microsoft.UI.Dispatching;
|
using Microsoft.UI.Dispatching;
|
||||||
using Microsoft.UI.Xaml.Media.Imaging;
|
using Microsoft.UI.Xaml.Media.Imaging;
|
||||||
using Peek.Common.Extensions;
|
using Peek.Common.Extensions;
|
||||||
@@ -76,7 +74,7 @@ namespace Peek.FilePreviewer.Previewers
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
State = PreviewState.Loaded;
|
State = PreviewState.Loaded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task CopyAsync()
|
public async Task CopyAsync()
|
||||||
@@ -99,7 +97,8 @@ namespace Peek.FilePreviewer.Previewers
|
|||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var iconBitmap = await IconHelper.GetIconAsync(Item.Path, cancellationToken);
|
var iconBitmap = await IconHelper.GetThumbnailAsync(Item.Path, cancellationToken)
|
||||||
|
?? await IconHelper.GetIconAsync(Item.Path, cancellationToken);
|
||||||
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user