mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-03-31 10:29:52 +08:00
184 lines
6.0 KiB
C#
184 lines
6.0 KiB
C#
using MicaSetup.Natives;
|
|
using System;
|
|
using System.Drawing;
|
|
using System.Runtime.InteropServices;
|
|
using System.Windows.Interop;
|
|
using System.Windows.Media.Imaging;
|
|
|
|
namespace MicaSetup.Shell.Dialogs;
|
|
|
|
public class ShellThumbnail
|
|
{
|
|
private readonly IShellItem shellItemNative;
|
|
|
|
private System.Windows.Size currentSize = new System.Windows.Size(256, 256);
|
|
|
|
private ShellThumbnailFormatOption formatOption = ShellThumbnailFormatOption.Default;
|
|
|
|
internal ShellThumbnail(ShellObject shellObject)
|
|
{
|
|
if (shellObject == null! || shellObject.NativeShellItem == null)
|
|
{
|
|
throw new ArgumentNullException("shellObject");
|
|
}
|
|
|
|
shellItemNative = shellObject.NativeShellItem;
|
|
}
|
|
|
|
public bool AllowBiggerSize { get; set; }
|
|
|
|
public BitmapSource BitmapSource => GetBitmapSource(CurrentSize);
|
|
|
|
public System.Windows.Size CurrentSize
|
|
{
|
|
get => currentSize;
|
|
set
|
|
{
|
|
if (value.Height == 0 || value.Width == 0)
|
|
{
|
|
throw new System.ArgumentOutOfRangeException("value", LocalizedMessages.ShellThumbnailSizeCannotBe0);
|
|
}
|
|
|
|
var size = (FormatOption == ShellThumbnailFormatOption.IconOnly) ?
|
|
DefaultIconSize.Maximum : DefaultThumbnailSize.Maximum;
|
|
|
|
if (value.Height > size.Height || value.Width > size.Width)
|
|
{
|
|
throw new System.ArgumentOutOfRangeException("value",
|
|
string.Format(System.Globalization.CultureInfo.InvariantCulture,
|
|
LocalizedMessages.ShellThumbnailCurrentSizeRange, size.ToString()));
|
|
}
|
|
|
|
currentSize = value;
|
|
}
|
|
}
|
|
|
|
public Bitmap ExtraLargeBitmap => GetBitmap(DefaultIconSize.ExtraLarge, DefaultThumbnailSize.ExtraLarge);
|
|
|
|
public BitmapSource ExtraLargeBitmapSource => GetBitmapSource(DefaultIconSize.ExtraLarge, DefaultThumbnailSize.ExtraLarge);
|
|
|
|
public Icon ExtraLargeIcon => Icon.FromHandle(ExtraLargeBitmap.GetHicon());
|
|
|
|
public ShellThumbnailFormatOption FormatOption
|
|
{
|
|
get => formatOption;
|
|
set
|
|
{
|
|
formatOption = value;
|
|
|
|
if (FormatOption == ShellThumbnailFormatOption.IconOnly
|
|
&& (CurrentSize.Height > DefaultIconSize.Maximum.Height || CurrentSize.Width > DefaultIconSize.Maximum.Width))
|
|
{
|
|
CurrentSize = DefaultIconSize.Maximum;
|
|
}
|
|
}
|
|
}
|
|
|
|
public Icon Icon => Icon.FromHandle(Bitmap.GetHicon());
|
|
|
|
public Bitmap LargeBitmap => GetBitmap(DefaultIconSize.Large, DefaultThumbnailSize.Large);
|
|
|
|
public BitmapSource LargeBitmapSource => GetBitmapSource(DefaultIconSize.Large, DefaultThumbnailSize.Large);
|
|
|
|
public Icon LargeIcon => Icon.FromHandle(LargeBitmap.GetHicon());
|
|
|
|
public Bitmap MediumBitmap => GetBitmap(DefaultIconSize.Medium, DefaultThumbnailSize.Medium);
|
|
|
|
public BitmapSource MediumBitmapSource => GetBitmapSource(DefaultIconSize.Medium, DefaultThumbnailSize.Medium);
|
|
|
|
public Icon MediumIcon => Icon.FromHandle(MediumBitmap.GetHicon());
|
|
|
|
public ShellThumbnailRetrievalOption RetrievalOption { get; set; }
|
|
|
|
public Bitmap SmallBitmap => GetBitmap(DefaultIconSize.Small, DefaultThumbnailSize.Small);
|
|
|
|
public BitmapSource SmallBitmapSource => GetBitmapSource(DefaultIconSize.Small, DefaultThumbnailSize.Small);
|
|
|
|
public Icon SmallIcon => Icon.FromHandle(SmallBitmap.GetHicon());
|
|
|
|
public Bitmap Bitmap => GetBitmap(CurrentSize);
|
|
|
|
private SIIGBF CalculateFlags()
|
|
{
|
|
SIIGBF flags = 0x0000;
|
|
|
|
if (AllowBiggerSize)
|
|
{
|
|
flags |= SIIGBF.BiggerSizeOk;
|
|
}
|
|
|
|
if (RetrievalOption == ShellThumbnailRetrievalOption.CacheOnly)
|
|
{
|
|
flags |= SIIGBF.InCacheOnly;
|
|
}
|
|
else if (RetrievalOption == ShellThumbnailRetrievalOption.MemoryOnly)
|
|
{
|
|
flags |= SIIGBF.MemoryOnly;
|
|
}
|
|
|
|
if (FormatOption == ShellThumbnailFormatOption.IconOnly)
|
|
{
|
|
flags |= SIIGBF.IconOnly;
|
|
}
|
|
else if (FormatOption == ShellThumbnailFormatOption.ThumbnailOnly)
|
|
{
|
|
flags |= SIIGBF.ThumbnailOnly;
|
|
}
|
|
|
|
return flags;
|
|
}
|
|
|
|
private Bitmap GetBitmap(System.Windows.Size iconOnlySize, System.Windows.Size thumbnailSize) => GetBitmap(FormatOption == ShellThumbnailFormatOption.IconOnly ? iconOnlySize : thumbnailSize);
|
|
|
|
private Bitmap GetBitmap(System.Windows.Size size)
|
|
{
|
|
var hBitmap = GetHBitmap(size);
|
|
|
|
var returnValue = Bitmap.FromHbitmap(hBitmap);
|
|
|
|
Gdi32.DeleteObject(hBitmap);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
private BitmapSource GetBitmapSource(System.Windows.Size iconOnlySize, System.Windows.Size thumbnailSize) => GetBitmapSource(FormatOption == ShellThumbnailFormatOption.IconOnly ? iconOnlySize : thumbnailSize);
|
|
|
|
private BitmapSource GetBitmapSource(System.Windows.Size size)
|
|
{
|
|
var hBitmap = GetHBitmap(size);
|
|
|
|
var returnValue = Imaging.CreateBitmapSourceFromHBitmap(
|
|
hBitmap,
|
|
IntPtr.Zero,
|
|
System.Windows.Int32Rect.Empty,
|
|
BitmapSizeOptions.FromEmptyOptions());
|
|
|
|
Gdi32.DeleteObject(hBitmap);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
private nint GetHBitmap(System.Windows.Size size)
|
|
{
|
|
var nativeSIZE = new SIZE()
|
|
{
|
|
Width = Convert.ToInt32(size.Width),
|
|
Height = Convert.ToInt32(size.Height)
|
|
};
|
|
|
|
var hr = ((IShellItemImageFactory)shellItemNative).GetImage(nativeSIZE, CalculateFlags(), out nint hbitmap);
|
|
|
|
if (hr == HResult.Ok) { return hbitmap; }
|
|
else if ((uint)hr == 0x8004B200 && FormatOption == ShellThumbnailFormatOption.ThumbnailOnly)
|
|
{
|
|
throw new InvalidOperationException(LocalizedMessages.ShellThumbnailDoesNotHaveThumbnail, Marshal.GetExceptionForHR((int)hr));
|
|
}
|
|
else if ((uint)hr == 0x80040154)
|
|
{
|
|
throw new NotSupportedException(LocalizedMessages.ShellThumbnailNoHandler, Marshal.GetExceptionForHR((int)hr));
|
|
}
|
|
|
|
throw new ShellException(hr);
|
|
}
|
|
}
|