Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Areo Glass Effect and windowStyle set to none causes window resize to not function properly

Tags:

c#

wpf

xaml

Areo Glass Effect and windowStyle set to none and AllowTransparency causes widow resize to not function properly

After adding the Areo Glass theme to my window and setting WindowState to None the window does not resize properly. I can go as large as I want but when resizing down smaller the glass effect stays the same width and height.

For example I click Maximize. The window Expands to the full screen size. But when restoring my window restores back down but not the glass effect.

All I really want is the blur effect. I Don't care about the glass, but this seems to be the only way I can get a transparent blur.

How can I fix this?

xaml

    <Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" AllowsTransparency="True" WindowStyle="None" ResizeMode="CanResizeWithGrip" Background="Transparent">
    <Border BorderThickness="1" Margin="0,35,0,0" BorderBrush="Orange">
    <Grid Background="#0CFFA500">

            <DockPanel VerticalAlignment="Top" HorizontalAlignment="Stretch" Height="35" Background="#4effffff">
            <DockPanel.Resources>
                <Style x:Key="WindowIconStyle" TargetType="{x:Type Button}">
                    <Setter Property="FontSize" Value="16" />
                    <Setter Property="Foreground" Value="#444" />
                    <Setter Property="Height" Value="30"></Setter>
                    <Setter Property="Width" Value="30"></Setter>
                    <Setter Property="FontFamily" Value="Webdings"></Setter>
                    <Setter Property="Background" Value="#ff0000"></Setter>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type Button}">
                                <Border BorderBrush="Transparent" BorderThickness="0.5,0,0.5,0">
                                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" Value="#77abff" />
                            <Setter Property="Foreground" Value="#000000" />
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type Button}">
                                        <Border BorderBrush="Black" BorderThickness="1,0,1,0">
                                            <Border.Background>
                                                <LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
                                                    <GradientStop Color="Black" Offset="1"/>
                                                    <GradientStop Color="White" Offset="0.952"/>
                                                    <GradientStop Color="Black" Offset="0"/>
                                                    <GradientStop Color="#FFF7F7F7" Offset="0.044"/>
                                                </LinearGradientBrush>
                                            </Border.Background>
                                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                                        </Border>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                        <Trigger  Property="IsPressed" Value="True">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type Button}">
                                        <Border BorderBrush="#444" BorderThickness="1,0,1,0">
                                            <Border.Background>
                                                <LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
                                                    <GradientStop Color="#444" Offset="1"/>
                                                    <GradientStop Color="#ffececec" Offset="0.952"/>
                                                    <GradientStop Color="#444" Offset="0"/>
                                                    <GradientStop Color="#ffececec" Offset="0.044"/>
                                                </LinearGradientBrush>
                                            </Border.Background>
                                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                                        </Border>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </DockPanel.Resources>
            <Button DockPanel.Dock="Right" VerticalAlignment="Center" HorizontalAlignment="Right" Click="TriggerClose" Style="{StaticResource WindowIconStyle}" Content="r" />
            <Button x:Name="btnMaximize" DockPanel.Dock="Right" VerticalAlignment="Center" HorizontalAlignment="Right" Click="TriggerMaximize" Style="{StaticResource WindowIconStyle}"  Content="c" />
            <Button DockPanel.Dock="Right" VerticalAlignment="Center" HorizontalAlignment="Right" Click="TriggerMinimize" Style="{StaticResource WindowIconStyle}" Content="0" />
            <StatusBar Background="Transparent" MouseDoubleClick="TriggerMaximize" MouseMove="TriggerMoveWindow" >
                <TextBlock DockPanel.Dock="Left" x:Name="txtTitle" Text="Title" FontSize="16" Padding="10,0,0,0"/>
            </StatusBar>
        </DockPanel>
            <Border BorderThickness="0,1,0,0" Margin="0,35,0,0" BorderBrush="#f7000000">

        </Border>
    </Grid>
    </Border>
</Window>

C#

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;


namespace WpfApplication2 {

    public partial class MainWindow : Window {

        #region Constants

        private System.Windows.Window me { get; set; }
        private const int WM_DWMCOMPOSITIONCHANGED = 0x031E;
        private const int DWM_BB_ENABLE = 0x1;

        #endregion //Constants

        #region Structures
        [StructLayout(LayoutKind.Sequential)]
        private struct DWM_BLURBEHIND {
            public int dwFlags;
            public bool fEnable;
            public IntPtr hRgnBlur;
            public bool fTransitionOnMaximized;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct MARGINS {
            public int cxLeftWidth;
            public int cxRightWidth;
            public int cyTopHeight;
            public int cyBottomHeight;
        }
        #endregion //Structures

        #region APIs

        [DllImport("dwmapi.dll", PreserveSig = false)]
        private static extern void DwmEnableBlurBehindWindow(IntPtr hwnd, ref DWM_BLURBEHIND blurBehind);
        [DllImport("dwmapi.dll")]
        private static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMargins);
        [DllImport("dwmapi.dll", PreserveSig = false)]
        private static extern bool DwmIsCompositionEnabled();

        #endregion //APIs

        public MainWindow() {
            SourceInitialized += OnSourceInitialized;
            InitializeComponent();
        }

        private void OnSourceInitialized(object sender, EventArgs eventArgs) {
            me = (Window)sender;
            if (Environment.OSVersion.Version.Major >= 6) {
                var hwnd = new WindowInteropHelper(me).Handle;
                var hs = HwndSource.FromHwnd(hwnd);
                hs.CompositionTarget.BackgroundColor = System.Windows.Media.Colors.Transparent;

                hs.AddHook(new HwndSourceHook(this.WndProc));
                this.InitializeGlass(hwnd);
            }

        }

        public System.Windows.Media.Color GetAreoColor() {
            int icolor = (int)Microsoft.Win32.Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM", "ColorizationColor", null);
            var c = System.Drawing.Color.FromArgb(icolor);
            return System.Windows.Media.Color.FromArgb(c.A, c.R, c.G, c.B);
        }


        private static String ConverterToHex(System.Drawing.Color c) {
            return String.Format("#{0}{1}{2}", c.R.ToString("X2"), c.G.ToString("X2"), c.B.ToString("X2"));
        }

        #region Methods

        #region InitializeGlass
        public void InitializeGlass(IntPtr hwnd) {
            if (!DwmIsCompositionEnabled())
                return;

            // fill the background with glass
            var margins = new MARGINS();
            margins.cxLeftWidth = margins.cxRightWidth = margins.cyBottomHeight = margins.cyTopHeight = -1;
            DwmExtendFrameIntoClientArea(hwnd, ref margins);

            // initialize blur for the window
            DWM_BLURBEHIND bbh = new DWM_BLURBEHIND();
            bbh.fEnable = true;
            // bbh.fTransitionOnMaximized = true;

            bbh.dwFlags = DWM_BB_ENABLE;
            DwmEnableBlurBehindWindow(hwnd, ref bbh);
        }
        #endregion //InitializeGlass

        #region WndProc
        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) {
            if (msg == WM_DWMCOMPOSITIONCHANGED) {
                this.InitializeGlass(hwnd);
                handled = false;
            }

            return IntPtr.Zero;
        }
        #endregion //WndProc

        #endregion //Methods


        private void TriggerMoveWindow(object sender, MouseEventArgs e) {
            if (e.LeftButton == MouseButtonState.Pressed) {
                if (WindowState == System.Windows.WindowState.Maximized) {
                    WindowState = System.Windows.WindowState.Normal;

                    double pct = PointToScreen(e.GetPosition(this)).X / System.Windows.SystemParameters.PrimaryScreenWidth;
                    Top = 0;
                    Left = e.GetPosition(this).X - (pct * Width);
                }

                Application.Current.MainWindow.DragMove();
            }
        }

        private void TriggerMaximize(object sender, EventArgs e) {
            if (WindowState == System.Windows.WindowState.Maximized) {
                WindowState = System.Windows.WindowState.Normal;
                btnMaximize.FontFamily = new System.Windows.Media.FontFamily("Webdings");
                btnMaximize.Content = "c";
            } else if (WindowState == System.Windows.WindowState.Normal) {
                WindowState = System.Windows.WindowState.Maximized;
                btnMaximize.FontFamily = new System.Windows.Media.FontFamily("Wingdings");
                btnMaximize.Content = "r";
                InvalidateVisual();
            }
        }

        private void TriggerClose(object sender, RoutedEventArgs e) {
                Close();
        }

        private void TriggerMinimize(object sender, RoutedEventArgs e) {
            WindowState = System.Windows.WindowState.Minimized;
        }
    }
}

enter image description here

like image 882
Mike Avatar asked Nov 18 '16 21:11

Mike


1 Answers

It seems that AllowsTransparency == True is the source of this behavior. Therefore you can remove it. However, you should set the Opacity of Backgroud Brush to be zero:

<Window.Background>
    <SolidColorBrush Opacity="0" Color="Transparent"/>
</Window.Background>

This along with setting CompositionTarget.BackgroundColor to be transparent, and also using DwmEnableBlurBehindWindow function will make a similar result to setting AllowsTransparency == True.

However, with these modifications, the look of the window is not very pleasant because of its border. The Border will go away if you set ResizeMode=="NoResize". However, in this case, you should implement resizing yourself. Fortunately, this is easy by adding a Thumb and handling DragDelta event. Here is the full code:

Xaml

 <Window x:Class="Test1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Test1" 
    mc:Ignorable="d"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    Title="MainWindow" Name="window" 
    Height="350" Width="525" WindowStyle="None" ResizeMode="NoResize" >
<Window.Background>
    <SolidColorBrush Opacity="0" Color="Transparent"/>
</Window.Background>

<Grid>
    <Thumb DockPanel.Dock="Bottom" DragDelta="Thumb_DragDelta" HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="8" Height="8" Cursor="SizeNWSE" Background="Red" Panel.ZIndex="4"/>
    <Border BorderThickness="1" BorderBrush="Orange" Margin="0,0,0,0">
        <Grid Background="#0CFFA500">
            <DockPanel VerticalAlignment="Top" HorizontalAlignment="Stretch" Height="35" Background="#4effffff">
                <DockPanel.Resources>
                    <Style x:Key="WindowIconStyle" TargetType="{x:Type Button}">
                        <Setter Property="FontSize" Value="16" />
                        <Setter Property="Foreground" Value="#444" />
                        <Setter Property="Height" Value="30"></Setter>
                        <Setter Property="Width" Value="30"></Setter>
                        <Setter Property="FontFamily" Value="Webdings"></Setter>
                        <Setter Property="Background" Value="#ff0000"></Setter>
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="{x:Type Button}">
                                    <Border BorderBrush="Transparent" BorderThickness="0.5,0,0.5,0">
                                        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                                    </Border>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                        <Style.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Background" Value="#77abff" />
                                <Setter Property="Foreground" Value="#000000" />
                                <Setter Property="Template">
                                    <Setter.Value>
                                        <ControlTemplate TargetType="{x:Type Button}">
                                            <Border BorderBrush="Black" BorderThickness="1,0,1,0">
                                                <Border.Background>
                                                    <LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
                                                        <GradientStop Color="Black" Offset="1"/>
                                                        <GradientStop Color="White" Offset="0.952"/>
                                                        <GradientStop Color="Black" Offset="0"/>
                                                        <GradientStop Color="#FFF7F7F7" Offset="0.044"/>
                                                    </LinearGradientBrush>
                                                </Border.Background>
                                                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                                            </Border>
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Trigger>
                            <Trigger  Property="IsPressed" Value="True">
                                <Setter Property="Template">
                                    <Setter.Value>
                                        <ControlTemplate TargetType="{x:Type Button}">
                                            <Border BorderBrush="#444" BorderThickness="1,0,1,0">
                                                <Border.Background>
                                                    <LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
                                                        <GradientStop Color="#444" Offset="1"/>
                                                        <GradientStop Color="#ffececec" Offset="0.952"/>
                                                        <GradientStop Color="#444" Offset="0"/>
                                                        <GradientStop Color="#ffececec" Offset="0.044"/>
                                                    </LinearGradientBrush>
                                                </Border.Background>
                                                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                                            </Border>
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </DockPanel.Resources>
                <Button DockPanel.Dock="Right" VerticalAlignment="Center" HorizontalAlignment="Right" Click="TriggerClose" Style="{StaticResource WindowIconStyle}" Content="r" />
                <Button x:Name="btnMaximize" DockPanel.Dock="Right" VerticalAlignment="Center" HorizontalAlignment="Right" Click="TriggerMaximize" Style="{StaticResource WindowIconStyle}"  Content="c" />
                <Button DockPanel.Dock="Right" VerticalAlignment="Center" HorizontalAlignment="Right" Click="TriggerMinimize" Style="{StaticResource WindowIconStyle}" Content="0" />
                <StatusBar Background="Transparent" MouseDoubleClick="TriggerMaximize" MouseMove="TriggerMoveWindow" >
                    <TextBlock DockPanel.Dock="Left" x:Name="txtTitle" Text="Title" FontSize="16" Padding="10,0,0,0"/>
                </StatusBar>
            </DockPanel>
            <Border BorderThickness="0,1,0,0" Margin="0,35,0,0" BorderBrush="#f7000000">

            </Border>
        </Grid>
    </Border>
</Grid>
</Window>

CS Code

public partial class MainWindow : Window
{ 
    private const int WM_DWMCOMPOSITIONCHANGED = 0x031E;
    private const int DWM_BB_ENABLE = 0x1; 

    [StructLayout(LayoutKind.Sequential)]
    private struct DWM_BLURBEHIND
    {
        public int dwFlags;
        public bool fEnable;
        public IntPtr hRgnBlur;
        public bool fTransitionOnMaximized;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct MARGINS
    {
        public int cxLeftWidth;
        public int cxRightWidth;
        public int cyTopHeight;
        public int cyBottomHeight;
    } 

    [DllImport("dwmapi.dll", PreserveSig = false)]
    private static extern void DwmEnableBlurBehindWindow(IntPtr hwnd, ref DWM_BLURBEHIND blurBehind);
    [DllImport("dwmapi.dll")]
    private static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMargins);
    [DllImport("dwmapi.dll", PreserveSig = false)]
    private static extern bool DwmIsCompositionEnabled();

    public MainWindow()
    { 
        InitializeComponent();
        SourceInitialized += OnSourceInitialized; 
    } 

    private void OnSourceInitialized(object sender, EventArgs eventArgs)
    {
        var hwnd = new WindowInteropHelper(this).Handle;
        var hs = HwndSource.FromHwnd(hwnd);
        hs.CompositionTarget.BackgroundColor = System.Windows.Media.Colors.Transparent;

        var margins = new MARGINS();
        margins.cxLeftWidth = margins.cxRightWidth = margins.cyTopHeight = margins.cyBottomHeight = -1;

        DwmExtendFrameIntoClientArea(hwnd, ref margins);

        DWM_BLURBEHIND bbh = new DWM_BLURBEHIND();
        bbh.fEnable = true;
        bbh.dwFlags = DWM_BB_ENABLE;
        DwmEnableBlurBehindWindow(hwnd, ref bbh);
    }

    private void TriggerMinimize(object sender, RoutedEventArgs e)
    {
        WindowState = System.Windows.WindowState.Minimized;
    }

    private void TriggerMoveWindow(object sender, MouseEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            if (WindowState == System.Windows.WindowState.Maximized)
            {
                WindowState = System.Windows.WindowState.Normal; 
                double pct = PointToScreen(e.GetPosition(this)).X / System.Windows.SystemParameters.PrimaryScreenWidth;
                Top = 0;
                Left = e.GetPosition(this).X - (pct * Width);
            }

            Application.Current.MainWindow.DragMove();
        }
    }

    private void TriggerMaximize(object sender, EventArgs e)
    {
        if (WindowState == System.Windows.WindowState.Maximized)
        {
            WindowState = System.Windows.WindowState.Normal;
            btnMaximize.FontFamily = new System.Windows.Media.FontFamily("Webdings");
            btnMaximize.Content = "c";
        }
        else if (WindowState == System.Windows.WindowState.Normal)
        {
            WindowState = System.Windows.WindowState.Maximized;
            btnMaximize.FontFamily = new System.Windows.Media.FontFamily("Wingdings");
            btnMaximize.Content = "r";
            InvalidateVisual();
        }
    }

    private void TriggerClose(object sender, RoutedEventArgs e)
    {
        Close();
    }

    private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
    {
        this.Height += e.VerticalChange;
        this.Width += e.HorizontalChange;
    }
}

You can see the result:

https://i.stack.imgur.com/Rvtp3.gif

like image 100
Ron Avatar answered Oct 24 '22 20:10

Ron