资源文件代码:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <!-- 最大化按钮形状 --> <PathGeometry x:Key="pathMaximize"> <PathGeometry.Figures> M1,1 L1 ,11 L11,11 L11,1 z M0,0 L12,0 L12,12 L0,12 z </PathGeometry.Figures> </PathGeometry> <!-- 还原按钮形状 --> <PathGeometry x:Key="pathRestore"> <PathGeometry.Figures> M1,3 L1,11 L9,11 L9,3 z M3,1 L3,2 L10,2 L10,9 L11,9 L11,1 z M2 ,0 L12,0 L12,10 L10,10 L10,12 L0,12 L0,2 L2 ,2 z </PathGeometry.Figures> </PathGeometry> <!-- 窗体模板 --> <ControlTemplate x:Key="tmplWindowEx" TargetType="{x:Type Window}"> <Border> <Border CornerRadius="5" Background="#0998B8" Margin="{Binding BorderMargin}"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="28"></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <TextBlock Text="{TemplateBinding Title}" Margin="10 0 0 0" FontFamily="微软雅黑,黑体" FontSize="12" Foreground="#fff" VerticalAlignment="Center"></TextBlock> <!-- Border用于遮盖Title --> <Border Margin="88 0 0 0" CornerRadius="0 5 0 0" Background="#0998B8" Width="90" HorizontalAlignment="{Binding BtnPanelHorizontalAlignment}"></Border> <StackPanel Orientation="Horizontal" HorizontalAlignment="{Binding BtnPanelHorizontalAlignment}" Margin="98 0 5 0"> <Button x:Name="btnMinimize" Width="28" Height="28" WindowChrome.IsHitTestVisibleInChrome="True" Command="{Binding DataContext.WindowBtnCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="1" Visibility="{Binding BtnMinimizeVisibility}" > <Button.Template> <ControlTemplate> <Grid x:Name="grid" Background="Transparent"> <Path x:Name="path1" Width="12" Height="12" Fill="#fff" Data="M0,5 L12,5 L12,6 L0,6 z" VerticalAlignment="Center" HorizontalAlignment="Center"></Path> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="true"> <Setter TargetName="grid" Property="Background" Value="#0988a8"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Button.Template> </Button> <Button x:Name="btnMaximize" Width="28" Height="28" WindowChrome.IsHitTestVisibleInChrome="True" Command="{Binding DataContext.WindowBtnCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="2" Visibility="{Binding BtnMaximizeVisibility}" > <Button.Template> <ControlTemplate> <Grid x:Name="grid" Background="Transparent"> <Path x:Name="path1" Width="12" Height="12" Fill="#fff" Data="{Binding BtnMaximizePathData}" VerticalAlignment="Center" HorizontalAlignment="Center" ></Path> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="true"> <Setter TargetName="grid" Property="Background" Value="#0988a8"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Button.Template> </Button> <Button x:Name="btnClose" Width="28" Height="28" WindowChrome.IsHitTestVisibleInChrome="True" Command="{Binding DataContext.WindowBtnCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="3"> <Button.Template> <ControlTemplate> <Grid x:Name="grid" Background="Transparent"> <Path x:Name="path1" Width="12" Height="12" Fill="#fff" Data="M1,0 L6,5 L11,0 L12,1 L7,6 L12,11 L11,12 L6,7 L1,12 L0,11 L5,6 L0,1 z" VerticalAlignment="Center" HorizontalAlignment="Center" ></Path> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="true"> <Setter TargetName="grid" Property="Background" Value="#0988a8"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Button.Template> </Button> </StackPanel> <Border Background="#d6e7f1" CornerRadius="3 0 3 3" Grid.Row="1" Margin="3 0 3 3" > <ContentPresenter ></ContentPresenter> </Border> </Grid> </Border> </Border> </ControlTemplate> <!-- 窗体样式 --> <Style x:Key="stlWindowEx" TargetType="{x:Type Window}"> <Setter Property="Template" Value="{StaticResource tmplWindowEx}"/> <!--在代码中设置AllowsTransparency和WindowStyle--> <!--<Setter Property="AllowsTransparency" Value="True"></Setter>--> <!--<Setter Property="WindowStyle" Value="None" />--> <Setter Property="Background" Value="Transparent"></Setter> <Setter Property="BorderThickness" Value="0" /> <Setter Property="BorderBrush" Value="Transparent" /> <Setter Property="ResizeMode" Value="NoResize" /> <Setter Property="ShowInTaskbar" Value="False" /> <Setter Property="WindowChrome.WindowChrome"> <Setter.Value> <WindowChrome CornerRadius="5" CaptionHeight="28" GlassFrameThickness="0" UseAeroCaptionButtons="False" NonClientFrameEdges="None"> </WindowChrome> </Setter.Value> </Setter> </Style> </ResourceDictionary>
自定义窗体封装WindowEx类代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Reflection; using System.Resources; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using System.Windows.Media; using System.Windows.Resources; using System.Windows.Shapes; namespace SunCreate.Common.Controls { /// <summary> /// 窗体封装 /// </summary> public class WindowEx : Window, INotifyPropertyChanged { public event EventHandler<WindowExFixEventArgs> FixEvent; private ResourceDictionary _resource; private ICommand _WindowBtnCommand; /// <summary> /// 窗体按钮命令 /// </summary> public ICommand WindowBtnCommand { get { return _WindowBtnCommand; } set { _WindowBtnCommand = value; OnPropertyChanged("WindowBtnCommand"); } } private Thickness _BorderMargin = new Thickness(0, 0, 0, 0); public Thickness BorderMargin { get { return _BorderMargin; } set { _BorderMargin = value; OnPropertyChanged("BorderMargin"); } } private HorizontalAlignment _BtnPanelHorizontalAlignment = HorizontalAlignment.Right; /// <summary> /// 窗体按钮的Panel位置 /// </summary> public HorizontalAlignment BtnPanelHorizontalAlignment { get { return _BtnPanelHorizontalAlignment; } set { _BtnPanelHorizontalAlignment = value; OnPropertyChanged("BtnPanelHorizontalAlignment"); } } private Visibility _BtnMinimizeVisibility = Visibility.Visible; /// <summary> /// 窗体最小化按钮的显示状态 /// </summary> public Visibility BtnMinimizeVisibility { get { return _BtnMinimizeVisibility; } set { _BtnMinimizeVisibility = value; OnPropertyChanged("BtnMinimizeVisibility"); } } private Visibility _BtnMaximizeVisibility = Visibility.Visible; /// <summary> /// 窗体最大化按钮的显示状态 /// </summary> public Visibility BtnMaximizeVisibility { get { return _BtnMaximizeVisibility; } set { _BtnMaximizeVisibility = value; OnPropertyChanged("BtnMaximizeVisibility"); } } private Geometry _BtnMaximizePathData; /// <summary> /// 窗体最大化按钮的样式 /// </summary> public Geometry BtnMaximizePathData { get { return _BtnMaximizePathData; } set { _BtnMaximizePathData = value; OnPropertyChanged("BtnMaximizePathData"); } } private Visibility _TitleVisibility = Visibility.Visible; /// <summary> /// 是否显示标题 /// </summary> public Visibility TitleVisibility { get { return _TitleVisibility; } set { _TitleVisibility = value; OnPropertyChanged("TitleVisibility"); } } private WindowExTheme _Theme = WindowExTheme.Default; /// <summary> /// 窗体主题 /// </summary> public WindowExTheme Theme { get { return _Theme; } set { _Theme = value; OnPropertyChanged("Theme"); } } /// <summary> /// 窗体 构造函数 /// </summary> public WindowEx() { this.Loaded += WindowEx_Loaded; this.DataContext = this; #region 窗体样式设置 //this.AllowsTransparency = true; //AllowsTransparency会导致视频播放不显示 this.WindowStyle = WindowStyle.None; #endregion #region 窗体按钮事件 WindowBtnCommand windowBtnCommand = new WindowBtnCommand(); windowBtnCommand.DoAction = (parameter) => { if (parameter == 1) //最小化 { MinimizedSet(); this.WindowState = WindowState.Minimized; } if (parameter == 2) //窗口还原、最大化 { if (this.WindowState == WindowState.Normal) { MaximizedSet(); this.WindowState = WindowState.Maximized; } else if (this.WindowState == WindowState.Maximized) { RestoredSet(); this.WindowState = WindowState.Normal; } else if (this.WindowState == WindowState.Minimized) { RestoredSet(); this.WindowState = WindowState.Normal; } } if (parameter == 3) //关闭窗口 { this.Close(); } if (parameter == 4) //固定窗口 { if (FixEvent != null) { WindowExFixEventArgs args = new WindowExFixEventArgs(this.Content); FixEvent(this, args); } } }; this.WindowBtnCommand = windowBtnCommand; this.StateChanged += (s, e) => { if (this.WindowState == WindowState.Maximized) { MaximizedSet(); } if (this.WindowState == WindowState.Normal) { RestoredSet(); } if (this.WindowState == WindowState.Minimized) { MinimizedSet(); } }; #endregion } /// <summary> /// 窗体Loaded /// </summary> private void WindowEx_Loaded(object sender, RoutedEventArgs e) { #region 窗体样式设置 Uri uri = null; switch (Theme) { case WindowExTheme.Default: uri = new Uri("/SunCreate.Common.Controls;Component/WindowEx/WindowExResource.xaml", UriKind.Relative); break; case WindowExTheme.MessageBox: uri = new Uri("/SunCreate.Common.Controls;Component/WindowEx/MessageBoxExResource.xaml", UriKind.Relative); break; case WindowExTheme.TabContainer: uri = new Uri("/SunCreate.Common.Controls;Component/WindowEx/TabContainerResource.xaml", UriKind.Relative); break; } _resource = new ResourceDictionary(); _resource.Source = uri; this.Style = _resource["stlWindowEx"] as Style; if (this.WindowState == WindowState.Maximized) { this.BtnMaximizePathData = _resource["pathRestore"] as PathGeometry; } else { this.BtnMaximizePathData = _resource["pathMaximize"] as PathGeometry; } #endregion #region 最大化设置 if (this.WindowState == WindowState.Maximized) { this.BorderMargin = CalculateWinMargin(true); } #endregion } #region 最小化设置 private void MinimizedSet() { this.BorderMargin = new Thickness(0, 0, 0, 0); BtnPanelHorizontalAlignment = HorizontalAlignment.Left; BtnMinimizeVisibility = Visibility.Collapsed; if (this.Content != null) (this.Content as FrameworkElement).Visibility = Visibility.Collapsed; //最小化时隐藏Content if (this.Theme == WindowExTheme.TabContainer) TitleVisibility = Visibility.Visible; this.BtnMaximizePathData = _resource["pathRestore"] as PathGeometry; } #endregion #region 还原设置 private void RestoredSet() { this.BorderMargin = new Thickness(0, 0, 0, 0); BtnPanelHorizontalAlignment = HorizontalAlignment.Right; BtnMinimizeVisibility = Visibility.Visible; if (this.Content != null) (this.Content as FrameworkElement).Visibility = Visibility.Visible; //最大化或还原时显示Content this.BtnMaximizePathData = _resource["pathMaximize"] as PathGeometry; if (this.Theme == WindowExTheme.TabContainer) TitleVisibility = Visibility.Collapsed; } #endregion #region 最大化设置 private void MaximizedSet() { this.BorderMargin = CalculateWinMargin(false); BtnPanelHorizontalAlignment = HorizontalAlignment.Right; BtnMinimizeVisibility = Visibility.Visible; if (this.Content != null) (this.Content as FrameworkElement).Visibility = Visibility.Visible; //最大化或还原时显示Content this.BtnMaximizePathData = _resource["pathRestore"] as PathGeometry; if (this.Theme == WindowExTheme.TabContainer) TitleVisibility = Visibility.Collapsed; } #endregion #region 计算窗体Margin大小 /// <summary> /// 计算窗体Margin大小 /// </summary> private Thickness CalculateWinMargin(bool firstLoad = false) { double taskBarHeight = SystemParameters.PrimaryScreenHeight - SystemParameters.WorkArea.Height; double taskBarWidth = SystemParameters.PrimaryScreenWidth - SystemParameters.WorkArea.Width; if (this.Theme == WindowExTheme.TabContainer || firstLoad) { if (taskBarWidth > 0) { return new Thickness(7, 7, taskBarWidth + 7, 7); } if (taskBarHeight > 0) { return new Thickness(7, 7, 7, taskBarHeight + 7); } return new Thickness(7, 7, 7, 7); } else { if (taskBarWidth > 0) { return new Thickness(0, 0, taskBarWidth, 0); } if (taskBarHeight > 0) { return new Thickness(0, 0, 0, taskBarHeight); } return new Thickness(0, 0, 0, 0); } } #endregion #region 实现INotifyPropertyChanged接口 public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string name) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(name)); } } #endregion } }
窗体最小化、最大化、关闭按钮的命令WindowBtnCommand:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Input; namespace SunCreate.Common.Controls { public class WindowBtnCommand : ICommand { public Action<int> DoAction { get; set; } public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public bool CanExecute(object parameter) { return true; } public void Execute(object parameter) { if (DoAction != null) { DoAction(Convert.ToInt32(parameter)); } } } }
使用WindowEx类的示例代码:
<ui:WindowEx x:Class="SunCreate.Common.Controls.Demo.MyWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ui="clr-namespace:SunCreate.Common.Controls;assembly=SunCreate.Common.Controls" Title="视频播放视频播放ABCDEFG" Height="300" Width="500" WindowStartupLocation="CenterScreen" BtnMinimizeVisibility="Visible" BtnMaximizeVisibility="Visible" > <Window.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="/SunCreate.Common.Controls;Component/Themes/ScrollViewer.xaml"/> <ResourceDictionary Source="/SunCreate.Common.Controls;Component/Themes/ControlsResource.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Window.Resources> <Grid> <StackPanel> <Border Margin="10"> <Button Height="30" Width="80" Content="测试" Style="{StaticResource stlTxtBtn}" HorizontalAlignment="Left" Click="Button_Click" /> </Border> <Border Margin="10"> <TextBlock Text="测试内容ABC"></TextBlock> </Border> </StackPanel> </Grid> </ui:WindowEx>
效果图:
窗体最小化效果图: