WPF 基础控件之Window样式

WPF开发者QQ群: 340500857

       由于微信群人数太多入群请添加小编微信号

 yanjinhuawechatW_Feng_aiQ 邀请入群

 需备注WPF开发者 

  PS:有更好的方式欢迎推荐。

01

代码如下

一、创建 Window.cs继承System.Windows.Window代码如下。

      在WPF自定义类库时需要注意在创建自定义Window时 默认新建的资源文件会找不到Style导致Window打开会成为黑色窗体解决方案有两种如下:

1)通过Style的Key去资源字典找到并替换窗体元数据。

static T GetResourceKey<T>(string key)
        {
            if (Application.Current.TryFindResource(key) is T resource)
            {
                return resource;
            }

            return default;
        }

2)直接对自定义库下的Themes文件夹下Generic.xaml资源写自定义Window的样式即可。

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;

namespace WPFDevelopers.Minimal.Net45x
{
    public class Window : System.Windows.Window
    {

        public double TitleHeight
        {
            get { return (double)GetValue(TitleHeightProperty); }
            set { SetValue(TitleHeightProperty, value); }
        }

        public static readonly DependencyProperty TitleHeightProperty =
            DependencyProperty.Register("TitleHeight", typeof(double), typeof(Window), new PropertyMetadata(50d));

        static Window()
        {
            StyleProperty.OverrideMetadata(typeof(Window), new FrameworkPropertyMetadata(GetResourceKey<Style>("WPFDevelopersWindow")));
        }
        static T GetResourceKey<T>(string key)
        {
            if (Application.Current.TryFindResource(key) is T resource)
            {
                return resource;
            }

            return default;
        }
        public Window()
        {
            this.Loaded += Window_Loaded;
            CommandBindings.Add(new CommandBinding(SystemCommands.CloseWindowCommand, CloseWindow));
            CommandBindings.Add(new CommandBinding(SystemCommands.MaximizeWindowCommand, MaximizeWindow, CanResizeWindow));
            CommandBindings.Add(new CommandBinding(SystemCommands.MinimizeWindowCommand, MinimizeWindow, CanMinimizeWindow));
            CommandBindings.Add(new CommandBinding(SystemCommands.RestoreWindowCommand, RestoreWindow, CanResizeWindow));
            //CommandBindings.Add(new CommandBinding(SystemCommands.ShowSystemMenuCommand, ShowSystemMenu));
        }
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            hWnd = new WindowInteropHelper(this).Handle;
            HwndSource.FromHwnd(hWnd).AddHook(WindowProc);
        }
        protected override void OnContentRendered(EventArgs e)
        {
            base.OnContentRendered(e);
            if (SizeToContent == SizeToContent.WidthAndHeight)
                InvalidateMeasure();
        }

        #region Window Commands

        private void CanResizeWindow(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = ResizeMode == ResizeMode.CanResize || ResizeMode == ResizeMode.CanResizeWithGrip;
        }

        private void CanMinimizeWindow(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = ResizeMode != ResizeMode.NoResize;
        }

        private void CloseWindow(object sender, ExecutedRoutedEventArgs e)
        {
            //Close();
            SystemCommands.CloseWindow(this);
        }

        private void MaximizeWindow(object sender, ExecutedRoutedEventArgs e)
        {
            SystemCommands.MaximizeWindow(this);
        }

        private void MinimizeWindow(object sender, ExecutedRoutedEventArgs e)
        {
            //SystemCommands.MinimizeWindow(this);
            SendMessage(hWnd, ApiCodes.WM_SYSCOMMAND, new IntPtr(ApiCodes.SC_MINIMIZE), IntPtr.Zero);
        }

        private void RestoreWindow(object sender, ExecutedRoutedEventArgs e)
        {
            SystemCommands.RestoreWindow(this);
        }
        internal class ApiCodes
        {
            public const int SC_RESTORE = 0xF120;
            public const int SC_MINIMIZE = 0xF020;
            public const int WM_SYSCOMMAND = 0x0112;
        }
        private IntPtr hWnd;

        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
        private IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            if (msg == ApiCodes.WM_SYSCOMMAND)
            {
                if (wParam.ToInt32() == ApiCodes.SC_MINIMIZE)
                {
                    WindowStyle = WindowStyle.SingleBorderWindow;
                    WindowState = WindowState.Minimized;
                    handled = true;
                }
                else if (wParam.ToInt32() == ApiCodes.SC_RESTORE)
                {
                    WindowState = WindowState.Normal;
                    WindowStyle = WindowStyle.None;
                    handled = true;
                }
            }
            return IntPtr.Zero;
        }
        private void ShowSystemMenu(object sender, ExecutedRoutedEventArgs e)
        {
            var element = e.OriginalSource as FrameworkElement;
            if (element == null)
                return;

            var point = WindowState == WindowState.Maximized ? new Point(0, element.ActualHeight)
                : new Point(Left + BorderThickness.Left, element.ActualHeight + Top + BorderThickness.Top);
            point = element.TransformToAncestor(this).Transform(point);
            SystemCommands.ShowSystemMenu(this, point);
        }

        #endregion

    }
}

二、创建资源字典Window.xaml。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                    xmlns:wpfdev="clr-namespace:WPFDevelopers.Minimal.Net45x" >
    <Style x:Key="WindowButtonStyle" TargetType="{x:Type Button}">
        <Setter Property="Foreground" Value="{DynamicResource PrimaryTextSolidColorBrush}"/>
        <Setter Property="Padding" Value="3"/>
        <Setter Property="Margin" Value="0"/>
        <Setter Property="MinWidth" Value="30"/>
        <Setter Property="MinHeight" Value="28"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="Cursor" Value="Hand"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid Background="Transparent">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="MouseOver">
                                    <Storyboard>
                                        <DoubleAnimation Duration="0" To="1" 
                                                         Storyboard.TargetProperty="(UIElement.Opacity)"
                                                         Storyboard.TargetName="PART_ContentPresenter" />
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Pressed">
                                    <Storyboard>
                                        <DoubleAnimation Duration="0" To="1" 
                                                         Storyboard.TargetProperty="(UIElement.Opacity)" 
                                                         Storyboard.TargetName="PART_ContentPresenter" />
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Disabled">
                                    <Storyboard>
                                        <DoubleAnimation Duration="0" To="0.3" 
                                                         Storyboard.TargetProperty="(UIElement.Opacity)"
                                                         Storyboard.TargetName="PART_ContentPresenter"/>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="FocusStates">
                                <VisualState x:Name="Focused"/>
                                <VisualState x:Name="Unfocused"/>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Rectangle Fill="Transparent"/>
                        <ContentPresenter x:Name="PART_ContentPresenter" Opacity="0.7" 
                                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                          Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                                          Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style x:Key="WPFDevelopersWindow" TargetType="{x:Type wpfdev:Window}" BasedOn="{x:Null}">
        <Setter Property="Foreground" Value="{DynamicResource PrimaryTextSolidColorBrush}" />
        <Setter Property="Background"  Value="{DynamicResource WhiteSolidColorBrush}" />
        <Setter Property="BorderBrush" Value="{DynamicResource PrimaryNormalSolidColorBrush}" />
        <Setter Property="BorderThickness"  Value="1" />
        <Setter Property="IsTabStop"  Value="False" />
        <Setter Property="ResizeMode" Value="CanResizeWithGrip" />
        <Setter Property="SnapsToDevicePixels" Value="True"/>
        <Setter Property="UseLayoutRounding" Value="True" />
        <Setter Property="TextOptions.TextFormattingMode" Value="Ideal" />
        <Setter Property="WindowStyle"  Value="None" />
        <Setter Property="MaxHeight" Value="{x:Static SystemParameters.MaximizedPrimaryScreenHeight}"/>
        <Setter Property="MaxWidth" Value="{x:Static SystemParameters.MaximizedPrimaryScreenWidth}"/>
        <Setter Property="FontFamily" Value="{DynamicResource NormalFontFamily}" />
        <Setter Property="WindowChrome.WindowChrome">
            <Setter.Value>
                <WindowChrome  GlassFrameThickness="0,0,0,1" 
                               UseAeroCaptionButtons="False"
                               CaptionHeight="{Binding TitleHeight,RelativeSource={RelativeSource AncestorType=wpfdev:Window}}"/>
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type wpfdev:Window}">
                    <Border BorderBrush="{TemplateBinding BorderBrush}" 
                            BorderThickness="{TemplateBinding BorderThickness}"
                            SnapsToDevicePixels="True">
                        <Grid Background="{TemplateBinding Background}">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="*" />
                                <RowDefinition Height="Auto" />
                            </Grid.RowDefinitions>
                            <Grid Grid.Row="0" Height="{TemplateBinding TitleHeight}" 
                                  Background="{TemplateBinding BorderBrush}">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="Auto" MinWidth="30"/>
                                </Grid.ColumnDefinitions>
                                <Image Source="{TemplateBinding Icon}" Stretch="Fill"
                                    VerticalAlignment="Center" HorizontalAlignment="Left" Width="30" Height="30" Margin="14,0,4,0"
                                    RenderOptions.BitmapScalingMode="HighQuality"/>
                                <TextBlock Text="{TemplateBinding Title}" x:Name="PART_Title"
                                       Foreground="{DynamicResource WhiteSolidColorBrush}" Grid.Column="1"
                                       VerticalAlignment="Center" FontSize="{DynamicResource TitleFontSize}"/>
                                <WrapPanel Grid.Column="2" WindowChrome.IsHitTestVisibleInChrome="True">
                                    <WrapPanel x:Name="PART_MinAndMax">
                                        <Button Name="PART_MinimizeButton"  IsTabStop="False"   Padding="0" Margin="0,6" 
                                            Style="{StaticResource WindowButtonStyle}" ToolTip="Minimize"
                                            Command="SystemCommands.MinimizeWindowCommand">
                                            <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
                                                <Rectangle x:Name="MinimizeGlyph"  Width="10"  Height="1"   Margin="0 7 0 0" 
                                                   VerticalAlignment="Bottom" Fill="{DynamicResource WhiteSolidColorBrush}" />
                                            </Grid>
                                        </Button>
                                        <Button Name="PART_MaximizeButton" IsTabStop="False"  Padding="0"
                                            Style="{StaticResource WindowButtonStyle}" Margin="0,6"
                                            ToolTip="Maximize"
                                            Command="SystemCommands.MaximizeWindowCommand">
                                            <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
                                                <Path Width="10" Height="10"
                                              HorizontalAlignment="Center" VerticalAlignment="Center" 
                                              Data="{DynamicResource PathMetroWindowMaximize}" Fill="{DynamicResource WhiteSolidColorBrush}"
                                              Stretch="Fill" UseLayoutRounding="False" />
                                            </Grid>
                                        </Button>
                                        <Button Name="PART_RestoreButton" IsTabStop="False"  Padding="0"
                                            Style="{StaticResource WindowButtonStyle}" Margin="0,6"
                                            ToolTip="Restore"
                                            Command="SystemCommands.RestoreWindowCommand"
                                            Visibility="Collapsed">
                                            <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
                                                <Path Width="10" Height="10"
                                              HorizontalAlignment="Center" VerticalAlignment="Center" 
                                              Data="{DynamicResource PathMetroWindowRestore}" Fill="{DynamicResource WhiteSolidColorBrush}"
                                              Stretch="Fill" UseLayoutRounding="False" />
                                            </Grid>
                                        </Button>
                                    </WrapPanel>

                                    <Button Name="PART_CloseButton" Margin="0,6" 
                                            ToolTip="Close"
                                            IsTabStop="False" Style="{StaticResource WindowButtonStyle}"
                                            Command="SystemCommands.CloseWindowCommand">
                                        <Path Width="10" Height="10"
                              HorizontalAlignment="Center"
                              VerticalAlignment="Center"
                              Data="{DynamicResource PathMetroWindowClose}"
                              Fill="{DynamicResource WhiteSolidColorBrush}"
                              Stretch="Fill" />
                                    </Button>
                                </WrapPanel>
                            </Grid>
                            <AdornerDecorator Grid.Row="1" KeyboardNavigation.IsTabStop="False"
                                              Margin="4">
                                <ContentPresenter x:Name="MainContentPresenter"/>
                            </AdornerDecorator>
                            <ResizeGrip x:Name="ResizeGrip" 
                                        HorizontalAlignment="Right" 
                                        VerticalAlignment="Bottom" 
                                        Grid.Row="2" IsTabStop="False"
                                        Visibility="Collapsed"/>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="WindowState" Value="Maximized">
                            <Setter Property="Visibility" Value="Visible" TargetName="PART_RestoreButton"/>
                            <Setter Property="Visibility" Value="Collapsed" TargetName="PART_MaximizeButton"/>
                        </Trigger>

                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="ResizeMode"  Value="CanResizeWithGrip" />
                                <Condition Property="WindowState"  Value="Normal" />
                            </MultiTrigger.Conditions>
                            <Setter TargetName="ResizeGrip" Property="Visibility" Value="Visible" />
                        </MultiTrigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="ResizeMode"  Value="NoResize" />
                                <Condition Property="WindowStyle"  Value="ToolWindow" />
                            </MultiTrigger.Conditions>
                            <Setter TargetName="PART_MinAndMax" Property="Visibility" Value="Collapsed" />
                        </MultiTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</ResourceDictionary>

三、创建MainWindow.xaml。

<ws:Window x:Class="Wpf45.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:ws="https://github.com/WPFDevelopersOrg.WPFDevelopers.Minimal"
        xmlns:local="clr-namespace:Wpf45"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        
    </Grid>
</ws:Window>

四、删除MainWindow.xaml.cs删除继承。

public partial class MainWindow 
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }

02


效果预览

鸣谢素材提供者菜小松cc

源码地址如下

Github:https://github.com/WPFDevelopersOrg

Gitee:https://gitee.com/WPFDevelopersOrg

WPF开发者QQ群: 340500857 

Github:https://github.com/WPFDevelopersOrg

出处:https://www.cnblogs.com/yanjinhua

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

转载请著名作者 出处 https://github.com/WPFDevelopersOrg

55d4dbc9dbd93c42bb4226cfd590c80c.png

扫一扫关注我们,

32c4cdd0466337b43a55b6e7bcba7b4e.gif

更多知识早知道!

1a2e9cf5c1ad64b9f686e13798e6c3dd.gif

点击阅读原文可跳转至源代码

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值