101 lines
3.0 KiB
C#
101 lines
3.0 KiB
C#
using System;
|
|
using System.Runtime.InteropServices;
|
|
using WinUIEx;
|
|
|
|
namespace Wino.Mail.WinUI.Helpers;
|
|
|
|
internal static class WindowAppUserModelIdHelper
|
|
{
|
|
private static readonly Guid PropertyStoreGuid = new("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99");
|
|
private static readonly PropertyKey AppUserModelIdPropertyKey = new(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 5);
|
|
|
|
public static void TrySet(WindowEx window, string appUserModelId)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(window);
|
|
|
|
if (string.IsNullOrWhiteSpace(appUserModelId))
|
|
return;
|
|
|
|
try
|
|
{
|
|
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(window);
|
|
if (hwnd == IntPtr.Zero)
|
|
return;
|
|
|
|
var propertyStoreGuid = PropertyStoreGuid;
|
|
var appUserModelIdPropertyKey = AppUserModelIdPropertyKey;
|
|
var hr = SHGetPropertyStoreForWindow(hwnd, ref propertyStoreGuid, out var propertyStore);
|
|
if (hr < 0 || propertyStore == null)
|
|
return;
|
|
|
|
using (propertyStore)
|
|
{
|
|
using var value = PropVariant.FromString(appUserModelId);
|
|
propertyStore.SetValue(ref appUserModelIdPropertyKey, value);
|
|
propertyStore.Commit();
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// Best effort only. Some Windows builds may keep the original taskbar identity.
|
|
}
|
|
}
|
|
|
|
[DllImport("shell32.dll")]
|
|
private static extern int SHGetPropertyStoreForWindow(
|
|
IntPtr hwnd,
|
|
ref Guid riid,
|
|
[MarshalAs(UnmanagedType.Interface)] out IPropertyStore propertyStore);
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
|
private readonly struct PropertyKey(Guid fmtid, uint pid)
|
|
{
|
|
public Guid FormatId { get; } = fmtid;
|
|
public uint PropertyId { get; } = pid;
|
|
}
|
|
|
|
[ComImport]
|
|
[Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
|
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
private interface IPropertyStore : IDisposable
|
|
{
|
|
uint GetCount();
|
|
void GetAt(uint propertyIndex, out PropertyKey key);
|
|
void GetValue(ref PropertyKey key, out PropVariant pv);
|
|
void SetValue(ref PropertyKey key, PropVariant pv);
|
|
void Commit();
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Explicit)]
|
|
private sealed class PropVariant : IDisposable
|
|
{
|
|
[FieldOffset(0)]
|
|
private ushort _valueType;
|
|
|
|
[FieldOffset(8)]
|
|
private IntPtr _pointerValue;
|
|
|
|
private PropVariant(string value)
|
|
{
|
|
_valueType = 31;
|
|
_pointerValue = Marshal.StringToCoTaskMemUni(value);
|
|
}
|
|
|
|
public static PropVariant FromString(string value) => new(value);
|
|
|
|
public void Dispose()
|
|
{
|
|
PropVariantClear(this);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
~PropVariant()
|
|
{
|
|
Dispose();
|
|
}
|
|
|
|
[DllImport("ole32.dll")]
|
|
private static extern int PropVariantClear([In, Out] PropVariant propvar);
|
|
}
|
|
}
|