mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-02-23 19:49:43 +01:00
[Indexer] File icons (#343)
- [x] **Closes:** #316 
This commit is contained in:
2
.github/actions/spell-check/expect.txt
vendored
2
.github/actions/spell-check/expect.txt
vendored
@@ -1541,6 +1541,8 @@ SHFILEOPSTRUCT
|
||||
SHGDN
|
||||
SHGDNF
|
||||
SHGFI
|
||||
SHGFIICON
|
||||
SHGFILARGEICON
|
||||
shinfo
|
||||
shlwapi
|
||||
SHNAMEMAPPING
|
||||
|
||||
@@ -12,6 +12,7 @@ using Microsoft.CmdPal.Ext.Indexer.Indexer;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Properties;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Windows.Storage.Streams;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Indexer;
|
||||
|
||||
@@ -90,13 +91,21 @@ internal sealed partial class IndexerPage : DynamicListPage, IDisposable
|
||||
|
||||
while (!_searchQuery.SearchResults.IsEmpty && _searchQuery.SearchResults.TryDequeue(out result) && ++index <= limit)
|
||||
{
|
||||
IconInfo icon = null;
|
||||
var stream = ThumbnailHelper.GetThumbnail(result.LaunchUri).Result;
|
||||
if (stream != null)
|
||||
{
|
||||
var data = new IconData(RandomAccessStreamReference.CreateFromStream(stream));
|
||||
icon = new IconInfo(data, data);
|
||||
}
|
||||
|
||||
_indexerListItems.Add(new IndexerListItem(new IndexerItem
|
||||
{
|
||||
FileName = result.ItemDisplayName,
|
||||
FullPath = result.LaunchUri,
|
||||
})
|
||||
{
|
||||
Icon = new IconInfo(result.IsFolder ? "\uE838" : "\uE8E5"),
|
||||
Icon = icon,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// 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.
|
||||
|
||||
@@ -28,7 +28,6 @@ public sealed class IconCacheService(DispatcherQueue dispatcherQueue)
|
||||
if (!string.IsNullOrEmpty(icon.Icon))
|
||||
{
|
||||
var source = IconPathConverter.IconSourceMUX(icon.Icon, false);
|
||||
|
||||
return source;
|
||||
}
|
||||
else if (icon.Data != null)
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" />
|
||||
<PackageReference Include="Microsoft.Web.WebView2" />
|
||||
<PackageReference Include="System.Drawing.Common" />
|
||||
<!-- This line forces the WebView2 version used by Windows App SDK to be the one we expect from Directory.Packages.props . -->
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// 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.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
internal sealed class NativeMethods
|
||||
{
|
||||
[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
|
||||
internal static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct SHFILEINFO
|
||||
{
|
||||
#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter
|
||||
public IntPtr hIcon;
|
||||
public int iIcon;
|
||||
public uint dwAttributes;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
|
||||
public string szDisplayName;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
|
||||
public string szTypeName;
|
||||
#pragma warning restore SA1307 // Accessible fields should begin with upper-case letter
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// 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.Drawing;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.FileProperties;
|
||||
using Windows.Storage.Streams;
|
||||
|
||||
namespace Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
public class ThumbnailHelper
|
||||
{
|
||||
private static readonly string[] ImageExtensions =
|
||||
[
|
||||
".png",
|
||||
".jpg",
|
||||
".jpeg",
|
||||
".gif",
|
||||
".bmp",
|
||||
".tiff",
|
||||
".ico",
|
||||
];
|
||||
|
||||
public static async Task<IRandomAccessStream> GetThumbnail(string path)
|
||||
{
|
||||
var extension = Path.GetExtension(path).ToLower(CultureInfo.InvariantCulture);
|
||||
if (ImageExtensions.Contains(extension))
|
||||
{
|
||||
try
|
||||
{
|
||||
return await GetImageThumbnailAsync(path);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return await Task.FromResult(GetFileIconStream(path));
|
||||
}
|
||||
|
||||
private const uint SHGFIICON = 0x000000100;
|
||||
private const uint SHGFILARGEICON = 0x000000000;
|
||||
|
||||
private static IRandomAccessStream GetFileIconStream(string filePath)
|
||||
{
|
||||
var shinfo = default(NativeMethods.SHFILEINFO);
|
||||
NativeMethods.SHGetFileInfo(filePath, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), SHGFIICON | SHGFILARGEICON);
|
||||
|
||||
using var icon = Icon.FromHandle(shinfo.hIcon);
|
||||
var stream = new InMemoryRandomAccessStream();
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
icon.ToBitmap().Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png);
|
||||
memoryStream.Position = 0;
|
||||
|
||||
using var outputStream = stream.GetOutputStreamAt(0);
|
||||
using var dataWriter = new DataWriter(outputStream);
|
||||
dataWriter.WriteBytes(memoryStream.ToArray());
|
||||
dataWriter.StoreAsync().GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
private static async Task<IRandomAccessStream> GetImageThumbnailAsync(string filePath)
|
||||
{
|
||||
var file = await StorageFile.GetFileFromPathAsync(filePath);
|
||||
var thumbnail = await file.GetThumbnailAsync(ThumbnailMode.PicturesView);
|
||||
return thumbnail;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user