zoukankan      html  css  js  c++  java
  • WPF之模板样式

          以前学WPF时弄的个自定义窗体,关于截断系统消息的一部分代码来源于网上。

          源文件在这里

         

          说起来也容易,整个窗体就是个border,渲染下,然后在上面加层DockPanel,放那些标题和按钮。

          下面是自定义窗体的样式,将XAML分开,这样方便看。

           窗体部分:

    View Code
        <Style x:Key="WindowStyle" TargetType="Window">
            <Setter Property="AllowsTransparency" Value="True"/>
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="WindowStyle" Value="None"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate x:Name="WindowTemplate" TargetType="Window">
                        <!--若不设置margin,阴影无法显示(被挡住了)-->
                        <Border x:Name="FussWindowBorder" CornerRadius="5" Margin="8" Background="White" BorderBrush="#6A6A6A" BorderThickness="1" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"  >
                            <Border.Effect>
                                <DropShadowEffect BlurRadius="8" ShadowDepth="0" Color="#00000000"/>
                            </Border.Effect>
                            <Grid>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="*"/>
                                </Grid.RowDefinitions>
                                <Border Name="TitleBar" Height="50" CornerRadius="5">
                                    <Border.Background>
                                        <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                            <GradientStop Color="#FF2161D6" Offset="0.02"/>
                                            <GradientStop Color="#00FFFFFF" Offset="1"/>
                                        </LinearGradientBrush>
                                    </Border.Background>
                                    <DockPanel Margin="0">
                                        <TextBlock DockPanel.Dock="Left" Name="TitleText" VerticalAlignment="Top" Margin="10 5 0 0"  FontSize="16" FontWeight="Bold" Foreground="#FF101010"/>
                                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" DockPanel.Dock="Right" Height="25" VerticalAlignment="Top">
                                            <Rectangle Style="{DynamicResource Splitter}"/>
                                            <Button Name="MiniButton" Width="30" Template="{DynamicResource MiniButton}"/>
                                            <Rectangle Style="{DynamicResource Splitter}"/>
                                            <Button Name="MaxButton" Width="30" Style="{DynamicResource WinNormalButton}"/>
                                            <Rectangle Name="MaxSplitter"  Style="{DynamicResource Splitter}"/>
                                            <Button Name="CloseButton" Width="35" Style="{DynamicResource CloseButton}"/>
                                        </StackPanel>
                                    </DockPanel>
                                </Border>
                                <AdornerDecorator Grid.Row="1" Height="Auto" Width="Auto">
                                    <ContentPresenter/>
                                </AdornerDecorator>
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

          最大化、最小化、关闭按钮间的切分条:

    View Code
        <Style x:Key="Splitter" TargetType="Rectangle">
            <Setter Property="Width" Value="1"/>
            <Setter Property="Stroke" Value="Transparent"/>
            <Setter Property="StrokeThickness" Value="0"/>
            <Setter Property="Fill">
                <Setter.Value>
                    <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                        <LinearGradientBrush.GradientStops>
                            <GradientStop Color="#FF000000" Offset="0"/>
                            <GradientStop Color="#80000000" Offset="0.6"/>
                            <GradientStop Color="#00000000" Offset="1.0"/>
                        </LinearGradientBrush.GradientStops>
                    </LinearGradientBrush>
                </Setter.Value>
            </Setter>
        </Style>

          几个按钮的颜色样式:

    View Code
        <LinearGradientBrush x:Key="MinMaxBrush" StartPoint="0.5,0" EndPoint="0.5,1">
            <LinearGradientBrush.GradientStops>
                <GradientStop Color="#F0FFFFFF" Offset="0"/>
                <GradientStop Color="#00FFFFFF" Offset="1"/>
            </LinearGradientBrush.GradientStops>
        </LinearGradientBrush>
        <LinearGradientBrush x:Key="MinMaxPressedBrush" StartPoint="0.5,0" EndPoint="0.5,1">
            <LinearGradientBrush.GradientStops>
                <GradientStop Color="#E0BBBBBB" Offset="0"/>
                <GradientStop Color="#00BBBBBB" Offset="1"/>
            </LinearGradientBrush.GradientStops>
        </LinearGradientBrush>
        <DrawingBrush x:Key="CloseButtonBrush">
            <DrawingBrush.Drawing>
                <GeometryDrawing Geometry="M 36.0396,7.62939e-006L -6.10352e-005,7.62939e-006L -6.10352e-005,25L 39.9999,25L 39.9999,3.90626C 39.9999,1.74885 38.2269,7.62939e-006 36.0396,7.62939e-006 Z ">
                    <GeometryDrawing.Brush>
                        <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                            <LinearGradientBrush.GradientStops>
                                <GradientStop Color="#FFFF0000" Offset="0"/>
                                <GradientStop Color="#00FF0000" Offset="1"/>
                            </LinearGradientBrush.GradientStops>
                        </LinearGradientBrush>
                    </GeometryDrawing.Brush>
                </GeometryDrawing>
            </DrawingBrush.Drawing>
        </DrawingBrush>
        <DrawingBrush x:Key="CloseButtonPressBrush">
            <DrawingBrush.Drawing>
                <GeometryDrawing Geometry="M 36.0396,7.62939e-006L -6.10352e-005,7.62939e-006L -6.10352e-005,25L 39.9999,25L 39.9999,3.90626C 39.9999,1.74885 38.2269,7.62939e-006 36.0396,7.62939e-006 Z ">
                    <GeometryDrawing.Brush>
                        <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                            <LinearGradientBrush.GradientStops>
                                <GradientStop Color="#FF5A022F" Offset="0"/>
                                <GradientStop Color="#005A022F" Offset="1"/>
                            </LinearGradientBrush.GradientStops>
                        </LinearGradientBrush>
                    </GeometryDrawing.Brush>
                </GeometryDrawing>
            </DrawingBrush.Drawing>
        </DrawingBrush>

          最小化、最大化(窗体最大化和正常两种情况)、关闭按钮的样式:

    View Code
        <ControlTemplate x:Key="MiniButton" TargetType="Button">
            <!--一定要初始化Grid的Background属性-->
            <Grid x:Name="MiniGrid" Background="Transparent">
                <Path Data="F1 M 14.7587,4.59057L 0.5,4.59057L 0.5,0.499992L 14.7587,0.499992L 14.7587,4.59057 Z "
                           Fill="#FFFCFCFD" StrokeLineJoin="Round" Stroke="#FF4A4B4D" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0 5 0 0" />
            </Grid>
            <ControlTemplate.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" TargetName="MiniGrid" Value="{StaticResource MinMaxBrush}"/>
                </Trigger>
                <Trigger Property="IsPressed" Value="True">
                    <Setter Property="Background" TargetName="MiniGrid" Value="{StaticResource MinMaxPressedBrush}"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
        <Style x:Key="WinMaxButton" TargetType="Button">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Grid x:Name="MaxButton" Background="Transparent">
                            <Canvas Width="15" Height="15" VerticalAlignment="Center" HorizontalAlignment="Center" >
                                <Canvas.Background>
                                    <DrawingBrush>
                                        <DrawingBrush.Drawing>
                                            <DrawingGroup>
                                                <DrawingGroup.Children>
                                                    <GeometryDrawing Brush="#FFFCFCFD" Geometry="M 3.06549,0.500031L 15.5,0.500031L 15.5,12.9346L 12.4866,12.9346L 12.4866,3.6337L 3.06549,3.6337L 3.06549,0.500031 Z ">
                                                        <GeometryDrawing.Pen>
                                                            <Pen LineJoin="Round" Brush="#FF040404"/>
                                                        </GeometryDrawing.Pen>
                                                    </GeometryDrawing>
                                                    <GeometryDrawing Brush="#FFFCFCFD" Geometry="M 0.5,3.06546L 12.9345,3.06546L 12.9345,15.5L 0.5,15.5L 0.5,3.06546 Z M 3.60864,6.1741L 3.60864,12.3914L 9.82587,12.3914L 9.82587,6.1741L 3.60864,6.1741 Z ">
                                                        <GeometryDrawing.Pen>
                                                            <Pen LineJoin="Round" Brush="#FF040404"/>
                                                        </GeometryDrawing.Pen>
                                                    </GeometryDrawing>
                                                </DrawingGroup.Children>
                                            </DrawingGroup>
                                        </DrawingBrush.Drawing>
                                    </DrawingBrush>
                                </Canvas.Background>
                            </Canvas>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Background" TargetName="MaxButton" Value="{StaticResource MinMaxBrush}"/>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="True">
                                <Setter Property="Background" TargetName="MaxButton" Value="{StaticResource MinMaxPressedBrush}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <Style x:Key="WinNormalButton" TargetType="Button">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Grid x:Name="MaxButton" Background="Transparent">
                            <Canvas Width="15" Height="15" VerticalAlignment="Center" HorizontalAlignment="Center" >
                                <Canvas.Background>
                                    <DrawingBrush>
                                        <DrawingBrush.Drawing>
                                            <DrawingGroup>
                                                <DrawingGroup.Children>
                                                    <GeometryDrawing Brush="#FFFCFCFD" Geometry="M 0.5,3.06546L 12.9345,3.06546L 12.9345,15.5L 0.5,15.5L 0.5,3.06546 Z M 3.60864,6.1741L 3.60864,12.3914L 9.82587,12.3914L 9.82587,6.1741L 3.60864,6.1741 Z ">
                                                        <GeometryDrawing.Pen>
                                                            <Pen LineJoin="Round" Brush="#FF040404"/>
                                                        </GeometryDrawing.Pen>
                                                    </GeometryDrawing>
                                                </DrawingGroup.Children>
                                            </DrawingGroup>
                                        </DrawingBrush.Drawing>
                                    </DrawingBrush>
                                </Canvas.Background>
                            </Canvas>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Background" TargetName="MaxButton" Value="{StaticResource MinMaxBrush}"/>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="True">
                                <Setter Property="Background" TargetName="MaxButton" Value="{StaticResource MinMaxPressedBrush}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <Style x:Key="CloseButton" TargetType="Button">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Grid x:Name="CloseGrid" Background="Transparent">
                            <Path Data="F1 M 8,3.21448L 6.02069,0.5L 0.507629,0.5L 5.24347,6.99478L 0.5,13.5L 6.013,13.5L 8,10.7751L 9.987,13.5L 15.5,13.5L 10.7565,6.99478L 15.4924,0.5L 9.97937,0.5L 8,3.21448 Z "
                                       Fill="#FFFCFCFD" StrokeLineJoin="Round" Stroke="#FF4A4B4D" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Background" TargetName="CloseGrid" Value="{StaticResource CloseButtonBrush}"/>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="True">
                                <Setter Property="Background" TargetName="CloseGrid" Value="{StaticResource CloseButtonPressBrush}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>


          然后写个基类,读取下样式资源并应用。

    View Code
    namespace Fuss.Wpf.Themes
    {
        public class WindowBase : Window
        {
            private ResourceDictionary myWindowResouce = new ResourceDictionary ( );
            private ControlTemplate myTemplate;
    
            private const int WM_NCHITTEST = 0x0084;
            private const int WM_GETMINMAXINFO = 0x0024;
    
            private readonly int agWidth = 12; //拐角宽度
            private readonly int bThickness = 4; // 边框宽度
            private Point mousePoint = new Point ( ); //鼠标坐标
            private Button maxButton;
            private bool _showMax=true;
            public bool ShowMax
            {
                get
                {
                    return _showMax;
                }
                set
                {
                    _showMax = value;
                }
            }
    
            public WindowBase ( )
            {
                myWindowResouce.Source = new Uri ( "Fuss.Wpf.Themes;component/WindowTemplate.xaml", UriKind.Relative );
                this.Resources.MergedDictionaries.Add ( myWindowResouce );
                this.Style = (Style)myWindowResouce ["WindowStyle"];
                myTemplate = (ControlTemplate)(this.Style.Setters [3] as Setter).Value;
                this.Loaded += new RoutedEventHandler ( WindowBase_Loaded );
                this.MaxWidth = SystemParameters.MaximizedPrimaryScreenWidth;
                this.MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight;
            }
    
            private void WindowBase_Loaded ( object sender, RoutedEventArgs e )
            {
                maxButton = (Button)myTemplate.FindName ( "MaxButton", this );
                //((Border)myTemplate.FindName ( "TitleBar", this )).MouseLeftButtonDown += ( s1, e1 ) =>
                //{
                //    this.DragMove ( );
                //};
                ((TextBlock)myTemplate.FindName("TitleText", this)).Text = this.Title;
                if (!ShowMax)
                {
                    maxButton.Visibility = Visibility.Collapsed;
                    (myTemplate.FindName("MaxSplitter", this) as Rectangle).Visibility = Visibility.Collapsed;
                }
                else maxButton.Visibility = Visibility.Visible;
    
                this.SizeChanged += ( s1, e1 ) =>
                {
                    if (this.WindowState == WindowState.Normal)
                    {
                        maxButton.Style = (Style)myWindowResouce ["WinNormalButton"];
                    }
                    else if (maxButton.Style != (Style)myWindowResouce ["WinMaxButton"]
                        &&this.WindowState == WindowState.Maximized)
                    {
                        maxButton.Style = (Style)myWindowResouce ["WinMaxButton"];
                    }
                };
                ( (Button)myTemplate.FindName ( "MiniButton", this ) ).Click += ( s2, e2 ) =>
                {
                    this.WindowState = WindowState.Minimized;
                };
                maxButton.Click += ( s3, e3 ) =>
                {
                    this.WindowState = (this.WindowState == WindowState.Normal) ? WindowState.Maximized : WindowState.Normal;
                };
                ( (Button)myTemplate.FindName ( "CloseButton", this ) ).Click += ( s4, e4 ) =>
                {
                    this.Close ( );
                };
                HwndSource hwndSource = PresentationSource.FromVisual ( this ) as HwndSource;
                if (hwndSource != null)
                {
                    hwndSource.AddHook ( new HwndSourceHook ( WndProc ) );
                }
            }
    
            protected virtual IntPtr WndProc ( IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled )
            {
                switch (msg)
                {
                    case WM_NCHITTEST:
                        mousePoint.X = (lParam.ToInt32 ( ) & 0xFFFF);
                        mousePoint.Y = (lParam.ToInt32 ( ) >> 16);
                        handled = true;
                        //窗体为最大化时(如果最大化,Left、Top属性都会造成影响)
                        if (this.WindowState == WindowState.Normal)
                        {
                            #region 拖拽改变窗体大小
                            //左上角
                            if ((mousePoint.Y - Top <= agWidth) && (mousePoint.X - Left <= agWidth))
                            {
                                return new IntPtr ( (int)HitTest.HTTOPLEFT );
                            }
                            //左下角
                            if ((this.ActualHeight + this.Top - this.mousePoint.Y <= this.agWidth) && (this.mousePoint.X - this.Left <= this.agWidth))
                            {
                                return new IntPtr ( (int)HitTest.HTBOTTOMLEFT );
                            }
                            //右上角
                            if ((this.mousePoint.Y - this.Top <= this.agWidth) && (this.ActualWidth + this.Left - this.mousePoint.X <= this.agWidth))
                            {
                                return new IntPtr ( (int)HitTest.HTTOPRIGHT );
                            }
                            //右下角
                            if ((this.ActualWidth + this.Left - this.mousePoint.X <= this.agWidth) && (this.ActualHeight + this.Top - this.mousePoint.Y <= this.agWidth))
                            {
                                return new IntPtr ( (int)HitTest.HTBOTTOMRIGHT );
                            }
                            //左侧
                            if (this.mousePoint.X - (this.Left + 4) <= this.bThickness)
                            {
                                return new IntPtr ( (int)HitTest.HTLEFT );
                            }
                            //右侧
                            if (this.ActualWidth + this.Left - 4 - this.mousePoint.X <= this.bThickness)
                            {
                                return new IntPtr ( (int)HitTest.HTRIGHT );
                            }
                            //上侧
                            if (this.mousePoint.Y - (this.Top + 4) <= this.bThickness)
                            {
                                return new IntPtr ( (int)HitTest.HTTOP );
                            }
                            //下侧
                            if (this.ActualHeight + this.Top - 4 - this.mousePoint.Y <= this.bThickness)
                            {
                                return new IntPtr ( (int)HitTest.HTBOTTOM );
                            }
                            #endregion
                            //正常情况下移动窗体
                            if (this.mousePoint.Y - this.Top > 0 && this.mousePoint.Y - this.Top < 40 && this.Left + this.ActualWidth - mousePoint.X > 110)
                            {
                                return new IntPtr ( (int)HitTest.HTCAPTION );
                            }
                        }
                        //最大化时移动窗体,让窗体正常化
                        if (this.WindowState == WindowState.Maximized)
                        {
                            if(this.mousePoint.Y< 40 && this.ActualWidth - mousePoint.X > 110)
                            {
                                return new IntPtr ( (int)HitTest.HTCAPTION );
                            }
                        }
                        ////将q其他区域设置为客户端,避免鼠标事件被屏蔽
                        return new IntPtr ( (int)HitTest.HTCLIENT );
                }
                return IntPtr.Zero;
            }
        }
    
        /// <summary>
        /// 包含了鼠标的各种消息
        /// </summary>
        public enum HitTest : int
        {
            HTERROR = -2,
            HTTRANSPARENT = -1,
            HTNOWHERE = 0,
            HTCLIENT = 1,
            HTCAPTION = 2,
            HTSYSMENU = 3,
            HTGROWBOX = 4,
            HTSIZE = HTGROWBOX,
            HTMENU = 5,
            HTHSCROLL = 6,
            HTVSCROLL = 7,
            HTMINBUTTON = 8,
            HTMAXBUTTON = 9,
            HTLEFT = 10,
            HTRIGHT = 11,
            HTTOP = 12,
            HTTOPLEFT = 13,
            HTTOPRIGHT = 14,
            HTBOTTOM = 15,
            HTBOTTOMLEFT = 16,
            HTBOTTOMRIGHT = 17,
            HTBORDER = 18,
            HTREDUCE = HTMINBUTTON,
            HTZOOM = HTMAXBUTTON,
            HTSIZEFIRST = HTLEFT,
            HTSIZELAST = HTBOTTOMRIGHT,
            HTOBJECT = 19,
            HTCLOSE = 20,
            HTHELP = 21
        } 
    }

         自定义窗体完成了,现在这样使用,注意后台代码中的窗体需继承自自定义的窗体类。

    View Code
    <fuss:WindowBase x:Class="Shell.LoginForm"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:fuss="clr-namespace:Fuss.Wpf.Themes;assembly=Fuss.Wpf.Themes"
            Title="登录" Height="320" Width="480" ResizeMode="NoResize" ShowMax="False">
        <Grid>
            <Grid Width="300" Height="120" Margin="0 30 0 0">
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="100"/>
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Row="0" Grid.Column="0" Text="用户名:" VerticalAlignment="Center" HorizontalAlignment="Right" FontSize="18" Margin="0 0 10 0"/>
                <TextBlock Grid.Row="1" Grid.Column="0" Text="密码:" VerticalAlignment="Center" HorizontalAlignment="Right" FontSize="18" Margin="0 0 10 0"/>
                <TextBox Grid.Row="0" Grid.Column="1"  VerticalAlignment="Center" FontSize="18"/>
                <TextBox Grid.Row="1" Grid.Column="1"  VerticalAlignment="Center" FontSize="18"/>
                <StackPanel Grid.Row="2" Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
                    <Button Content="登陆" Margin="5" Padding="8 3" Click="LoginButton_Click"/>
                    <Button Content="取消" Margin="5 5 10 5" Padding="8 3"/>
                </StackPanel>
            </Grid>
        </Grid>
    </fuss:WindowBase>
  • 相关阅读:
    centos7安装gitlab
    jenkins 部署k8s-jar包项目
    jenkins部署k8s项目-CICD
    pipeline
    jenkins打包
    jenkins 按角色设置管理权限
    1 jenkins的介绍和安装
    PyTables的下载和安装
    解决python报错:ImportError: No module named shutil_get_terminal_size 的方法
    nodejs安装失败
  • 原文地址:https://www.cnblogs.com/Fuss/p/2789842.html
Copyright © 2011-2022 走看看