gpt4 book ai didi

WPF学习-自定义窗体(二)

转载 作者:我是一只小鸟 更新时间:2023-09-05 14:31:16 27 4
gpt4 key购买 nike

上一篇文章写了如何创建自定义窗体:使用 WindowChrome 或者 WindowStyle=“None”这两种方式。本文将讲述如何设置窗体的效果(以阴影效果为例),以及在效果模式下,窗体各功能的配合.

1、窗体的空间范围:

窗体的范围,就是白色区域部分:包括窗体的边框,标题栏,以及内部的空白部分。出了白色范围,不再属于窗体,且窗体也不能影响到白色区域意外的地方。理解这一点很重要! 。

2、透明窗体:

要设置透明窗体,比较简单,要同时设置三个属性:

                          <Window x:Class="ControlTest.EffectNoneWindow"
        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:local="clr-namespace:ControlTest"
        mc:Ignorable="d"
        Title="EffectNoneWindow" Height="450" Width="800"
        
                          
                            AllowsTransparency="True" Background="Transparent" WindowStyle ="None"
                          
                          >
    <Grid>
    </Grid>
</Window>

                        

 注意:当AllowTransparency = “True”时,WindowStyle的值必须为None.

这个截图就是窗体。因为它是透明的,所以直接看到了桌面(注意看顶部的调试工具条).

3、添加阴影效果:

                          <Window x:Class="ControlTest.EffectNoneWindow"
        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:local="clr-namespace:ControlTest"
        mc:Ignorable="d"
        Title="EffectNoneWindow" Height="450" Width="800"
        AllowsTransparency="True" Background="Transparent" WindowStyle ="None">

    <Border 
                          
                            Margin="20"
                          
                          
                            Background="White"
                          
                          >
        <Border.Effect>
            <DropShadowEffect Direction="0" BlurRadius="20" ShadowDepth="0" Color="#FF585252" />
        </Border.Effect>
    </Border>
</Window>

                        

 注意,最外圈的灰色部分(图中标1的地方)是桌面(它是微信截图的时候产生的);图中标2的青色框,是窗体的实际边框,它与白色部分(图中标3的地方)之间的空间,就是Border的Margin。为什么要这个Margin?

因为Border有一个Effect。如果没有这个Margin,Effect没有地方放置(因为任何窗体的效果、元素,都不能超出窗体的区域).

4、添加功能:

你以为到这里文章就结束了?No No No,让我们添加功能之后再看看。把上一篇文章中,关于标题栏,按钮的功能加上.

                          
                            Xaml代码:


                          
                          <Window x:Class=
                          
                            "
                          
                          
                            ControlTest.EffectNoneWindow
                          
                          
                            "
                          
                          
                            
        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:local
                          
                          =
                          
                            "
                          
                          
                            clr-namespace:ControlTest
                          
                          
                            "
                          
                          
                            
        mc:Ignorable
                          
                          =
                          
                            "
                          
                          
                            d
                          
                          
                            "
                          
                          
                            
        Title
                          
                          =
                          
                            "
                          
                          
                            EffectNoneWindow
                          
                          
                            "
                          
                           Height=
                          
                            "
                          
                          
                            450
                          
                          
                            "
                          
                           Width=
                          
                            "
                          
                          
                            800
                          
                          
                            "
                          
                          
                            
        AllowsTransparency
                          
                          =
                          
                            "
                          
                          
                            True
                          
                          
                            "
                          
                           Background=
                          
                            "
                          
                          
                            Transparent
                          
                          
                            "
                          
                           WindowStyle =
                          
                            "
                          
                          
                            None
                          
                          
                            "
                          
                          >

    <Border Margin=
                          
                            "
                          
                          
                            20
                          
                          
                            "
                          
                           Background=
                          
                            "
                          
                          
                            White
                          
                          
                            "
                          
                          >
        <Border.Effect>
            <DropShadowEffect Direction=
                          
                            "
                          
                          
                            0
                          
                          
                            "
                          
                           BlurRadius=
                          
                            "
                          
                          
                            20
                          
                          
                            "
                          
                           ShadowDepth=
                          
                            "
                          
                          
                            0
                          
                          
                            "
                          
                           Color=
                          
                            "
                          
                          
                            #FF585252
                          
                          
                            "
                          
                           />
        </Border.Effect>

        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height=
                          
                            "
                          
                          
                            auto
                          
                          
                            "
                          
                          />
                <RowDefinition Height=
                          
                            "
                          
                          
                            *
                          
                          
                            "
                          
                          />
            </Grid.RowDefinitions>
            <Border Height=
                          
                            "
                          
                          
                            30
                          
                          
                            "
                          
                           Background=
                          
                            "
                          
                          
                            YellowGreen
                          
                          
                            "
                          
                          
                            
            MouseDown
                          
                          =
                          
                            "
                          
                          
                            TitleMove
                          
                          
                            "
                          
                          >
                <Grid>
                    <Grid.Resources>
                        <Style TargetType=
                          
                            "
                          
                          
                            Button
                          
                          
                            "
                          
                          >
                            <Setter Property=
                          
                            "
                          
                          
                            Width
                          
                          
                            "
                          
                           Value=
                          
                            "
                          
                          
                            30
                          
                          
                            "
                          
                          />
                            <Setter Property=
                          
                            "
                          
                          
                            Background
                          
                          
                            "
                          
                           Value=
                          
                            "
                          
                          
                            Transparent
                          
                          
                            "
                          
                          />
                            <Setter Property=
                          
                            "
                          
                          
                            BorderThickness
                          
                          
                            "
                          
                           Value=
                          
                            "
                          
                          
                            0
                          
                          
                            "
                          
                          />
                        </Style>
                    </Grid.Resources>
                    <StackPanel Orientation=
                          
                            "
                          
                          
                            Horizontal
                          
                          
                            "
                          
                           WindowChrome.IsHitTestVisibleInChrome=
                          
                            "
                          
                          
                            True
                          
                          
                            "
                          
                          >
                        <Image />
                        <TextBlock VerticalAlignment=
                          
                            "
                          
                          
                            Center
                          
                          
                            "
                          
                           Margin=
                          
                            "
                          
                          
                            3,0
                          
                          
                            "
                          
                           Text=
                          
                            "
                          
                          
                            {Binding Title, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}
                          
                          
                            "
                          
                          />
                    </StackPanel>

                    <StackPanel Orientation=
                          
                            "
                          
                          
                            Horizontal
                          
                          
                            "
                          
                           HorizontalAlignment=
                          
                            "
                          
                          
                            Right
                          
                          
                            "
                          
                           WindowChrome.IsHitTestVisibleInChrome=
                          
                            "
                          
                          
                            True
                          
                          
                            "
                          
                          >
                        <Button Content=
                          
                            "
                          
                          
                            _
                          
                          
                            "
                          
                           Click=
                          
                            "
                          
                          
                            Btn_Min
                          
                          
                            "
                          
                          />
                        <Button Content=
                          
                            "
                          
                          
                            Max
                          
                          
                            "
                          
                           Click=
                          
                            "
                          
                          
                            Btn_Max
                          
                          
                            "
                          
                          />
                        <Button Content=
                          
                            "
                          
                          
                            X
                          
                          
                            "
                          
                           Click=
                          
                            "
                          
                          
                            Btn_Close
                          
                          
                            "
                          
                          />
                    </StackPanel>
                </Grid>
            </Border>
            <TabControl Grid.Row=
                          
                            "
                          
                          
                            1
                          
                          
                            "
                          
                           Margin=
                          
                            "
                          
                          
                            10
                          
                          
                            "
                          
                          >
                <TabItem Header=
                          
                            "
                          
                          
                            项目
                          
                          
                            "
                          
                          />
                <TabItem Header=
                          
                            "
                          
                          
                            代码
                          
                          
                            "
                          
                          />
            </TabControl>
        </Grid>
    </Border>
</Window>
                          
                            

C#代码:(
                             此处不包含调整窗体大小的代码。具体请看上一篇文章的末尾 
                          
                            //
                          
                          
                             窗体移动
                          
                          
                            private
                          
                          
                            void
                          
                           TitleMove(
                          
                            object
                          
                          
                             sender, MouseButtonEventArgs e)
{
    
                          
                          
                            if
                          
                           (e.ChangedButton != MouseButton.Left) 
                          
                            return
                          
                          ;            
                          
                            //
                          
                          
                             非左键点击,退出
                          
                          
                            if
                          
                           (e.ClickCount == 
                          
                            1
                          
                          
                            )
    {
        
                          
                          
                            this
                          
                          .DragMove();                                        
                          
                            //
                          
                          
                             拖动窗体
                          
                          
                                }
    
                          
                          
                            else
                          
                          
                            
    {
        WindowMax();                                            
                          
                          
                            //
                          
                          
                             双击时,最大化或者还原窗体
                          
                          
                                }
}


                          
                          
                            //
                          
                          
                             最小化
                          
                          
                            private
                          
                          
                            void
                          
                           Btn_Min(
                          
                            object
                          
                          
                             sender, RoutedEventArgs e)
{
    
                          
                          
                            this
                          
                          .WindowState =
                          
                             WindowState.Minimized;
}


                          
                          
                            //
                          
                          
                             关闭窗体
                          
                          
                            private
                          
                          
                            void
                          
                           Btn_Close(
                          
                            object
                          
                          
                             sender, RoutedEventArgs e)
{
    
                          
                          
                            this
                          
                          
                            .Close();
}


                          
                          
                            //
                          
                          
                             最大化、还原
                          
                          
                            private
                          
                          
                            void
                          
                           Btn_Max(
                          
                            object
                          
                          
                             sender, RoutedEventArgs e)
{
    WindowMax();
}


                          
                          
                            private
                          
                          
                            void
                          
                          
                             WindowMax()
{
    
                          
                          
                            if
                          
                           (
                          
                            this
                          
                          .WindowState ==
                          
                             WindowState.Normal)
    {
        
                          
                          
                            this
                          
                          .WindowState =
                          
                             WindowState.Maximized;
    }
    
                          
                          
                            else
                          
                          
                            
    {
        
                          
                          
                            this
                          
                          .WindowState =
                          
                             WindowState.Normal;
    }
}
                          
                        

大部分功能完好。可以用鼠标在标题上拖动窗体,双击标题栏放大、缩小,最小化、关闭按钮工作正常。唯独最大化按钮的效果不是我们想要的! 。

问题:1. 最大化之后,它的四周与屏幕边缘还有空白;2. 它遮住了桌面的任务栏.

这才是要解决的问题的关键!这个问题的产生,还是“窗体的空间范围”引起的:

1. 因为最大化的是窗体,而窗体包括了最外层Border的Margin,所以最大化之后,Margin依然是存在的,四周与屏幕之间自然就有了空白.

2. 因为没有操作系统赋予的“窗口边框”,窗体也就不知道了屏幕可用范围大小,只能是尽可能占据全部屏幕,因此就遮住了桌面的任务栏.

要解决这两个问题,只需要做两个设置。且看如下代码(最重要的是OnStateChanged()方法):

                          
                            Xaml代码:

                          
                          <!-- 设置最外层Border的Name属性 -->
<Border 
                          
                            Name="bd" 
                          
                          Margin=
                          
                            "
                          
                          
                            20
                          
                          
                            "
                          
                           Background=
                          
                            "
                          
                          
                            White
                          
                          
                            "
                          
                          >
                          
                            
    ……

                          
                          </Border>
                          
                            

C#代码:

                          
                          
                            public
                          
                          
                            partial
                          
                          
                            class
                          
                          
                             EffectNoneWindow : Window
{
    Thickness originMargin;              
                             // 记录bd的初始Margin值 
                            
    Thickness zeroMargin 
                          
                          = 
                          
                            new
                          
                           Thickness(
                          
                            5
                          
                          
                            );    
                             // 设置当窗体最大化之后,bd的Margin值。该值本应该为0,但是实际上最大化之后会有点“吃”窗体,因此设置为5或者其他数值,以求更好的视觉效果。 
                          
                          
                            public
                          
                          
                             EffectNoneWindow()
    {
        InitializeComponent();
        
                            
// 注册事件。如此当拖动鼠标到屏幕的边缘时,Windows系统会将窗体最大化,程序也能正常工作。
this .StateChanged += OnStateChanged;               // 设置窗体最大化时的最大高度 this .MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight; this .originMargin = this .bd.Margin; } private void OnStateChanged(object? sender, EventArgs e) { if ( this .WindowState == WindowState.Normal) { // Normal状态时,将bd的Margin设置为初始值 this .bd.Margin = this .originMargin; } else { // 最大化时,将bd的Margin设置为0; this .bd.Margin = zeroMargin; } } // 窗体移动 private void TitleMove( object sender, MouseButtonEventArgs e) { if (e.ChangedButton != MouseButton.Left) return ; // 非左键点击,退出 if (e.ClickCount == 1 ) { this .DragMove(); // 拖动窗体 } else { WindowMax(); // 双击时,最大化或者还原窗体 } } // 最小化 private void Btn_Min( object sender, RoutedEventArgs e) { this .WindowState = WindowState.Minimized; } // 关闭窗体 private void Btn_Close( object sender, RoutedEventArgs e) { this .Close(); } // 最大化、还原 private void Btn_Max( object sender, RoutedEventArgs e) { WindowMax(); } private void WindowMax() { if ( this .WindowState == WindowState.Normal) { this .WindowState = WindowState.Maximized; } else { this .WindowState = WindowState.Normal; } } }

你以为这就完事了?太天真了,微软的东西哪有这么简单?它总是会给你埋坑的! 。

5、分屏:

以上代码,在点击“最大化”按钮、用鼠标把窗体拖到屏幕顶端(系统赋予的最大化操作)时,都OK,没问题。但如果把窗体用鼠标拖到屏幕的左侧、右侧、屏幕的四个角时,系统会让窗体占据部分屏幕(类似于分屏)时,窗体呈现的效果如下:

窗体高度OK了,但是Margin错了! 。

 因此,还要修改。代码如下:

                          
                            public
                          
                          
                            partial
                          
                          
                            class
                          
                          
                             EffectNoneWindow : Window
    {
        Thickness originMargin;
        Thickness margin5 
                          
                          = 
                          
                            new
                          
                           Thickness(
                          
                            8
                          
                          
                            );
        Thickness marginTopLeft;
        Thickness marginTopRight;
        Thickness marginBottomLeft;
        Thickness marginBottomRight;
        Thickness marginLeft;
        Thickness marginRight;

        
                          
                          
                            double
                          
                           maxWidth =
                          
                             SystemParameters.MaximizedPrimaryScreenWidth;
        
                          
                          
                            double
                          
                           maxHeight =
                          
                             SystemParameters.MaximizedPrimaryScreenHeight;


        
                          
                          
                            public
                          
                          
                             EffectNoneWindow()
        {
            InitializeComponent();

            
                          
                          
                            //
                          
                          
                            不再使用StateChanged事件,而使用SizeChanged事件
                          
                          
                            this.SizeChanged += EffectNoneWindow_SizeChanged;

            
                          
                          
                            //
                          
                          
                             设置窗体最大化时的最大高度
                          
                          
            MaxHeight =
                          
                             maxHeight;
            originMargin 
                          
                          =
                          
                             bd.Margin;
            marginTopLeft 
                          
                          = 
                          
                            new
                          
                           Thickness(
                          
                            0
                          
                          , 
                          
                            0
                          
                          
                            , originMargin.Right, originMargin.Bottom);
            marginTopRight 
                          
                          = 
                          
                            new
                          
                           Thickness(originMargin.Left, 
                          
                            0
                          
                          , 
                          
                            0
                          
                          
                            , originMargin.Bottom);
            marginBottomLeft 
                          
                          = 
                          
                            new
                          
                           Thickness(
                          
                            0
                          
                          , originMargin.Top, originMargin.Right, 
                          
                            0
                          
                          
                            );
            marginBottomRight 
                          
                          = 
                          
                            new
                          
                           Thickness(originMargin.Left, originMargin.Top, 
                          
                            0
                          
                          , 
                          
                            0
                          
                          
                            );
            marginLeft 
                          
                          = 
                          
                            new
                          
                           Thickness(
                          
                            0
                          
                          , 
                          
                            0
                          
                          , originMargin.Right, 
                          
                            0
                          
                          
                            );
            marginRight 
                          
                          = 
                          
                            new
                          
                           Thickness(originMargin.Left, 
                          
                            0
                          
                          , 
                          
                            0
                          
                          , 
                          
                            0
                          
                          
                            );
        }

        
                          
                          
                            //
                          
                          
                             尺寸发生改变时:
                          
                          
                            private void EffectNoneWindow_SizeChanged(object
                          
                          
                             sender, SizeChangedEventArgs e) 
                            
        {
            
                          
                          
                            //
                          
                          
                             1. 判断是否最大化:
                          
                          
                            if
                          
                          (Math.Abs(
                          
                            this
                          
                          .ActualWidth- maxWidth)<
                          
                            4
                          
                          
                            )          
                             // 此处用绝对值判断,是因为窗体的大小,不会刚刚好是最大值。下同。 
                            
            {
                bd.Margin 
                          
                          =
                          
                             margin5;
                
                          
                          
                            return
                          
                          
                            ;
            }

            
                          
                          
                            //
                          
                          
                             2. 判断是否分屏:
                          
                          
                            if
                          
                          (Math.Abs(
                          
                            this
                          
                          .Height-maxHeight)<
                          
                            20
                          
                          
                            )
            {
                
                          
                          
                            //
                          
                          
                             在窗体的左侧:
                          
                          
                bd.Margin = Left == 
                          
                            0
                          
                           ?
                          
                             marginLeft : marginRight;
                
                          
                          
                            //
                          
                          
                            Height = maxHeight;
                          
                          
                            return
                          
                          
                            ;
            }

            
                          
                          
                            //
                          
                          
                             3. 判断是否四分屏:
                          
                          
                            if
                          
                          (Math.Abs(
                          
                            this
                          
                          .Width - maxWidth/
                          
                            2
                          
                          )<
                          
                            20
                          
                           && Math.Abs(
                          
                            this
                          
                          .Height - maxHeight/
                          
                            2
                          
                          )<
                          
                            20
                          
                          
                            )
            {
                
                          
                          
                            if
                          
                          (Left == 
                          
                            0
                          
                          
                            )
                {
                    
                          
                          
                            if
                          
                          (Top ==
                          
                            0
                          
                          
                            )
                    {
                        
                          
                          
                            //
                          
                          
                             左上角
                          
                          
                        bd.Margin =
                          
                             marginTopLeft;
                    }
                    
                          
                          
                            else
                          
                          
                            
                    {
                        bd.Margin 
                          
                          =
                          
                             marginBottomLeft;
                    }
                }
                
                          
                          
                            else
                          
                          
                            
                {
                    
                          
                          
                            if
                          
                          (Top == 
                          
                            0
                          
                          
                            )
                    {
                        bd.Margin 
                          
                          =
                          
                             marginTopRight;
                    }
                    
                          
                          
                            else
                          
                          
                            
                    {
                        bd.Margin 
                          
                          =
                          
                             marginBottomRight;
                    }
                }
                
                          
                          
                            return
                          
                          
                            ;
            }

            
                          
                          
                            this
                          
                          .bd.Margin =
                          
                             originMargin;
        }

        
                          
                          
                            private
                          
                          
                            void
                          
                           OnStateChanged(
                          
                            object
                          
                          ?
                          
                             sender, EventArgs e)
        {
            
                          
                          
                            if
                          
                          (
                          
                            this
                          
                          .WindowState ==
                          
                             WindowState.Normal)
            {
                
                          
                          
                            //
                          
                          
                             Normal状态时,将bd的Margin设置为初始值
                          
                          
                            this
                          
                          .bd.Margin = 
                          
                            this
                          
                          
                            .originMargin;
            }
            
                          
                          
                            else
                          
                          
                            
            {
                
                          
                          
                            //
                          
                          
                             最大化时,将bd的Margin设置为0;
                          
                          
                            this
                          
                          .bd.Margin =
                          
                             margin5;
            }
        }

        
                          
                          
                            //
                          
                          
                             窗体移动
                          
                          
                            private
                          
                          
                            void
                          
                           TitleMove(
                          
                            object
                          
                          
                             sender, MouseButtonEventArgs e)
        {
            
                          
                          
                            if
                          
                           (e.ChangedButton != MouseButton.Left) 
                          
                            return
                          
                          ;            
                          
                            //
                          
                          
                             非左键点击,退出
                          
                          
                            if
                          
                           (e.ClickCount == 
                          
                            1
                          
                          
                            )
            {
                
                          
                          
                            this
                          
                          .DragMove();                                        
                          
                            //
                          
                          
                             拖动窗体
                          
                          
                                        }
            
                          
                          
                            else
                          
                          
                            
            {
                WindowMax();                                            
                          
                          
                            //
                          
                          
                             双击时,最大化或者还原窗体
                          
                          
                                        }
        }

        
                          
                          
                            //
                          
                          
                             最小化
                          
                          
                            private
                          
                          
                            void
                          
                           Btn_Min(
                          
                            object
                          
                          
                             sender, RoutedEventArgs e)
        {
            
                          
                          
                            this
                          
                          .WindowState =
                          
                             WindowState.Minimized;
        }



        
                          
                          
                            //
                          
                          
                             关闭窗体
                          
                          
                            private
                          
                          
                            void
                          
                           Btn_Close(
                          
                            object
                          
                          
                             sender, RoutedEventArgs e)
        {
            
                          
                          
                            this
                          
                          
                            .Close();
        }

        
                          
                          
                            //
                          
                          
                             最大化、还原
                          
                          
                            private
                          
                          
                            void
                          
                           Btn_Max(
                          
                            object
                          
                          
                             sender, RoutedEventArgs e)
        {
            WindowMax();
        }

        
                          
                          
                            private
                          
                          
                            void
                          
                          
                             WindowMax()
        {
            
                          
                          
                            if
                          
                           (
                          
                            this
                          
                          .WindowState ==
                          
                             WindowState.Normal)
            {
                
                          
                          
                            this
                          
                          .WindowState =
                          
                             WindowState.Maximized;
            }
            
                          
                          
                            else
                          
                          
                            
            {
                
                          
                          
                            this
                          
                          .WindowState =
                          
                             WindowState.Normal;
            }
        }
    }
                          
                        

此处,最主要的是EffectNoneWindow_SizeChanged()方法。当窗体的尺寸发生改变时,它会判断窗体在哪个位置,是最大化、两分屏,还是四分屏,并对Margin进行相应的赋值.

至此,一个功能齐全的自定义窗体就搞定了。要改换效果,则只需要将Xaml代码中的Effect替换即可.

6、禁止调整窗体大小:

有些时候,我们不希望窗体能调整大小,比如初始窗口,仅仅只是在加载的时候显示,程序加载完之后就关闭了.

如果不希望窗体能调整大小,只需设置Windows的ResizeMode = “NoResize”即可.

最后此篇关于WPF学习-自定义窗体(二)的文章就讲到这里了,如果你想了解更多关于WPF学习-自定义窗体(二)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com