using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
namespace Developpez.Dotnet.Windows.Util
{
///
/// Fournit des propriétés attachées pour utiliser les effets du DWM (Desktop Window Manager)
///
public static class DwmUtil
{
#region Attached properties
#region IsHandlerAttached (private)
private static bool GetIsHandlerAttached(DependencyObject obj)
{
return (bool)obj.GetValue(IsHandlerAttachedProperty);
}
private static void SetIsHandlerAttached(DependencyObject obj, bool value)
{
obj.SetValue(IsHandlerAttachedProperty, value);
}
// Using a DependencyProperty as the backing store for IsHandlerAttached. This enables animation, styling, binding, etc...
private static readonly DependencyProperty IsHandlerAttachedProperty =
DependencyProperty.RegisterAttached("IsHandlerAttached", typeof(bool), typeof(DwmUtil), new UIPropertyMetadata(false));
private static void AttachHandler(Window w)
{
if (!GetIsHandlerAttached(w))
{
w.Loaded += w_Loaded;
w.Unloaded += w_Unloaded;
SetIsHandlerAttached(w, true);
}
}
private static void DetachHandler(Window w)
{
if (GetIsHandlerAttached(w))
{
w.Loaded -= w_Loaded;
w.Unloaded -= w_Unloaded;
SetIsHandlerAttached(w, false);
}
}
static void w_Unloaded(object sender, RoutedEventArgs e)
{
Window w = sender as Window;
if (w != null)
{
DetachHandler(w);
}
}
static void w_Loaded(object sender, RoutedEventArgs e)
{
Window w = sender as Window;
if (w != null)
{
ApplyGlassFrameMargins(w, GetGlassFrameMargins(w));
EnableBlur(w, GetEnableBlur(w));
}
}
#endregion
#region GlassFrameMargins
///
/// Obtient les marges de la bordure "Glass"
///
/// La fenêtre cible
/// Les marges de la bordure "Glass"
[AttachedPropertyBrowsableForType(typeof(Window))]
public static Thickness GetGlassFrameMargins(Window window)
{
return (Thickness)window.GetValue(GlassFrameMarginsProperty);
}
///
/// Définit les marges de la bordure "Glass"
///
/// La fenêtre cible
/// Les marges à appliquer
/// Une bordure uniforme de -1 applique l'effet "Glass" à toute la fenêtre
public static void SetGlassFrameMargins(Window window, Thickness value)
{
window.SetValue(GlassFrameMarginsProperty, value);
}
///
/// Identifiant de la propriété GlassFrameMargins
///
public static readonly DependencyProperty GlassFrameMarginsProperty =
DependencyProperty.RegisterAttached(
"GlassFrameMargins",
typeof(Thickness),
typeof(DwmUtil),
new UIPropertyMetadata(
new Thickness(),
(o, e) =>
{
Window w = o as Window;
Thickness newValue = (Thickness)e.NewValue;
if (w != null)
{
if (w.IsLoaded)
{
ApplyGlassFrameMargins(w, newValue);
}
else
{
AttachHandler(w);
}
}
}));
private static readonly Thickness fullClientArea = new Thickness(-1);
private static void ApplyGlassFrameMargins(Window window, Thickness margins)
{
try
{
bool compositionEnabled = false;
Interop.Functions.DwmIsCompositionEnabled(ref compositionEnabled);
if (compositionEnabled)
{
// Obtain the window handle for WPF application
IntPtr hwnd = new WindowInteropHelper(window).Handle;
HwndSource mainWindowSrc = HwndSource.FromHwnd(hwnd);
mainWindowSrc.CompositionTarget.BackgroundColor = Color.FromArgb(0, 0, 0, 0);
//Color bgColor = Color.FromArgb(0, 0, 0, 0);
//if (window.Background is SolidColorBrush)
// bgColor = (window.Background as SolidColorBrush).Color;
//mainWindowSrc.CompositionTarget.BackgroundColor = bgColor;
// Set Margins
if (!margins.Equals(fullClientArea))
{
System.Drawing.Graphics desktop = System.Drawing.Graphics.FromHwnd(hwnd);
float DesktopDpiX = desktop.DpiX;
float DesktopDpiY = desktop.DpiY;
margins.Left *= DesktopDpiX / 96;
margins.Right *= DesktopDpiX / 96;
margins.Top *= DesktopDpiY / 96;
margins.Bottom *= DesktopDpiY / 96;
}
Interop.Types.MARGINS mrg =
new Interop.Types.MARGINS
{
Left = (int)margins.Left,
Top = (int)margins.Top,
Right = (int)margins.Right,
Bottom = (int)margins.Bottom
};
int hr = Interop.Functions.DwmExtendFrameIntoClientArea(mainWindowSrc.Handle, ref mrg);
if (hr < 0)
{
Exception ex = Marshal.GetExceptionForHR(hr);
throw ex;
}
}
}
// If not Vista, paint background white.
catch (DllNotFoundException)
{
window.Background = Brushes.White;
}
}
#endregion
#region EnableBlur
///
/// Indique si l'effet "Blur" est appliqué à la fenêtre
///
/// La fenêtre cible
/// true si l'effet "Blur" est appliqué à la fenêtre, false sinon.
[AttachedPropertyBrowsableForType(typeof(Window))]
public static bool? GetEnableBlur(Window window)
{
return (bool?)window.GetValue(EnableBlurProperty);
}
///
/// Définit si l'effet "Blur" est appliqué à la fenêtre
///
/// La fenêtre cible
/// true si l'effet "Blur" doit être appliqué à la fenêtre, false sinon.
public static void SetEnableBlur(Window window, bool? value)
{
window.SetValue(EnableBlurProperty, value);
}
///
/// Identifiant de la propriété EnableBlur
///
public static readonly DependencyProperty EnableBlurProperty =
DependencyProperty.RegisterAttached(
"EnableBlur",
typeof(bool?),
typeof(DwmUtil),
new UIPropertyMetadata(
null,
(o, e) =>
{
bool? newValue = (bool?)e.NewValue;
Window w = o as Window;
if (w != null)
{
if (w.IsLoaded && newValue.HasValue)
{
EnableBlur(w, newValue);
}
else
{
AttachHandler(w);
}
}
}));
private static void EnableBlur(Window window, bool? enable)
{
if (enable.HasValue)
{
try
{
bool compositionEnabled = false;
Interop.Functions.DwmIsCompositionEnabled(ref compositionEnabled);
if (compositionEnabled)
{
IntPtr hwnd = new WindowInteropHelper(window).Handle;
HwndSource mainWindowSrc = System.Windows.Interop.HwndSource.FromHwnd(hwnd);
mainWindowSrc.CompositionTarget.BackgroundColor = Color.FromArgb(0, 0, 0, 0);
Interop.Types.DWM_BLURBEHIND bb = new Interop.Types.DWM_BLURBEHIND();
bb.Enable = enable.Value;
bb.BlurRegion = IntPtr.Zero;
int hr = Interop.Functions.DwmEnableBlurBehindWindow(hwnd, ref bb);
if (hr < 0)
{
Exception ex = Marshal.GetExceptionForHR(hr);
throw ex;
}
}
}
// If not Vista, paint background white.
catch (DllNotFoundException)
{
window.Background = Brushes.White;
}
}
}
#endregion
#endregion
#region Interop declarations
private static class Interop
{
public static class Types
{
[StructLayout(LayoutKind.Sequential)]
public struct MARGINS
{
public MARGINS(int thickness)
{
Left = thickness;
Right = thickness;
Top = thickness;
Bottom = thickness;
}
public int Left; // width of left border that retains its size
public int Right; // width of right border that retains its size
public int Top; // height of top border that retains its size
public int Bottom; // height of bottom border that retains its size
};
[StructLayout(LayoutKind.Sequential)]
public struct DWM_BLURBEHIND
{
private uint _flags;
public uint Flags
{
get { return _flags; }
set { _flags = value; }
}
[MarshalAs(UnmanagedType.Bool)]
private bool _enable;
public bool Enable
{
get { return _enable; }
set
{
_enable = value;
_flags |= Constants.DWM_BB_ENABLE;
}
}
private IntPtr _blurRegion;
public IntPtr BlurRegion
{
get { return _blurRegion; }
set
{
_blurRegion = value;
_flags |= Constants.DWM_BB_BLURREGION;
}
}
[MarshalAs(UnmanagedType.Bool)]
private bool _transitionOnMaximized;
public bool TransitionOnMaximized
{
get { return _transitionOnMaximized; }
set
{
_transitionOnMaximized = value;
_flags |= Constants.DWM_BB_TRANSITIONONMAXIMIZED;
}
}
};
}
public static class Functions
{
[DllImport("DwmApi.dll")]
public static extern int DwmExtendFrameIntoClientArea(IntPtr hwnd, ref Types.MARGINS pMarInset);
[DllImport("DwmApi.dll")]
public static extern int DwmEnableBlurBehindWindow(IntPtr hwnd, ref Types.DWM_BLURBEHIND pBlurBehind);
[DllImport("DwmApi.dll")]
public static extern int DwmIsCompositionEnabled(ref bool enabled);
}
public static class Constants
{
public const uint DWM_BB_ENABLE = 0x00000001;
public const uint DWM_BB_BLURREGION = 0x00000002;
public const uint DWM_BB_TRANSITIONONMAXIMIZED = 0x00000004;
}
}
#endregion
}
}