From 45c5d050083c42f3c7de1be8eeda234208ca0f2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannes=20Str=C3=B6hlein?= Date: Tue, 26 Jul 2022 12:01:59 +0200 Subject: [PATCH 1/5] - added ShowClose --- WPFUI/Controls/TitleBar.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/WPFUI/Controls/TitleBar.cs b/WPFUI/Controls/TitleBar.cs index 84e8ba828..e9dd5edae 100644 --- a/WPFUI/Controls/TitleBar.cs +++ b/WPFUI/Controls/TitleBar.cs @@ -70,9 +70,16 @@ public class TitleBar : UserControl /// Property for . /// public static readonly DependencyProperty ShowMinimizeProperty = DependencyProperty.Register( - nameof(ShowMinimize), + nameof(ShowmMinimize), typeof(bool), typeof(TitleBar), new PropertyMetadata(true)); + /// + /// Property for . + /// + public static readonly DependencyProperty ShowCloseProperty = DependencyProperty.Register( + nameof(ShowClose), + typeof(bool), typeof(TitleBar), new PropertyMetadata(true)); + /// /// Property for /// @@ -228,6 +235,14 @@ public bool ShowMinimize set => SetValue(ShowMinimizeProperty, value); } + /// + /// Gets or sets information whether to show close button. + /// + public bool ShowClose + { + get => (bool)SetValue(CanClose) + } + /// /// Gets or sets information whether to show help button /// From 1cb630bc86b6c4d3c0bb9ee3a891e4f3e1518227 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannes=20Str=C3=B6hlein?= Date: Tue, 26 Jul 2022 12:13:37 +0200 Subject: [PATCH 2/5] - added Property to set the visibility of the Close Button --- src/Wpf.Ui.Demo/Views/Container.xaml | 1 + src/Wpf.Ui/Controls/TitleBar.cs | 18 +++++++++++++++++- src/Wpf.Ui/Styles/Controls/TitleBar.xaml | 5 +++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Wpf.Ui.Demo/Views/Container.xaml b/src/Wpf.Ui.Demo/Views/Container.xaml index 55ec6d9ea..502fba55a 100644 --- a/src/Wpf.Ui.Demo/Views/Container.xaml +++ b/src/Wpf.Ui.Demo/Views/Container.xaml @@ -195,6 +195,7 @@ + /// Property for . + /// + public static readonly DependencyProperty ShowCloseProperty = DependencyProperty.Register( + nameof(ShowClose), + typeof(bool), typeof(TitleBar), new PropertyMetadata(true)); + /// /// Property for /// @@ -266,7 +273,16 @@ public bool ShowMinimize get => (bool)GetValue(ShowMinimizeProperty); set => SetValue(ShowMinimizeProperty, value); } - + + /// + /// Gets or sets information whether to show close button. + /// + public bool ShowClose + { + get => (bool)GetValue(ShowCloseProperty); + set => SetValue(ShowCloseProperty, value); + } + /// /// Gets or sets information whether to show help button /// diff --git a/src/Wpf.Ui/Styles/Controls/TitleBar.xaml b/src/Wpf.Ui/Styles/Controls/TitleBar.xaml index b11f94e5e..9ee017567 100644 --- a/src/Wpf.Ui/Styles/Controls/TitleBar.xaml +++ b/src/Wpf.Ui/Styles/Controls/TitleBar.xaml @@ -250,6 +250,8 @@ + + + From 907f7535327dfcf0c3a0e284911397e000112000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannes=20Str=C3=B6hlein?= Date: Tue, 26 Jul 2022 12:16:03 +0200 Subject: [PATCH 3/5] removed ghost file --- WPFUI/Controls/TitleBar.cs | 647 ------------------------------------- 1 file changed, 647 deletions(-) delete mode 100644 WPFUI/Controls/TitleBar.cs diff --git a/WPFUI/Controls/TitleBar.cs b/WPFUI/Controls/TitleBar.cs deleted file mode 100644 index e9dd5edae..000000000 --- a/WPFUI/Controls/TitleBar.cs +++ /dev/null @@ -1,647 +0,0 @@ -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. -// Copyright (C) Leszek Pomianowski and WPF UI Contributors. -// All Rights Reserved. - -using System; -using System.ComponentModel; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; -using System.Windows.Media; -using WPFUI.Win32; - -namespace WPFUI.Controls -{ - /// - /// Custom navigation buttons for the window. - /// - public class TitleBar : UserControl - { - private Window _parent; - - private User32.POINT _doubleClickPoint; - - private Tray.NotifyIcon _notifyIcon; - - private Common.SnapLayout _snapLayout; - - /// - /// Property for . - /// - public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(nameof(Title), - typeof(string), typeof(TitleBar), new PropertyMetadata(null)); - - /// - /// Property for . - /// - public static readonly DependencyProperty MinimizeToTrayProperty = DependencyProperty.Register( - nameof(MinimizeToTray), - typeof(bool), typeof(TitleBar), new PropertyMetadata(false)); - - /// - /// Property for . - /// - public static readonly DependencyProperty UseSnapLayoutProperty = DependencyProperty.Register( - nameof(UseSnapLayout), - typeof(bool), typeof(TitleBar), new PropertyMetadata(false)); - - /// - /// Property for . - /// - public static readonly DependencyProperty IsMaximizedProperty = DependencyProperty.Register(nameof(IsMaximized), - typeof(bool), typeof(TitleBar), new PropertyMetadata(false)); - - /// - /// Property for . - /// - public static readonly DependencyProperty ApplicationNavigationProperty = - DependencyProperty.Register(nameof(ApplicationNavigation), typeof(bool), typeof(TitleBar), - new PropertyMetadata(false)); - - /// - /// Property for . - /// - public static readonly DependencyProperty ShowMaximizeProperty = DependencyProperty.Register( - nameof(ShowMaximize), - typeof(bool), typeof(TitleBar), new PropertyMetadata(true)); - - /// - /// Property for . - /// - public static readonly DependencyProperty ShowMinimizeProperty = DependencyProperty.Register( - nameof(ShowmMinimize), - typeof(bool), typeof(TitleBar), new PropertyMetadata(true)); - - /// - /// Property for . - /// - public static readonly DependencyProperty ShowCloseProperty = DependencyProperty.Register( - nameof(ShowClose), - typeof(bool), typeof(TitleBar), new PropertyMetadata(true)); - - /// - /// Property for - /// - public static readonly DependencyProperty ShowHelpProperty = DependencyProperty.Register( - nameof(ShowHelp), - typeof(bool), typeof(TitleBar), new PropertyMetadata(false)); - - /// - /// Property for - /// - public static readonly DependencyProperty CanMaximizeProperty = DependencyProperty.Register( - nameof(CanMaximize), - typeof(bool), typeof(TitleBar), new PropertyMetadata(true)); - - /// - /// Property for . - /// - public static readonly DependencyProperty IconProperty = DependencyProperty.Register( - nameof(Icon), - typeof(ImageSource), typeof(TitleBar), new PropertyMetadata(null)); - - /// - /// Property for . - /// - public static readonly DependencyProperty NotifyIconTooltipProperty = DependencyProperty.Register( - nameof(NotifyIconTooltip), - typeof(string), typeof(TitleBar), new PropertyMetadata(String.Empty, NotifyIconTooltip_OnChanged)); - - /// - /// Property for . - /// - public static readonly DependencyProperty NotifyIconImageProperty = DependencyProperty.Register( - nameof(NotifyIconImage), - typeof(ImageSource), typeof(TitleBar), new PropertyMetadata(null)); - - /// - /// Property for . - /// - public static readonly DependencyProperty UseNotifyIconProperty = DependencyProperty.Register( - nameof(UseNotifyIcon), - typeof(bool), typeof(TitleBar), new PropertyMetadata(false, UseNotifyIcon_OnChanged)); - - /// - /// Property for . - /// - public static readonly DependencyProperty NotifyIconMenuProperty = DependencyProperty.Register( - nameof(NotifyIconMenu), - typeof(ContextMenu), typeof(TitleBar), new PropertyMetadata(null, NotifyIconMenu_OnChanged)); - - /// - /// Routed event for . - /// - public static readonly RoutedEvent NotifyIconClickEvent = EventManager.RegisterRoutedEvent( - nameof(NotifyIconClick), RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TitleBar)); - - /// - /// Routed event for . - /// - public static readonly RoutedEvent NotifyIconDoubleClickEvent = EventManager.RegisterRoutedEvent( - nameof(NotifyIconDoubleClick), RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TitleBar)); - - /// - /// Routed event for . - /// - public static readonly RoutedEvent CloseClickedEvent = EventManager.RegisterRoutedEvent( - nameof(CloseClicked), RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TitleBar)); - - /// - /// Routed event for . - /// - public static readonly RoutedEvent MaximizeClickedEvent = EventManager.RegisterRoutedEvent( - nameof(MaximizeClicked), RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TitleBar)); - - /// - /// Routed event for . - /// - public static readonly RoutedEvent MinimizeClickedEvent = EventManager.RegisterRoutedEvent( - nameof(MinimizeClicked), RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TitleBar)); - - /// - /// Routed event for . - /// - public static readonly RoutedEvent HelpClickedEvent = EventManager.RegisterRoutedEvent( - nameof(HelpClicked), RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TitleBar)); - - /// - /// Property for . - /// - public static readonly DependencyProperty ButtonCommandProperty = - DependencyProperty.Register(nameof(ButtonCommand), - typeof(Common.IRelayCommand), typeof(TitleBar), new PropertyMetadata(null)); - - /// - /// Gets or sets title displayed on the left. - /// - public string Title - { - get => (string)GetValue(TitleProperty); - set => SetValue(TitleProperty, value); - } - - /// - /// Gets or sets information whether to minimize the application to tray. - /// - public bool MinimizeToTray - { - get => (bool)GetValue(MinimizeToTrayProperty); - set => SetValue(MinimizeToTrayProperty, value); - } - - /// - /// Gets or sets information whether the use Windows 11 Snap Layout. - /// - public bool UseSnapLayout - { - get => (bool)GetValue(UseSnapLayoutProperty); - set => SetValue(UseSnapLayoutProperty, value); - } - - /// - /// Gets or sets information whether the current window is maximized. - /// - public bool IsMaximized - { - get => (bool)GetValue(IsMaximizedProperty); - internal set => SetValue(IsMaximizedProperty, value); - } - - /// - /// Gets or sets information whether the controls affect main application window. - /// - public bool ApplicationNavigation - { - get => (bool)GetValue(ApplicationNavigationProperty); - set => SetValue(ApplicationNavigationProperty, value); - } - - /// - /// Gets or sets information whether to show maximize button. - /// - public bool ShowMaximize - { - get => (bool)GetValue(ShowMaximizeProperty); - set => SetValue(ShowMaximizeProperty, value); - } - - /// - /// Gets or sets information whether to show minimize button. - /// - public bool ShowMinimize - { - get => (bool)GetValue(ShowMinimizeProperty); - set => SetValue(ShowMinimizeProperty, value); - } - - /// - /// Gets or sets information whether to show close button. - /// - public bool ShowClose - { - get => (bool)SetValue(CanClose) - } - - /// - /// Gets or sets information whether to show help button - /// - public bool ShowHelp - { - get => (bool)GetValue(ShowHelpProperty); - set => SetValue(ShowHelpProperty, value); - } - - /// - /// Enables or disables the maximize functionality if disables the MaximizeActionOverride action won't be called - /// - public bool CanMaximize - { - get => (bool)GetValue(CanMaximizeProperty); - set => SetValue(CanMaximizeProperty, value); - } - - /// - /// Titlebar icon. - /// - public ImageSource Icon - { - get => (ImageSource)GetValue(IconProperty); - set => SetValue(IconProperty, value); - } - - /// - /// Gets or sets text displayed when hover NotifyIcon in system tray. - /// - public string NotifyIconTooltip - { - get => (string)GetValue(NotifyIconTooltipProperty); - set => SetValue(NotifyIconTooltipProperty, value); - } - - /// - /// BitmapSource of tray icon. - /// - public ImageSource NotifyIconImage - { - get => (ImageSource)GetValue(NotifyIconImageProperty); - set => SetValue(NotifyIconImageProperty, value); - } - - /// - /// Gets or sets information whether to use shell icon with menu in system tray. - /// - public bool UseNotifyIcon - { - get => (bool)GetValue(UseNotifyIconProperty); - set => SetValue(UseNotifyIconProperty, value); - } - - /// - /// Menu displayed when left click on NotifyIcon. - /// - public ContextMenu NotifyIconMenu - { - get => (ContextMenu)GetValue(NotifyIconMenuProperty); - set => SetValue(NotifyIconMenuProperty, value); - } - - /// - /// Event triggered after clicking the left mouse button on the tray icon. - /// - public event RoutedEventHandler NotifyIconClick - { - add => AddHandler(NotifyIconClickEvent, value); - remove => RemoveHandler(NotifyIconClickEvent, value); - } - - /// - /// Event triggered after double-clicking the left mouse button on the tray icon. - /// - public event RoutedEventHandler NotifyIconDoubleClick - { - add => AddHandler(NotifyIconDoubleClickEvent, value); - remove => RemoveHandler(NotifyIconDoubleClickEvent, value); - } - - /// - /// Event triggered after clicking close button. - /// - public event RoutedEventHandler CloseClicked - { - add => AddHandler(CloseClickedEvent, value); - remove => RemoveHandler(CloseClickedEvent, value); - } - - /// - /// Event triggered after clicking maximize or restore button. - /// - public event RoutedEventHandler MaximizeClicked - { - add => AddHandler(MaximizeClickedEvent, value); - remove => RemoveHandler(MaximizeClickedEvent, value); - } - - /// - /// Event triggered after clicking minimize button. - /// - public event RoutedEventHandler MinimizeClicked - { - add => AddHandler(MinimizeClickedEvent, value); - remove => RemoveHandler(MinimizeClickedEvent, value); - } - - /// - /// Event triggered after clicking help button - /// - public event RoutedEventHandler HelpClicked - { - add => AddHandler(HelpClickedEvent, value); - remove => RemoveHandler(HelpClickedEvent, value); - } - - /// - /// Command triggered after clicking the titlebar button. - /// - public Common.IRelayCommand ButtonCommand => (Common.IRelayCommand)GetValue(ButtonCommandProperty); - - /// - /// Lets you override the behavior of the Close button with an . - /// - public Action CloseActionOverride { get; set; } = null; - - /// - /// Lets you override the behavior of the Maximize/Restore button with an . - /// - public Action MaximizeActionOverride { get; set; } = null; - - /// - /// Lets you override the behavior of the Minimize button with an . - /// - public Action MinimizeActionOverride { get; set; } = null; - - private Window ParentWindow => _parent ??= Window.GetWindow(this); - - /// - /// Creates a new instance of the class and sets the default event. - /// - public TitleBar() - { - SetValue(ButtonCommandProperty, new Common.RelayCommand(o => TemplateButton_OnClick(this, o))); - - Loaded += TitleBar_Loaded; - } - - /// - /// Resets icon. - /// - public void ResetIcon() - { - if (_notifyIcon != null) - _notifyIcon.Destroy(); - - InitializeNotifyIcon(); - } - - private void CloseWindow() - { - if (CloseActionOverride != null) - { - CloseActionOverride(this, _parent); - - return; - } - - if (ApplicationNavigation) - Application.Current.Shutdown(); - else - ParentWindow.Close(); - } - - private void MinimizeWindow() - { - if (MinimizeToTray && UseNotifyIcon && MinimizeWindowToTray()) return; - - if (MinimizeActionOverride != null) - { - MinimizeActionOverride(this, _parent); - - return; - } - - ParentWindow.WindowState = WindowState.Minimized; - } - - private void MaximizeWindow() - { - if (!CanMaximize) - return; - - if (MaximizeActionOverride != null) - { - MaximizeActionOverride(this, _parent); - - return; - } - - if (ParentWindow.WindowState == WindowState.Normal) - { - IsMaximized = true; - ParentWindow.WindowState = WindowState.Maximized; - } - else - { - IsMaximized = false; - ParentWindow.WindowState = WindowState.Normal; - } - } - - private void InitializeNotifyIcon() - { - if (DesignerProperties.GetIsInDesignMode(new DependencyObject())) return; - - NotifyIconClick += OnNotifyIconClick; - - _notifyIcon = new() - { - Parent = this, - Tooltip = NotifyIconTooltip, - ContextMenu = NotifyIconMenu, - Icon = NotifyIconImage, - Click = icon => { RaiseEvent(new RoutedEventArgs(NotifyIconClickEvent, this)); }, - DoubleClick = icon => { RaiseEvent(new RoutedEventArgs(NotifyIconDoubleClickEvent, this)); } - }; - - _notifyIcon.Show(); - } - - private bool MinimizeWindowToTray() - { - if (_notifyIcon == null) - return false; - - ParentWindow.WindowState = WindowState.Minimized; - ParentWindow.Hide(); - - return true; - } - - private void OnNotifyIconClick(object sender, RoutedEventArgs e) - { - if (!MinimizeToTray) return; - - if (ParentWindow.WindowState != WindowState.Minimized) return; - - ParentWindow.Show(); - ParentWindow.WindowState = WindowState.Normal; - - ParentWindow.Topmost = true; - ParentWindow.Topmost = false; - - Focus(); - } - - private void InitializeSnapLayout(WPFUI.Controls.Button maximizeButton) - { - if (!Common.SnapLayout.IsSupported()) return; - - _snapLayout = new Common.SnapLayout(); - _snapLayout.Register(maximizeButton); - } - - private void TitleBar_Loaded(object sender, RoutedEventArgs e) - { - if (UseNotifyIcon) - InitializeNotifyIcon(); - - // It may look ugly, but at the moment it works surprisingly well - - var maximizeButton = (WPFUI.Controls.Button)Template.FindName("ButtonMaximize", this); - - if (maximizeButton != null && UseSnapLayout) - InitializeSnapLayout(maximizeButton); - - var rootGrid = (System.Windows.Controls.Grid)Template.FindName("RootGrid", this); - - if (rootGrid != null) - { - rootGrid.MouseLeftButtonDown += RootGrid_MouseLeftButtonDown; - rootGrid.MouseMove += RootGrid_MouseMove; - } - - if (ParentWindow != null) - ParentWindow.StateChanged += ParentWindow_StateChanged; - } - - private void RootGrid_MouseMove(object sender, MouseEventArgs e) - { - if (e.LeftButton != MouseButtonState.Pressed || ParentWindow == null) return; - - // prevent firing from double clicking when the mouse never actually moved - User32.GetCursorPos(out var currentMousePos); - - if (currentMousePos.X == _doubleClickPoint.X && currentMousePos.Y == _doubleClickPoint.Y) return; - - if (IsMaximized) - { - var screenPoint = PointToScreen(e.MouseDevice.GetPosition(this)); - screenPoint.X /= Common.Dpi.SystemDpiXScale(); - screenPoint.Y /= Common.Dpi.SystemDpiYScale(); - - // TODO: refine the Left value to be more accurate - // - This calculation is good enough using the center - // of the titlebar, however this isn't quite accurate for - // how the OS operates. - // - It should be set as a % (e.g. screen X / maximized width), - // then offset from the left to line up more naturally. - ParentWindow.Left = screenPoint.X - (ParentWindow.RestoreBounds.Width * 0.5); - ParentWindow.Top = screenPoint.Y; - - // style has to be quickly swapped to avoid restore animation delay - var style = ParentWindow.WindowStyle; - ParentWindow.WindowStyle = WindowStyle.None; - ParentWindow.WindowState = WindowState.Normal; - ParentWindow.WindowStyle = style; - } - - // Call drag move only when mouse down, check again - // if() - if(e.LeftButton == MouseButtonState.Pressed) - { - ParentWindow.DragMove(); - } - } - - private void ParentWindow_StateChanged(object sender, EventArgs e) - { - if (ParentWindow == null) return; - - if (IsMaximized != (ParentWindow.WindowState == WindowState.Maximized)) - IsMaximized = ParentWindow.WindowState == WindowState.Maximized; - } - - private void RootGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - if (e.ClickCount != 2) return; - - User32.GetCursorPos(out _doubleClickPoint); - - MaximizeWindow(); - } - - private void TemplateButton_OnClick(TitleBar sender, object parameter) - { - string command = parameter as string; - - switch (command) - { - case "close": - RaiseEvent(new RoutedEventArgs(CloseClickedEvent, this)); - CloseWindow(); - break; - - case "minimize": - RaiseEvent(new RoutedEventArgs(MinimizeClickedEvent, this)); - MinimizeWindow(); - break; - - case "maximize": - RaiseEvent(new RoutedEventArgs(MaximizeClickedEvent, this)); - MaximizeWindow(); - break; - case "help": - RaiseEvent(new RoutedEventArgs(HelpClickedEvent, this)); - break; - } - } - - private static void NotifyIconTooltip_OnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - if (d is not TitleBar { UseNotifyIcon: true } titleBar) return; - - titleBar.ResetIcon(); - } - - private static void UseNotifyIcon_OnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - if (d is not TitleBar titleBar) return; - - if (titleBar.UseNotifyIcon) - titleBar.ResetIcon(); - else - titleBar._notifyIcon.Destroy(); - } - - private static void NotifyIconMenu_OnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - //if (d is not TitleBar titleBar) return; - - //if (titleBar.UseNotifyIcon == false) - //{ - // return; - //} - - //titleBar.ResetIcon(); - } - } -} \ No newline at end of file From f17b17f16bd9b6eca4ca0942c197159b2b3306d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannes=20Str=C3=B6hlein?= Date: Tue, 26 Jul 2022 12:16:43 +0200 Subject: [PATCH 4/5] - removed test code --- src/Wpf.Ui.Demo/Views/Container.xaml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Wpf.Ui.Demo/Views/Container.xaml b/src/Wpf.Ui.Demo/Views/Container.xaml index 502fba55a..55ec6d9ea 100644 --- a/src/Wpf.Ui.Demo/Views/Container.xaml +++ b/src/Wpf.Ui.Demo/Views/Container.xaml @@ -195,7 +195,6 @@ Date: Wed, 27 Jul 2022 00:03:21 +0200 Subject: [PATCH 5/5] - fixed old name in cref --- src/Wpf.Ui/Controls/TitleBar.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Wpf.Ui/Controls/TitleBar.cs b/src/Wpf.Ui/Controls/TitleBar.cs index fb6f919cc..ee5eaeea7 100644 --- a/src/Wpf.Ui/Controls/TitleBar.cs +++ b/src/Wpf.Ui/Controls/TitleBar.cs @@ -110,7 +110,7 @@ public class TitleBar : System.Windows.Controls.Control, IThemeControl typeof(bool), typeof(TitleBar), new PropertyMetadata(true)); /// - /// Property for . + /// Property for . /// public static readonly DependencyProperty ShowCloseProperty = DependencyProperty.Register( nameof(ShowClose),