ghost1372 / HandyControls

Contains some simple and commonly used WPF controls based on HandyControl
https://ghost1372.github.io/
MIT License
1.1k stars 104 forks source link

[Feature request] Update backdrop effect at runtime #136

Closed GliczDev closed 2 years ago

GliczDev commented 2 years ago

Hi, after you've added acrylic and tabbed effects to handycontrols, it'll be great, if you'll add ability to update (or disable) backdrop effect at runtime. It's possible, because i've added it myself to my program.

Also, when update'll be released? I want to use new features from new MicaHelper class

ghost1372 commented 2 years ago

Hi, i will try to do that. I will try to release a new version in the next 2 or 3 weeks

ghost1372 commented 2 years ago

@MichixYT can you share your codes?

GliczDev commented 2 years ago

@MichixYT can you share your codes?

yes

using HandyControl.Data;
using HandyControl.Themes;
using HandyControl.Tools;
using HandyControl.Tools.Interop;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;

namespace GlitchCode.Managers
{
    public static class MicaManager
    {
        private static List<Window> _windows = new List<Window>();
        private static IntPtr _windowHandle;
        private static bool _isDark = false;

        public static void ApplyMicaEffect(object window, bool isDark)
        {
            ((window as Window) ?? throw new Exception("Only Window controls can have the Mica effect applied.")).Loaded += OnWindowLoaded;
            if (_windows.Contains(window))
            {
                UpdateMica(window, isDark);
                return;
            }
            _isDark = isDark;
            _windows.Add((Window)window);
        }

        public static void UpdateMica(object window, bool isDark)
        {
            Window obj = (window as Window) ?? throw new Exception("Only windows can have the Mica effect applied.");
            _isDark = isDark;
            _windowHandle = new WindowInteropHelper(obj).Handle;
            if (ThemeManager.Current.UsingSystemTheme)
            {
                bool isDark2 = !WindowHelper.DetermineIfInLightThemeMode();
                ApplyMicaEffect(_windowHandle, isDark2);
            }
            else
            {
                ApplyMicaEffect(_windowHandle, isDark);
            }
        }

        public static void OnWindowLoaded(object sender, RoutedEventArgs e)
        {
            Window obj = (sender as Window) ?? throw new Exception("Only windows can have the Mica effect applied.");
            obj.Background = Brushes.Transparent;
            _windowHandle = new WindowInteropHelper(obj).Handle;
            PresentationSource.FromVisual(obj).ContentRendered += OnContentRendered;
            ThemeManager.Current.SystemThemeChanged += Current_SystemThemeChanged;
        }

        private static void Current_SystemThemeChanged(object sender, FunctionEventArgs<ThemeManager.SystemTheme> e)
        {
            if (ThemeManager.Current.UsingSystemTheme)
            {
                bool isDark = !WindowHelper.DetermineIfInLightThemeMode();
                ApplyMicaEffect(_windowHandle, isDark);
            }
            else
            {
                ApplyMicaEffect(_windowHandle, _isDark);
            }
        }

        private static void OnContentRendered(object sender, EventArgs e)
        {
            if (ThemeManager.Current.UsingSystemTheme)
            {
                bool flag = !WindowHelper.DetermineIfInLightThemeMode();
                ThemeManager.Current.ApplicationTheme = (flag ? ApplicationTheme.Dark : ApplicationTheme.Light);
                ApplyMicaEffect(_windowHandle, flag);
            }
            else
            {
                ApplyMicaEffect(_windowHandle, _isDark);
            }
        }

        public static void RemoveMicaEffect(object window)
        {
            Window obj = (window as Window) ?? throw new Exception("Only windows can have the Mica effect applied.");
            if (_windows.Contains(obj))
            {
                _windowHandle = new WindowInteropHelper(obj).Handle;
                MicaHelper.RemoveMicaEffect(_windowHandle);
            }
        }

        private static int _pvTrueAttribute = 1;
        private static int _pvFalseAttribute = 0;
        private static int _pvMicaTrueAttribute = 2;
        private static int _pvAcrylicTrueAttribute = 3;
        private static int _pvTabbedTrueAttribute = 4;

        private static int MICA_EFFECT = 38;

        [DllImport("dwmapi.dll")]
        public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);

        public static void ApplyMicaEffect(IntPtr handle, bool isDark)
        {
            if (!(handle == IntPtr.Zero))
            {
                try
                {
                    InteropMethods.SetWindowLong(handle, -16, InteropMethods.GetWindowLong(handle, -16) & -524289);
                }
                catch (Exception)
                {
                }

                if (isDark)
                {
                    InteropMethods.DwmSetWindowAttribute(handle, InteropValues.DWMWINDOWATTRIBUTE.USE_IMMERSIVE_DARK_MODE, ref _pvTrueAttribute, Marshal.SizeOf(typeof(int)));
                }
                else
                {
                    InteropMethods.DwmSetWindowAttribute(handle, InteropValues.DWMWINDOWATTRIBUTE.USE_IMMERSIVE_DARK_MODE, ref _pvFalseAttribute, Marshal.SizeOf(typeof(int)));
                }

                if (Properties.Settings.Default.BackdropEffect.Equals("2"))
                {
                    DwmSetWindowAttribute(handle, MICA_EFFECT, ref _pvMicaTrueAttribute, Marshal.SizeOf(typeof(int)));
                } 
                else if (Properties.Settings.Default.BackdropEffect.Equals("3"))
                {
                    DwmSetWindowAttribute(handle, MICA_EFFECT, ref _pvAcrylicTrueAttribute, Marshal.SizeOf(typeof(int)));
                }
                else if (Properties.Settings.Default.BackdropEffect.Equals("4"))
                {
                    DwmSetWindowAttribute(handle, MICA_EFFECT, ref _pvTabbedTrueAttribute, Marshal.SizeOf(typeof(int)));
                }
                else
                {
                    DwmSetWindowAttribute(handle, MICA_EFFECT, ref _pvFalseAttribute, Marshal.SizeOf(typeof(int)));
                    Brush brush = App.Current.FindResource("RegionBrush") as Brush;
                    WindowManager.SetBackgroundColors(brush);
                }
            }
        }
    }
}

I know that code isn't really good, but i've created it only for now

ghost1372 commented 2 years ago

you can now change mica to disable and see effect at runtime