diff --git a/Example/App.xaml b/Example/App.xaml
new file mode 100644
index 0000000..423c29f
--- /dev/null
+++ b/Example/App.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/Example/App.xaml.cs b/Example/App.xaml.cs
new file mode 100644
index 0000000..df2669e
--- /dev/null
+++ b/Example/App.xaml.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace Example
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/Example/AssemblyInfo.cs b/Example/AssemblyInfo.cs
new file mode 100644
index 0000000..8b5504e
--- /dev/null
+++ b/Example/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Windows;
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
diff --git a/Example/Custom4Behavior.xaml b/Example/Custom4Behavior.xaml
new file mode 100644
index 0000000..e8c95e0
--- /dev/null
+++ b/Example/Custom4Behavior.xaml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Example/Custom4Behavior.xaml.cs b/Example/Custom4Behavior.xaml.cs
new file mode 100644
index 0000000..3343dfe
--- /dev/null
+++ b/Example/Custom4Behavior.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 Example
+{
+ ///
+ /// Custom4Behavior.xaml 的交互逻辑
+ ///
+ public partial class Custom4Behavior : Window
+ {
+ public Custom4Behavior()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Example/CustomWindow.xaml b/Example/CustomWindow.xaml
new file mode 100644
index 0000000..0aff57a
--- /dev/null
+++ b/Example/CustomWindow.xaml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Example/CustomWindow.xaml.cs b/Example/CustomWindow.xaml.cs
new file mode 100644
index 0000000..43cca5c
--- /dev/null
+++ b/Example/CustomWindow.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 Example
+{
+ ///
+ /// CustomWindow.xaml 的交互逻辑
+ ///
+ public partial class CustomWindow : Window
+ {
+ public CustomWindow()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Example/CustomWindowTitleBar.cs b/Example/CustomWindowTitleBar.cs
new file mode 100644
index 0000000..07c3fa3
--- /dev/null
+++ b/Example/CustomWindowTitleBar.cs
@@ -0,0 +1,318 @@
+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.Markup;
+using System.Windows.Media;
+using System.Windows.Shell;
+using Microsoft.Xaml.Behaviors;
+using System.Windows.Shapes;
+using System.Windows.Media.Animation;
+using System.Windows.Input;
+
+namespace Example
+{
+ ///
+ /// 为窗口提供自定义标题栏的行为
+ ///
+ public class CustomTitleBar : Behavior
+ {
+ //private readonly static string svgMax = "M959.72 0H294.216a63.96 63.96 0 0 0-63.96 63.96v127.92H64.28A63.96 63.96 0 0 0 0.32 255.84V959.4a63.96 63.96 0 0 0 63.96 63.96h703.56a63.96 63.96 0 0 0 63.96-63.96V792.465h127.92a63.96 63.96 0 0 0 63.96-63.96V63.96A63.96 63.96 0 0 0 959.72 0zM767.84 728.505V959.4H64.28V255.84h703.56z m189.322 0H831.8V255.84a63.96 63.96 0 0 0-63.96-63.96H294.216V63.96H959.72z";
+ //private readonly static string[] svgNomal = new string[] {
+ // "M785.960424 410.377773c0-14.634419-11.871277-26.608035-26.608035-26.608035L204.677194 383.769738c-14.634419 0-26.608035 11.871277-26.608035 26.608035l0 349.998001c0 14.634419 11.871277 26.608035 26.608035 26.608035l554.675195 0c14.634419 0 26.608035-11.871277 26.608035-26.608035L785.960424 410.377773zM740.931441 741.954827 223.098141 741.954827 223.098141 428.798721l517.8333 0L740.931441 741.954827z",
+ // "M856.471717 294.735159l-554.675195 0c-12.485309 0-22.514491 10.029182-22.514491 22.514491s10.029182 22.514491 22.514491 22.514491L838.153108 339.764142l0 331.679392c0 12.485309 10.029182 22.514491 22.514491 22.514491s22.514491-10.029182 22.514491-22.514491l0-349.998001C883.182091 306.708775 871.106136 294.735159 856.471717 294.735159z"
+ //};
+
+ //private readonly static Geometry svgMaxGeometry;
+ //private readonly static Geometry svgNomalGeometry;
+
+ //static CustomTitleBar()
+ //{
+ // svgMaxGeometry = Geometry.Parse(svgMax);
+ // GeometryGroup nomal = new GeometryGroup();
+ // nomal.Children.Add(Geometry.Parse(svgNomal[0]));
+ // nomal.Children.Add(Geometry.Parse(svgNomal[1]));
+ // svgNomalGeometry = nomal;
+ //}
+
+ private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
+ {
+ Grid titleBarRoot = new Grid() { Height = this.TitleHeight };
+ titleBarRoot.Background = this.Background ?? this.AssociatedObject.Background;
+
+ StackPanel spLeft = new StackPanel() { VerticalAlignment = VerticalAlignment.Stretch, HorizontalAlignment = HorizontalAlignment.Left, Orientation = Orientation.Horizontal };
+ Border bIcon = new Border() { Width = this.TitleHeight };
+ bIcon.Child = this.TitleIcon ?? new Image() { Source = this.AssociatedObject.Icon };
+ TextBlock tbTitle = new TextBlock()
+ {
+ Text = this.Title,
+ VerticalAlignment = VerticalAlignment.Center,
+ HorizontalAlignment = HorizontalAlignment.Left,
+ Foreground = Foreground = this.Foreground ?? this.AssociatedObject.Foreground,
+ FontSize = this.AssociatedObject.FontSize
+ };
+
+ spLeft.Children.Add(bIcon);
+ spLeft.Children.Add(tbTitle);
+
+ string templateString = "" +
+ "\r\n" +
+ " \r\n" +
+ " \r\n" +
+ " \r\n" +
+ " \r\n" +
+ " \r\n" +
+ "\r\n";
+
+ ResourceDictionary dictionary = (ResourceDictionary)XamlReader.Parse(templateString);
+ ControlTemplate template = (ControlTemplate)dictionary["dpButtonTemplate"] as ControlTemplate;
+
+ StackPanel spRight = new StackPanel() { VerticalAlignment = VerticalAlignment.Stretch, HorizontalAlignment = HorizontalAlignment.Right, Orientation = Orientation.Horizontal, Width = this.TitleHeight * 4, FlowDirection = FlowDirection.RightToLeft };
+ Button butClose = new Button()
+ {
+ Name = "Close",
+ Background = this.Background ?? this.AssociatedObject.Background,
+ Foreground = this.Foreground ?? this.AssociatedObject.Foreground,
+ BorderThickness = new Thickness(0),
+ Padding = new Thickness(10),
+ Template = template,
+ Content = new Viewbox()
+ {
+ Child = new Path()
+ {
+ Data = Geometry.Parse("M548.992 503.744L885.44 167.328a31.968 31.968 0 1 0-45.248-45.248L503.744 458.496 167.328 122.08a31.968 31.968 0 1 0-45.248 45.248l336.416 336.416L122.08 840.16a31.968 31.968 0 1 0 45.248 45.248l336.416-336.416L840.16 885.44a31.968 31.968 0 1 0 45.248-45.248L548.992 503.744z"),
+ Height = 1024,
+ Width = 1024,
+ Fill = this.AssociatedObject.Foreground
+ }
+ }
+ };
+ Button butMax = new Button()
+ {
+ Name = "Max",
+ Background = this.Background ?? this.AssociatedObject.Background,
+ Foreground = this.Foreground ?? this.AssociatedObject.Foreground,
+ BorderThickness = new Thickness(0),
+ Padding = new Thickness(10),
+ Template = template,
+ Content = new Viewbox()
+ {
+ Child = new Path()
+ {
+ Data = Geometry.Parse("M959.72 0H294.216a63.96 63.96 0 0 0-63.96 63.96v127.92H64.28A63.96 63.96 0 0 0 0.32 255.84V959.4a63.96 63.96 0 0 0 63.96 63.96h703.56a63.96 63.96 0 0 0 63.96-63.96V792.465h127.92a63.96 63.96 0 0 0 63.96-63.96V63.96A63.96 63.96 0 0 0 959.72 0zM767.84 728.505V959.4H64.28V255.84h703.56z m189.322 0H831.8V255.84a63.96 63.96 0 0 0-63.96-63.96H294.216V63.96H959.72z"),
+ Height = 1024,
+ Width = 1024,
+ Fill = this.AssociatedObject.Foreground
+ }
+ }
+ };
+ Button butMin = new Button()
+ {
+ Name = "Min",
+ Background = this.Background ?? this.AssociatedObject.Background,
+ Foreground = this.Foreground ?? this.AssociatedObject.Foreground,
+ BorderThickness = new Thickness(0),
+ Padding = new Thickness(10),
+ Template = template,
+ Content = new Viewbox()
+ {
+ Child = new Path()
+ {
+ Data = Geometry.Parse("M130 545.3h766c17.7 0 32-14.3 32-32s-14.3-32-32-32H130c-17.7 0-32 14.3-32 32 0 17.6 14.3 32 32 32z"),
+ Height = 1024,
+ Width = 1024,
+ Fill = this.AssociatedObject.Foreground
+ }
+ }
+ };
+
+ butClose.Click += ButClose_Click;
+ butMax.Click += ButMax_Click;
+ butMin.Click += ButMin_Click;
+
+ spRight.Children.Add(butClose);
+ spRight.Children.Add(butMax);
+ spRight.Children.Add(butMin);
+ butClose.AddHandler(Button.MouseEnterEvent, new RoutedEventHandler(this.ButMouseEnter));
+ butMax.AddHandler(Button.MouseEnterEvent, new RoutedEventHandler(this.ButMouseEnter));
+ butMin.AddHandler(Button.MouseEnterEvent, new RoutedEventHandler(this.ButMouseEnter));
+ butClose.AddHandler(Button.MouseLeaveEvent, new RoutedEventHandler(this.ButMouseLeave));
+ butMax.AddHandler(Button.MouseLeaveEvent, new RoutedEventHandler(this.ButMouseLeave));
+ butMin.AddHandler(Button.MouseLeaveEvent, new RoutedEventHandler(this.ButMouseLeave));
+
+ titleBarRoot.Children.Add(spLeft);
+ titleBarRoot.Children.Add(spRight);
+
+ titleBarRoot.Children.Add(new TextBlock()
+ {
+ Text = this.Header,
+ VerticalAlignment = VerticalAlignment.Center,
+ HorizontalAlignment = HorizontalAlignment.Center,
+ Foreground = this.Foreground ?? this.AssociatedObject.Foreground
+ });
+
+ WindowChrome.SetIsHitTestVisibleInChrome(spRight, true);
+ this.TitleBar.Child = titleBarRoot;
+ }
+
+ private void ButMouseEnter(object sender, RoutedEventArgs e)
+ {
+ Button? button = sender as Button;
+ if (button != null) button.Background = this.HoverBrush;
+ }
+
+ private void ButMouseLeave(object sender, RoutedEventArgs e)
+ {
+ Button? button = sender as Button;
+ if (button != null) button.Background = new SolidColorBrush(Colors.Transparent);
+ }
+
+ private void ButMin_Click(object sender, RoutedEventArgs e)
+ {
+ this.AssociatedObject.WindowState = WindowState.Minimized;
+ }
+
+ private void ButMax_Click(object sender, RoutedEventArgs e)
+ {
+ if (this.AssociatedObject.WindowState == WindowState.Maximized)
+ this.AssociatedObject.WindowState = WindowState.Normal;
+ else
+ this.AssociatedObject.WindowState = WindowState.Maximized;
+ }
+
+ private void ButClose_Click(object sender, RoutedEventArgs e)
+ {
+ this.AssociatedObject.Close();
+ }
+
+ protected override void OnAttached()
+ {
+ /*
+ *
+
+
+ */
+ Window target = this.AssociatedObject;
+ WindowChrome.SetWindowChrome(target, new WindowChrome() { CaptionHeight = this.TitleHeight });
+
+ this.AssociatedObject.Loaded += AssociatedObject_Loaded;
+ this.AssociatedObject.StateChanged += AssociatedObject_StateChanged;
+ }
+
+ private void AssociatedObject_StateChanged(object? sender, EventArgs e)
+ {
+ FrameworkElement? winContent = this.AssociatedObject.Content as FrameworkElement;
+ if (winContent == null) return;
+ if (this.AssociatedObject.WindowState == WindowState.Maximized)
+ winContent.Margin = new Thickness(8);
+ else winContent.Margin = new Thickness(0);
+ }
+
+ protected override void OnDetaching()
+ {
+ this.AssociatedObject.Loaded -= AssociatedObject_Loaded;
+ }
+
+
+
+ public int TitleHeight
+ {
+ get { return (int)GetValue(TitleHeightProperty); }
+ set { SetValue(TitleHeightProperty, value); }
+ }
+
+ // Using a DependencyProperty as the backing store for TitleHeight. This enables animation, styling, binding, etc...
+ public static readonly DependencyProperty TitleHeightProperty =
+ DependencyProperty.Register("TitleHeight", typeof(int), typeof(CustomTitleBar), new PropertyMetadata(40));
+
+
+
+ public Decorator TitleBar
+ {
+ get { return (Decorator)GetValue(TitleBarProperty); }
+ set { SetValue(TitleBarProperty, value); }
+ }
+
+ // Using a DependencyProperty as the backing store for TitleBar. This enables animation, styling, binding, etc...
+ public static readonly DependencyProperty TitleBarProperty =
+ DependencyProperty.Register("TitleBar", typeof(Decorator), typeof(CustomTitleBar), new PropertyMetadata(null));
+
+
+
+ public Brush Background
+ {
+ get { return (Brush)GetValue(BackgroundProperty); }
+ set { SetValue(BackgroundProperty, value); }
+ }
+
+ // Using a DependencyProperty as the backing store for Background. This enables animation, styling, binding, etc...
+ public static readonly DependencyProperty BackgroundProperty =
+ DependencyProperty.Register("Background", typeof(Brush), typeof(CustomTitleBar), new PropertyMetadata(null));
+
+
+
+ public Brush HoverBrush
+ {
+ get { return (Brush)GetValue(HoverBrushProperty); }
+ set { SetValue(HoverBrushProperty, value); }
+ }
+
+ // Using a DependencyProperty as the backing store for HoverBrush. This enables animation, styling, binding, etc...
+ public static readonly DependencyProperty HoverBrushProperty =
+ DependencyProperty.Register("HoverBrush", typeof(Brush), typeof(CustomTitleBar), new PropertyMetadata(null));
+
+
+
+ public Brush Foreground
+ {
+ get { return (Brush)GetValue(ForegroundProperty); }
+ set { SetValue(ForegroundProperty, value); }
+ }
+
+ // Using a DependencyProperty as the backing store for Foreground. This enables animation, styling, binding, etc...
+ public static readonly DependencyProperty ForegroundProperty =
+ DependencyProperty.Register("Foreground", typeof(Brush), typeof(CustomTitleBar), new PropertyMetadata(null));
+
+
+
+ public UIElement TitleIcon
+ {
+ get { return (UIElement)GetValue(TitleIconProperty); }
+ set { SetValue(TitleIconProperty, value); }
+ }
+
+ // Using a DependencyProperty as the backing store for TitleIcon. This enables animation, styling, binding, etc...
+ public static readonly DependencyProperty TitleIconProperty =
+ DependencyProperty.Register("TitleIcon", typeof(UIElement), typeof(CustomTitleBar), new PropertyMetadata(null));
+
+
+
+ public string Title
+ {
+ get { return (string)GetValue(TitleProperty); }
+ set { SetValue(TitleProperty, value); }
+ }
+
+ // Using a DependencyProperty as the backing store for Title. This enables animation, styling, binding, etc...
+ public static readonly DependencyProperty TitleProperty =
+ DependencyProperty.Register("Title", typeof(string), typeof(CustomTitleBar), new PropertyMetadata(""));
+
+
+
+ public string Header
+ {
+ get { return (string)GetValue(HeaderProperty); }
+ set { SetValue(HeaderProperty, value); }
+ }
+
+ // Using a DependencyProperty as the backing store for Header. This enables animation, styling, binding, etc...
+ public static readonly DependencyProperty HeaderProperty =
+ DependencyProperty.Register("Header", typeof(string), typeof(CustomTitleBar), new PropertyMetadata(""));
+
+
+ }
+}
diff --git a/Example/Example.csproj b/Example/Example.csproj
new file mode 100644
index 0000000..7f6360f
--- /dev/null
+++ b/Example/Example.csproj
@@ -0,0 +1,11 @@
+
+
+ WinExe
+ net6.0-windows7.0
+ enable
+ true
+
+
+
+
+
\ No newline at end of file
diff --git a/Example/MainWindow.xaml b/Example/MainWindow.xaml
new file mode 100644
index 0000000..2a72ae6
--- /dev/null
+++ b/Example/MainWindow.xaml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Example/MainWindow.xaml.cs b/Example/MainWindow.xaml.cs
new file mode 100644
index 0000000..7e39884
--- /dev/null
+++ b/Example/MainWindow.xaml.cs
@@ -0,0 +1,94 @@
+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.Navigation;
+using System.Windows.Shapes;
+
+namespace Example
+{
+ ///
+ /// Interaction logic for MainWindow.xaml
+ ///
+ public partial class MainWindow : Window
+ {
+ public MainWindow()
+ {
+ InitializeComponent();
+
+
+ CommandBinding cbinding = new CommandBinding(MainWindow.GetButtonContentCmd);
+ cbinding.Executed += Cbinding_Executed;
+ cbinding.CanExecute += Cbinding_CanExecute;
+ this.CommandBindings.Add(cbinding);
+
+ this.textCommand.OnCanExecute = (obj) => true;
+ this.textCommand.OnExecute += TextCommand_OnExecute;
+ this.butCustom.Command = this.textCommand;
+ }
+
+ private void TextCommand_OnExecute(object? obj)
+ {
+ MessageBox.Show("自这义命令被调用!");
+ }
+
+ private void Cbinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
+ {
+ e.CanExecute = true;
+ }
+
+ private void Cbinding_Executed(object sender, ExecutedRoutedEventArgs e)
+ {
+ MessageBox.Show(e.Source.ToString());
+ }
+
+ public static RoutedCommand GetButtonContentCmd = new RoutedCommand();
+
+ public CustomCommand textCommand = new CustomCommand();
+
+ public class CustomCommand : ICommand
+ {
+ public string? Command { get; set; }
+ public CustomCommand() { }
+ public CustomCommand(string command, Action