using System; using System.Runtime.InteropServices; using System.Windows.Interop; using System.Windows; using Windows.Win32; using Windows.Win32.Graphics.Dwm; using Flow.Launcher.Infrastructure.UserSettings; namespace Flow.Launcher.Infrastructure { public static class Win32Helper { #region Blur Handling public static unsafe bool DWMSetBackdropForWindow(Window window, BackdropTypes backdrop) { var windowHelper = new WindowInteropHelper(window); windowHelper.EnsureHandle(); var backdropType = backdrop switch { BackdropTypes.Acrylic => DWM_SYSTEMBACKDROP_TYPE.DWMSBT_TRANSIENTWINDOW, BackdropTypes.Mica => DWM_SYSTEMBACKDROP_TYPE.DWMSBT_MAINWINDOW, BackdropTypes.MicaAlt => DWM_SYSTEMBACKDROP_TYPE.DWMSBT_TABBEDWINDOW, _ => DWM_SYSTEMBACKDROP_TYPE.DWMSBT_AUTO }; return PInvoke.DwmSetWindowAttribute( new(windowHelper.Handle), DWMWINDOWATTRIBUTE.DWMWA_SYSTEMBACKDROP_TYPE, &backdropType, (uint)Marshal.SizeOf()).Succeeded; } public static unsafe bool DWMSetDarkModeForWindow(Window window, bool useDarkMode) { var windowHelper = new WindowInteropHelper(window); windowHelper.EnsureHandle(); var darkMode = useDarkMode ? 1 : 0; return PInvoke.DwmSetWindowAttribute( new(windowHelper.Handle), DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, &darkMode, (uint)Marshal.SizeOf()).Succeeded; } /// /// /// /// /// DoNotRound, Round, RoundSmall, Default /// public static unsafe bool DWMSetCornerPreferenceForWindow(Window window, string cornerType) { var windowHelper = new WindowInteropHelper(window); windowHelper.EnsureHandle(); var preference = cornerType switch { "DoNotRound" => DWM_WINDOW_CORNER_PREFERENCE.DWMWCP_DONOTROUND, "Round" => DWM_WINDOW_CORNER_PREFERENCE.DWMWCP_ROUND, "RoundSmall" => DWM_WINDOW_CORNER_PREFERENCE.DWMWCP_ROUNDSMALL, "Default" => DWM_WINDOW_CORNER_PREFERENCE.DWMWCP_DEFAULT, _ => throw new InvalidOperationException("Invalid corner type") }; return PInvoke.DwmSetWindowAttribute( new(windowHelper.Handle), DWMWINDOWATTRIBUTE.DWMWA_WINDOW_CORNER_PREFERENCE, &preference, (uint)Marshal.SizeOf()).Succeeded; } #endregion #region Backdrop public static bool IsBackdropSupported() { // Windows 11 (22000) 이상에서만 Mica 및 Acrylic 효과 지원 return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && Environment.OSVersion.Version.Build >= 22000; } public static unsafe bool SetMicaForWindow(Window window, bool enableMica) { var windowHelper = new WindowInteropHelper(window); windowHelper.EnsureHandle(); DWM_SYSTEMBACKDROP_TYPE backdropType = enableMica ? DWM_SYSTEMBACKDROP_TYPE.DWMSBT_MAINWINDOW : DWM_SYSTEMBACKDROP_TYPE.DWMSBT_NONE; return PInvoke.DwmSetWindowAttribute( new(windowHelper.Handle), DWMWINDOWATTRIBUTE.DWMWA_SYSTEMBACKDROP_TYPE, &backdropType, (uint)Marshal.SizeOf()).Succeeded; } #endregion #region Blur Handling /* Found on https://github.com/riverar/sample-win10-aeroglass */ private enum AccentState { ACCENT_DISABLED = 0, ACCENT_ENABLE_GRADIENT = 1, ACCENT_ENABLE_TRANSPARENTGRADIENT = 2, ACCENT_ENABLE_BLURBEHIND = 3, ACCENT_INVALID_STATE = 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 } [DllImport("user32.dll")] private static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttributeData data); /// /// Checks if the blur theme is enabled /// public static bool IsBlurTheme() { if (Environment.OSVersion.Version >= new Version(6, 2)) { var resource = Application.Current.TryFindResource("ThemeBlurEnabled"); if (resource is bool b) return b; return false; } return false; } /// /// Sets the blur for a window via SetWindowCompositionAttribute /// public static void SetBlurForWindow(Window w, bool blur) { SetWindowAccent(w, blur ? AccentState.ACCENT_ENABLE_BLURBEHIND : AccentState.ACCENT_DISABLED); } private static void SetWindowAccent(Window w, AccentState state) { var windowHelper = new WindowInteropHelper(w); windowHelper.EnsureHandle(); var accent = new AccentPolicy { AccentState = state }; var accentStructSize = Marshal.SizeOf(accent); var accentPtr = Marshal.AllocHGlobal(accentStructSize); Marshal.StructureToPtr(accent, accentPtr, false); var data = new WindowCompositionAttributeData { Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY, SizeOfData = accentStructSize, Data = accentPtr }; SetWindowCompositionAttribute(windowHelper.Handle, ref data); Marshal.FreeHGlobal(accentPtr); } #endregion } }