Files
ClashWidget/Helpers/NativeMethods.cs
T
2026-05-08 11:59:26 +08:00

127 lines
4.2 KiB
C#

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
namespace ClashWidget.Helpers;
internal static class NativeMethods
{
[DllImport("user32.dll")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter,
int X, int Y, int cx, int cy, uint uFlags);
[DllImport("dwmapi.dll")]
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr,
ref int attrValue, int attrSize);
[DllImport("dwmapi.dll")]
private static extern int DwmExtendFrameIntoClientArea(IntPtr hwnd,
ref MARGINS margins);
[DllImport("user32.dll")]
private static extern int SetWindowCompositionAttribute(IntPtr hwnd,
ref WindowCompositionAttributeData data);
[DllImport("user32.dll")]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
private static readonly IntPtr HWND_TOPMOST = new(-1);
private const uint SWP_NOMOVE = 0x0002;
private const uint SWP_NOSIZE = 0x0001;
private const uint SWP_NOACTIVATE = 0x0010;
private const uint SWP_SHOWWINDOW = 0x0040;
private const int GWL_EXSTYLE = -20;
private const int WS_EX_TOOLWINDOW = 0x00000080;
private const int WS_EX_APPWINDOW = 0x00040000;
private const int DWMWA_SYSTEMBACKDROP_TYPE = 38;
[StructLayout(LayoutKind.Sequential)]
private struct MARGINS { public int Left, Right, Top, Bottom; }
private enum AccentState { ACCENT_DISABLED = 0, ACCENT_ENABLE_ACRYLICBLURBEHIND = 4 }
[StructLayout(LayoutKind.Sequential)]
private struct AccentPolicy
{
public AccentState AccentState;
public int AccentFlags;
public int GradientColor;
public int AnimationId;
}
[StructLayout(LayoutKind.Sequential)]
private struct WindowCompositionAttributeData
{
public WindowCompositionAttribute Attribute;
public IntPtr Data;
public int SizeOfData;
}
private enum WindowCompositionAttribute { WCA_ACCENT_POLICY = 19 }
public static void ApplyAcrylic(Window window)
{
var hwnd = new WindowInteropHelper(window).EnsureHandle();
// Extend DWM frame into entire client area
var margins = new MARGINS { Left = -1, Right = -1, Top = -1, Bottom = -1 };
DwmExtendFrameIntoClientArea(hwnd, ref margins);
// Try Win11 modern API first
int backdrop = 3; // DWMSBT_TRANSIENTWINDOW = Acrylic
int hr = DwmSetWindowAttribute(hwnd, DWMWA_SYSTEMBACKDROP_TYPE, ref backdrop, sizeof(int));
if (hr != 0)
{
// Fallback: Win10 acrylic
try
{
var accent = new AccentPolicy
{
AccentState = AccentState.ACCENT_ENABLE_ACRYLICBLURBEHIND,
AccentFlags = 2,
GradientColor = 0x01FFFFFF
};
var data = new WindowCompositionAttributeData
{
Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY,
SizeOfData = Marshal.SizeOf<AccentPolicy>(),
Data = Marshal.AllocHGlobal(Marshal.SizeOf<AccentPolicy>())
};
Marshal.StructureToPtr(accent, data.Data, false);
SetWindowCompositionAttribute(hwnd, ref data);
Marshal.FreeHGlobal(data.Data);
}
catch { }
}
}
public static void SetTopmost(Window window)
{
try
{
var hwnd = new WindowInteropHelper(window).EnsureHandle();
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW);
}
catch { }
}
public static void HideFromTaskbar(Window window)
{
try
{
var hwnd = new WindowInteropHelper(window).EnsureHandle();
int exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
exStyle |= WS_EX_TOOLWINDOW;
exStyle &= ~WS_EX_APPWINDOW;
SetWindowLong(hwnd, GWL_EXSTYLE, exStyle);
}
catch { }
}
}