更新
This commit is contained in:
382
AntdWpf/Microsoft.Windows.Shell/WindowChrome.cs
Normal file
382
AntdWpf/Microsoft.Windows.Shell/WindowChrome.cs
Normal file
@@ -0,0 +1,382 @@
|
||||
using AntdWpf.Microsoft.Windows.Shell.Standard;
|
||||
|
||||
using Microsoft.Windows.Shell;
|
||||
/**************************************************************************\
|
||||
Copyright Microsoft Corporation. All Rights Reserved.
|
||||
\**************************************************************************/
|
||||
#pragma warning disable 1591, 618
|
||||
namespace AntdWpf.Microsoft.Windows.Shell
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
using global::Standard;
|
||||
|
||||
public enum ResizeGripDirection
|
||||
{
|
||||
None,
|
||||
TopLeft,
|
||||
Top,
|
||||
TopRight,
|
||||
Right,
|
||||
BottomRight,
|
||||
Bottom,
|
||||
BottomLeft,
|
||||
Left,
|
||||
Caption,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum NonClientFrameEdges
|
||||
{
|
||||
None = 0,
|
||||
Left = 1,
|
||||
Top = 2,
|
||||
Right = 4,
|
||||
Bottom = 8,
|
||||
}
|
||||
|
||||
public class WindowChrome : Freezable
|
||||
{
|
||||
private struct _SystemParameterBoundProperty
|
||||
{
|
||||
public string SystemParameterPropertyName { get; set; }
|
||||
public DependencyProperty DependencyProperty { get; set; }
|
||||
}
|
||||
|
||||
// Named property available for fully extending the glass frame.
|
||||
public static Thickness GlassFrameCompleteThickness { get { return new Thickness(-1); } }
|
||||
|
||||
#region Attached Properties
|
||||
|
||||
public static readonly DependencyProperty WindowChromeProperty = DependencyProperty.RegisterAttached(
|
||||
"WindowChrome",
|
||||
typeof(WindowChrome),
|
||||
typeof(WindowChrome),
|
||||
new PropertyMetadata(null, _OnChromeChanged));
|
||||
|
||||
private static void _OnChromeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
// The different design tools handle drawing outside their custom window objects differently.
|
||||
// Rather than try to support this concept in the design surface let the designer draw its own
|
||||
// chrome anyways.
|
||||
// There's certainly room for improvement here.
|
||||
if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(d))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var window = (Window)d;
|
||||
var newChrome = (WindowChrome)e.NewValue;
|
||||
|
||||
Assert.IsNotNull(window);
|
||||
|
||||
// Update the ChromeWorker with this new object.
|
||||
|
||||
// If there isn't currently a worker associated with the Window then assign a new one.
|
||||
// There can be a many:1 relationship of to Window to WindowChrome objects, but a 1:1 for a Window and a WindowChromeWorker.
|
||||
WindowChromeWorker chromeWorker = WindowChromeWorker.GetWindowChromeWorker(window);
|
||||
if (chromeWorker == null)
|
||||
{
|
||||
chromeWorker = new WindowChromeWorker();
|
||||
WindowChromeWorker.SetWindowChromeWorker(window, chromeWorker);
|
||||
}
|
||||
|
||||
chromeWorker.SetWindowChrome(newChrome);
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")]
|
||||
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
|
||||
public static WindowChrome GetWindowChrome(Window window)
|
||||
{
|
||||
Verify.IsNotNull(window, "window");
|
||||
return (WindowChrome)window.GetValue(WindowChromeProperty);
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")]
|
||||
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
|
||||
public static void SetWindowChrome(Window window, WindowChrome chrome)
|
||||
{
|
||||
Verify.IsNotNull(window, "window");
|
||||
window.SetValue(WindowChromeProperty, chrome);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsHitTestVisibleInChromeProperty = DependencyProperty.RegisterAttached(
|
||||
"IsHitTestVisibleInChrome",
|
||||
typeof(bool),
|
||||
typeof(WindowChrome),
|
||||
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits));
|
||||
|
||||
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")]
|
||||
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
|
||||
public static bool GetIsHitTestVisibleInChrome(IInputElement inputElement)
|
||||
{
|
||||
Verify.IsNotNull(inputElement, "inputElement");
|
||||
var dobj = inputElement as DependencyObject;
|
||||
if (dobj == null)
|
||||
{
|
||||
throw new ArgumentException("The element must be a DependencyObject", "inputElement");
|
||||
}
|
||||
return (bool)dobj.GetValue(IsHitTestVisibleInChromeProperty);
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")]
|
||||
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
|
||||
public static void SetIsHitTestVisibleInChrome(IInputElement inputElement, bool hitTestVisible)
|
||||
{
|
||||
Verify.IsNotNull(inputElement, "inputElement");
|
||||
var dobj = inputElement as DependencyObject;
|
||||
if (dobj == null)
|
||||
{
|
||||
throw new ArgumentException("The element must be a DependencyObject", "inputElement");
|
||||
}
|
||||
dobj.SetValue(IsHitTestVisibleInChromeProperty, hitTestVisible);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ResizeGripDirectionProperty = DependencyProperty.RegisterAttached(
|
||||
"ResizeGripDirection",
|
||||
typeof(ResizeGripDirection),
|
||||
typeof(WindowChrome),
|
||||
new FrameworkPropertyMetadata(ResizeGripDirection.None, FrameworkPropertyMetadataOptions.Inherits));
|
||||
|
||||
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")]
|
||||
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
|
||||
public static ResizeGripDirection GetResizeGripDirection(IInputElement inputElement)
|
||||
{
|
||||
Verify.IsNotNull(inputElement, "inputElement");
|
||||
var dobj = inputElement as DependencyObject;
|
||||
if (dobj == null)
|
||||
{
|
||||
throw new ArgumentException("The element must be a DependencyObject", "inputElement");
|
||||
}
|
||||
return (ResizeGripDirection)dobj.GetValue(ResizeGripDirectionProperty);
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")]
|
||||
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
|
||||
public static void SetResizeGripDirection(IInputElement inputElement, ResizeGripDirection direction)
|
||||
{
|
||||
Verify.IsNotNull(inputElement, "inputElement");
|
||||
var dobj = inputElement as DependencyObject;
|
||||
if (dobj == null)
|
||||
{
|
||||
throw new ArgumentException("The element must be a DependencyObject", "inputElement");
|
||||
}
|
||||
dobj.SetValue(ResizeGripDirectionProperty, direction);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dependency Properties
|
||||
|
||||
public static readonly DependencyProperty CaptionHeightProperty = DependencyProperty.Register(
|
||||
"CaptionHeight",
|
||||
typeof(double),
|
||||
typeof(WindowChrome),
|
||||
new PropertyMetadata(
|
||||
0d,
|
||||
(d, e) => ((WindowChrome)d)._OnPropertyChangedThatRequiresRepaint()),
|
||||
value => (double)value >= 0d);
|
||||
|
||||
/// <summary>The extent of the top of the window to treat as the caption.</summary>
|
||||
public double CaptionHeight
|
||||
{
|
||||
get { return (double)GetValue(CaptionHeightProperty); }
|
||||
set { SetValue(CaptionHeightProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ResizeBorderThicknessProperty = DependencyProperty.Register(
|
||||
"ResizeBorderThickness",
|
||||
typeof(Thickness),
|
||||
typeof(WindowChrome),
|
||||
new PropertyMetadata(default(Thickness)),
|
||||
(value) => Utility.IsThicknessNonNegative((Thickness)value));
|
||||
|
||||
public Thickness ResizeBorderThickness
|
||||
{
|
||||
get { return (Thickness)GetValue(ResizeBorderThicknessProperty); }
|
||||
set { SetValue(ResizeBorderThicknessProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty GlassFrameThicknessProperty = DependencyProperty.Register(
|
||||
"GlassFrameThickness",
|
||||
typeof(Thickness),
|
||||
typeof(WindowChrome),
|
||||
new PropertyMetadata(
|
||||
default(Thickness),
|
||||
(d, e) => ((WindowChrome)d)._OnPropertyChangedThatRequiresRepaint(),
|
||||
(d, o) => _CoerceGlassFrameThickness((Thickness)o)));
|
||||
|
||||
private static object _CoerceGlassFrameThickness(Thickness thickness)
|
||||
{
|
||||
// If it's explicitly set, but set to a thickness with at least one negative side then
|
||||
// coerce the value to the stock GlassFrameCompleteThickness.
|
||||
if (!Utility.IsThicknessNonNegative(thickness))
|
||||
{
|
||||
return GlassFrameCompleteThickness;
|
||||
}
|
||||
|
||||
return thickness;
|
||||
}
|
||||
|
||||
public Thickness GlassFrameThickness
|
||||
{
|
||||
get { return (Thickness)GetValue(GlassFrameThicknessProperty); }
|
||||
set { SetValue(GlassFrameThicknessProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty UseAeroCaptionButtonsProperty = DependencyProperty.Register(
|
||||
"UseAeroCaptionButtons",
|
||||
typeof(bool),
|
||||
typeof(WindowChrome),
|
||||
new FrameworkPropertyMetadata(true));
|
||||
|
||||
public bool UseAeroCaptionButtons
|
||||
{
|
||||
get { return (bool)GetValue(UseAeroCaptionButtonsProperty); }
|
||||
set { SetValue(UseAeroCaptionButtonsProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register(
|
||||
"CornerRadius",
|
||||
typeof(CornerRadius),
|
||||
typeof(WindowChrome),
|
||||
new PropertyMetadata(
|
||||
default(CornerRadius),
|
||||
(d, e) => ((WindowChrome)d)._OnPropertyChangedThatRequiresRepaint()),
|
||||
(value) => Utility.IsCornerRadiusValid((CornerRadius)value));
|
||||
|
||||
public CornerRadius CornerRadius
|
||||
{
|
||||
get { return (CornerRadius)GetValue(CornerRadiusProperty); }
|
||||
set { SetValue(CornerRadiusProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty NonClientFrameEdgesProperty = DependencyProperty.Register(
|
||||
"NonClientFrameEdges",
|
||||
typeof(NonClientFrameEdges),
|
||||
typeof(WindowChrome),
|
||||
new PropertyMetadata(
|
||||
NonClientFrameEdges.None,
|
||||
(d, e) => ((WindowChrome)d)._OnPropertyChangedThatRequiresRepaint()),
|
||||
_NonClientFrameEdgesAreValid);
|
||||
|
||||
private static readonly NonClientFrameEdges NonClientFrameEdges_All = NonClientFrameEdges.Left | NonClientFrameEdges.Top | NonClientFrameEdges.Right | NonClientFrameEdges.Bottom;
|
||||
|
||||
private static bool _NonClientFrameEdgesAreValid(object value)
|
||||
{
|
||||
NonClientFrameEdges ncEdges = NonClientFrameEdges.None;
|
||||
try
|
||||
{
|
||||
ncEdges = (NonClientFrameEdges)value;
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ncEdges == NonClientFrameEdges.None)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Does this only contain valid bits?
|
||||
if ((ncEdges | NonClientFrameEdges_All) != NonClientFrameEdges_All)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// It can't sacrifice all 4 edges. Weird things happen.
|
||||
if (ncEdges == NonClientFrameEdges_All)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public NonClientFrameEdges NonClientFrameEdges
|
||||
{
|
||||
get { return (NonClientFrameEdges)GetValue(NonClientFrameEdgesProperty); }
|
||||
set { SetValue(NonClientFrameEdgesProperty, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region New Dependency Properties
|
||||
|
||||
/// <summary>Dependency property for IgnoreTaskbar</summary>
|
||||
public static readonly DependencyProperty IgnoreTaskbarProperty = DependencyProperty.Register(
|
||||
"IgnoreTaskbar",
|
||||
typeof(bool),
|
||||
typeof(WindowChrome),
|
||||
new FrameworkPropertyMetadata(false, (d, e) => ((WindowChrome)d)._OnPropertyChangedThatRequiresRepaint()));
|
||||
|
||||
/// <summary>
|
||||
/// If this property is true and the attached window's WindowStyle=None then when the window is maximized it will cover the entire
|
||||
/// monitor, including the taskbar.
|
||||
/// </summary>
|
||||
public bool IgnoreTaskbar
|
||||
{
|
||||
get { return (bool)GetValue(IgnoreTaskbarProperty); }
|
||||
set { SetValue(IgnoreTaskbarProperty, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected override Freezable CreateInstanceCore()
|
||||
{
|
||||
return new WindowChrome();
|
||||
}
|
||||
|
||||
private static readonly List<_SystemParameterBoundProperty> _BoundProperties = new List<_SystemParameterBoundProperty>
|
||||
{
|
||||
new _SystemParameterBoundProperty { DependencyProperty = CornerRadiusProperty, SystemParameterPropertyName = "WindowCornerRadius" },
|
||||
new _SystemParameterBoundProperty { DependencyProperty = CaptionHeightProperty, SystemParameterPropertyName = "WindowCaptionHeight" },
|
||||
new _SystemParameterBoundProperty { DependencyProperty = ResizeBorderThicknessProperty, SystemParameterPropertyName = "WindowResizeBorderThickness" },
|
||||
new _SystemParameterBoundProperty { DependencyProperty = GlassFrameThicknessProperty, SystemParameterPropertyName = "WindowNonClientFrameThickness" },
|
||||
};
|
||||
|
||||
public WindowChrome()
|
||||
{
|
||||
// Effective default values for some of these properties are set to be bindings
|
||||
// that set them to system defaults.
|
||||
// A more correct way to do this would be to Coerce the value iff the source of the DP was the default value.
|
||||
// Unfortunately with the current property system we can't detect whether the value being applied at the time
|
||||
// of the coersion is the default.
|
||||
foreach (var bp in _BoundProperties)
|
||||
{
|
||||
// This list must be declared after the DP's are assigned.
|
||||
Assert.IsNotNull(bp.DependencyProperty);
|
||||
BindingOperations.SetBinding(
|
||||
this,
|
||||
bp.DependencyProperty,
|
||||
new Binding
|
||||
{
|
||||
#if NET45 || NET462
|
||||
Path = new PropertyPath("(SystemParameters." + bp.SystemParameterPropertyName + ")"),
|
||||
#else
|
||||
Source = SystemParameters2.Current,
|
||||
Path = new PropertyPath(bp.SystemParameterPropertyName),
|
||||
#endif
|
||||
Mode = BindingMode.OneWay,
|
||||
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void _OnPropertyChangedThatRequiresRepaint()
|
||||
{
|
||||
var handler = PropertyChangedThatRequiresRepaint;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
internal event EventHandler PropertyChangedThatRequiresRepaint;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user