diff --git a/DeedyDesigner/Deedy.Testing/MainWindow.xaml b/DeedyDesigner/Deedy.Testing/MainWindow.xaml
index 5940972..f63d84b 100644
--- a/DeedyDesigner/Deedy.Testing/MainWindow.xaml
+++ b/DeedyDesigner/Deedy.Testing/MainWindow.xaml
@@ -15,7 +15,10 @@
-
+
+
+
+
diff --git a/DeedyDesigner/Deedy.Testing/MainWindow.xaml.cs b/DeedyDesigner/Deedy.Testing/MainWindow.xaml.cs
index d770676..f3a782f 100644
--- a/DeedyDesigner/Deedy.Testing/MainWindow.xaml.cs
+++ b/DeedyDesigner/Deedy.Testing/MainWindow.xaml.cs
@@ -8,6 +8,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
+using Deedy.Testing;
namespace Deedy
{
@@ -31,5 +32,10 @@ namespace Deedy
//DrawerManager.ShowDrawer(this.decorator, new Border() { Background = Brushes.Red, MinWidth = 400, MinHeight = 400, HorizontalAlignment = HorizontalAlignment.Stretch, VerticalAlignment = VerticalAlignment.Stretch });
new ElegantWindow().ShowDialog();
}
+
+ private void Button_Click_1(object sender, RoutedEventArgs e)
+ {
+ new WindowAdornerTest().ShowDialog();
+ }
}
}
\ No newline at end of file
diff --git a/DeedyDesigner/Deedy.Testing/Themes/Generic.xaml b/DeedyDesigner/Deedy.Testing/Themes/Generic.xaml
index 93ab023..fc28926 100644
--- a/DeedyDesigner/Deedy.Testing/Themes/Generic.xaml
+++ b/DeedyDesigner/Deedy.Testing/Themes/Generic.xaml
@@ -142,4 +142,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DeedyDesigner/Deedy.Testing/WindowAdorner.cs b/DeedyDesigner/Deedy.Testing/WindowAdorner.cs
new file mode 100644
index 0000000..db11aa6
--- /dev/null
+++ b/DeedyDesigner/Deedy.Testing/WindowAdorner.cs
@@ -0,0 +1,250 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Markup;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using System.Windows.Shell;
+
+namespace Deedy
+{
+ ///
+ /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。
+ ///
+ /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。
+ /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
+ /// 元素中:
+ ///
+ /// xmlns:MyNamespace="clr-namespace:Deedy.Testing"
+ ///
+ ///
+ /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。
+ /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
+ /// 元素中:
+ ///
+ /// xmlns:MyNamespace="clr-namespace:Deedy.Testing;assembly=Deedy.Testing"
+ ///
+ /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用,
+ /// 并重新生成以避免编译错误:
+ ///
+ /// 在解决方案资源管理器中右击目标项目,然后依次单击
+ /// “添加引用”->“项目”->[浏览查找并选择此项目]
+ ///
+ ///
+ /// 步骤 2)
+ /// 继续操作并在 XAML 文件中使用控件。
+ ///
+ ///
+ ///
+ ///
+ [ContentProperty("Child")]
+ [TemplatePart(Name = "IconView", Type = typeof(Border))]
+ [TemplatePart(Name = "TitleBar", Type = typeof(TextBlock))]
+ [TemplatePart(Name = "Minimize", Type = typeof(Button))]
+ [TemplatePart(Name = "Maximize", Type = typeof(Button))]
+ [TemplatePart(Name = "CloseWin", Type = typeof(Button))]
+ [TemplatePart(Name = "Controller", Type = typeof(Panel))]
+ [TemplatePart(Name = "Container", Type = typeof(Decorator))]
+ public class WindowAdorner : Control
+ {
+ static WindowAdorner()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(WindowAdorner), new FrameworkPropertyMetadata(typeof(WindowAdorner)));
+ }
+ public Brush HoverBrush
+ {
+ get { return (Brush)GetValue(HoverBrushProperty); }
+ set { SetValue(HoverBrushProperty, value); }
+ }
+
+ public static readonly DependencyProperty HoverBrushProperty =
+ DependencyProperty.Register("HoverBrush", typeof(Brush), typeof(WindowAdorner), new PropertyMetadata(Brushes.Silver));
+
+
+ public UIElement Child
+ {
+ get { return (UIElement)GetValue(ChildProperty); }
+ set { SetValue(ChildProperty, value); }
+ }
+
+ public static readonly DependencyProperty ChildProperty =
+ DependencyProperty.Register("Child", typeof(UIElement), typeof(WindowAdorner), new PropertyMetadata(null, (d, e) =>
+ {
+ WindowAdorner windowDecorator = (WindowAdorner)d;
+ if (e.NewValue != null)
+ {
+ if (windowDecorator.Container != null)
+ windowDecorator.Container.Child = e.NewValue as UIElement;
+ }
+ }));
+
+ private Panel? Controller;
+ private Decorator? Container;
+ private Button? Minimize;
+ private Button? Maximize;
+ private Button? CloseWin;
+ private TextBlock? TitleBar;
+ private Border? IconView;
+
+ private Window? Target;
+ private WindowChrome? Chrome;
+ //private Decorator? Decorator;
+
+ private static bool IsNeedOverrideMetadata = true;
+ public WindowAdorner() { }
+ public void OnAttached()
+ {
+ FrameworkElement? parent = this.Parent as FrameworkElement;
+ Window? target = parent as Window;
+ while (parent != null && target == null)
+ {
+ parent = parent.Parent as FrameworkElement;
+ target = parent as Window;
+ }
+ //这是第【1】步
+ if (target == null && !DesignerProperties.GetIsInDesignMode(this)) throw new ArgumentNullException("窗体装饰器[WindowDecorator]对象不可以附加到一个空的Window对象上!");
+ //if (decorator == null) throw new ArgumentNullException("窗体装饰器[WindowDecorator]对象需要一个用于放置的容器!");
+ this.Target = target;
+ //this.Decorator = decorator;
+ //this.Decorator.Child = this;
+ if (this.Target == null) return;
+ this.Target.StateChanged += Target_StateChanged;
+ this.Target.Loaded += Target_Loaded;
+ if (IsNeedOverrideMetadata)
+ {
+ Window.WindowStyleProperty.OverrideMetadata(this.Target.GetType(), new FrameworkPropertyMetadata((d, e) => this.AdjustVisual()));
+ Window.ResizeModeProperty.OverrideMetadata(this.Target.GetType(), new FrameworkPropertyMetadata((d, e) => this.AdjustVisual()));
+ IsNeedOverrideMetadata = false;
+ }
+ }
+ public override void OnApplyTemplate()
+ {
+ this.OnDetaching();
+ base.OnApplyTemplate();
+ this.OnAttached();
+ //这是第【2】步
+ this.Controller = GetTemplateChild("Controller") as Panel;
+ this.Container = GetTemplateChild("Container") as Decorator;
+ this.Minimize = GetTemplateChild("Minimize") as Button;
+ this.Maximize = GetTemplateChild("Maximize") as Button;
+ this.CloseWin = GetTemplateChild("CloseWin") as Button;
+ this.IconView = GetTemplateChild("IconView") as Border;
+ this.TitleBar = GetTemplateChild("TitleBar") as TextBlock;
+ if (this.Container != null) this.Container.Child = this.Child;
+ }
+ private void Target_Loaded(object sender, RoutedEventArgs e)
+ {
+ if (this.Background == BackgroundProperty.DefaultMetadata.DefaultValue) this.SetBinding(BackgroundProperty, new Binding() { Source = this.Target, Path = new PropertyPath(BackgroundProperty.Name) });
+ if (this.BorderBrush == BorderBrushProperty.DefaultMetadata.DefaultValue) this.SetBinding(BorderBrushProperty, new Binding() { Source = this.Target, Path = new PropertyPath(BorderBrushProperty.Name) });
+ //这是第【3】步
+ this.Chrome = new WindowChrome() { CaptionHeight = this.ActualHeight };
+ WindowChrome.SetWindowChrome(this.Target, this.Chrome);
+ WindowChrome.SetIsHitTestVisibleInChrome(this.Container, true);
+ WindowChrome.SetIsHitTestVisibleInChrome(this.Controller, true);
+ //if (this.Container != null) this.Container.Child = this.Child;
+ if (this.Controller != null)
+ {
+ foreach (var c in this.Controller.Children)
+ {
+ Button? button = c as Button;
+ button?.AddHandler(Button.ClickEvent, new RoutedEventHandler(this.CommandButton_Click));
+ button?.AddHandler(Button.MouseEnterEvent, new RoutedEventHandler((s, e) => ((Button)e.Source).Background = this.HoverBrush));
+ button?.AddHandler(Button.MouseLeaveEvent, new RoutedEventHandler((s, e) => ((Button)e.Source).Background = Brushes.Transparent));
+ }
+ }
+ this.AdjustVisual();
+ this.AdjustMargin();
+ }
+ public void OnDetaching()
+ {
+ if (this.Target != null)
+ {
+ this.Target.StateChanged -= this.Target_StateChanged;
+ this.Target.Loaded -= this.Target_Loaded;
+ }
+ }
+ private void AdjustVisual()
+ {
+ if (this.Target != null)
+ {
+ if (this.Controller != null) this.Controller.Visibility = Visibility.Visible;
+ if (this.Minimize != null) this.Minimize.Visibility = Visibility.Visible;
+ if (this.Maximize != null) this.Maximize.Visibility = Visibility.Visible;
+ if (this.CloseWin != null) this.CloseWin.Visibility = Visibility.Visible;
+ if (this.IconView != null) this.IconView.Visibility = Visibility.Visible;
+ if (this.TitleBar != null) this.TitleBar.Visibility = Visibility.Visible;
+
+ if (this.Target.ResizeMode == ResizeMode.NoResize)
+ {
+ if (this.Minimize != null) this.Minimize.Visibility = Visibility.Collapsed;
+ if (this.Maximize != null) this.Maximize.Visibility = Visibility.Collapsed;
+ }
+ if (this.Target.ResizeMode == ResizeMode.CanMinimize)
+ {
+ if (this.Maximize != null) this.Maximize.Visibility = Visibility.Collapsed;
+ }
+ if (this.Target.WindowStyle == WindowStyle.None)
+ {
+ if (this.IconView != null) this.IconView.Visibility = Visibility.Collapsed;
+ if (this.TitleBar != null) this.TitleBar.Visibility = Visibility.Collapsed;
+ if (this.Controller != null) this.Controller.Visibility = Visibility.Collapsed;
+ }
+ if (this.Target.WindowStyle == WindowStyle.ToolWindow)
+ {
+ if (this.Controller != null) this.Controller.Visibility = Visibility.Collapsed;
+ }
+ }
+ }
+ private void AdjustMargin()
+ {
+ if (this.Target != null)
+ {
+ var winContent = this.Target.Content as FrameworkElement;
+ if (winContent == null) return;
+ if (this.Target.WindowState == WindowState.Maximized)
+ winContent.Margin = new Thickness(8);
+ else winContent.Margin = new Thickness(0);
+ }
+ }
+ private void Target_StateChanged(object? sender, EventArgs e)
+ {
+ this.AdjustMargin();
+ }
+ private void CommandButton_Click(object sender, RoutedEventArgs e)
+ {
+ Button? button = sender as Button;
+ if (button != null)
+ {
+ switch (button.Name)
+ {
+ case "Minimize":
+ if (this.Target != null) this.Target.WindowState = WindowState.Minimized;
+ break;
+ case "Maximize":
+ {
+ if (this.Target != null)
+ {
+ if (this.Target.WindowState == WindowState.Maximized || this.Target.WindowState == WindowState.Minimized)
+ this.Target.WindowState = WindowState.Normal;
+ else this.Target.WindowState = WindowState.Maximized;
+ }
+ }
+ break;
+ default:
+ this.Target?.Close();
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/DeedyDesigner/Deedy.Testing/WindowAdornerTest.xaml b/DeedyDesigner/Deedy.Testing/WindowAdornerTest.xaml
new file mode 100644
index 0000000..6f6860e
--- /dev/null
+++ b/DeedyDesigner/Deedy.Testing/WindowAdornerTest.xaml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
diff --git a/DeedyDesigner/Deedy.Testing/WindowAdornerTest.xaml.cs b/DeedyDesigner/Deedy.Testing/WindowAdornerTest.xaml.cs
new file mode 100644
index 0000000..4f2fd4f
--- /dev/null
+++ b/DeedyDesigner/Deedy.Testing/WindowAdornerTest.xaml.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace Deedy.Testing
+{
+ ///
+ /// WindowAdornerTest.xaml 的交互逻辑
+ ///
+ public partial class WindowAdornerTest : Window
+ {
+ public WindowAdornerTest()
+ {
+ InitializeComponent();
+ }
+ }
+}