基于WPF实现边缘停靠效果

 更新时间:2024年01月09日 09:30:04   作者:zhaotianff  
这篇文章主要为大家信息介绍了如何基于WPF实现边缘停靠效果,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下

最近做的某个功能需要用到边缘停靠,WPF实现了下,效果如下

主要实现原理如下:

1、增加一块热点区域,鼠标进入时,触发显示动画,并隐藏热点区域

2、鼠标拖动或离开窗体,判断窗体离屏幕边缘的距离,符合条件的,触发隐藏动画,并显示热点区域

3、使用Window.Left属性进行窗体动画

需要注意的地方:

1、在拖动窗体时,不能通过窗体的Left属性来进行判断,因为Left没有刷新,可以通过Win32 API 函数GetWindowRect来获取

2、可以增加缓动动画,使动画效果更好。

实现代码如下:

MainWindow.xaml

在XAML里定义了显示和隐藏的动画,窗体定义了两列,第一列就是隐藏时用于显示窗体的热点区域

<blur:BlurWindow x:Class="WpfDockDemo.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:local="clr-namespace:WpfDockDemo"
        xmlns:blur="clr-namespace:TianXiaTech;assembly=BlurWindow"
        mc:Ignorable="d"
        Title="MainWindow" Height="650" Width="305" TitleVisibility="Collapsed" IconVisibility="Collapsed" ControlBoxVisibility="Collapsed"
                 Background="White" Name="main" MouseMove="BlurWindow_MouseMove" MouseLeave="main_MouseLeave" Topmost="True" PreviewMouseDown="main_MouseDown">
    <blur:BlurWindow.Resources>
        <Storyboard x:Key="hiddenAnimation">
            <DoubleAnimation Storyboard.TargetName="main" Storyboard.TargetProperty="(Window.Left)" Duration="0:0:0.5" AutoReverse="False">
                <DoubleAnimation.EasingFunction>
                    <BackEase Amplitude="0.3"/>
                </DoubleAnimation.EasingFunction>
            </DoubleAnimation>
        </Storyboard>

        <Storyboard x:Key="showAnimation">
            <DoubleAnimation Storyboard.TargetName="main" Storyboard.TargetProperty="(Window.Left)" Duration="0:0:0.5" AutoReverse="False">
                <DoubleAnimation.EasingFunction>
                    <BackEase Amplitude="0.3" />
                </DoubleAnimation.EasingFunction>
            </DoubleAnimation>
        </Storyboard>
    </blur:BlurWindow.Resources>
    <Grid>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="5"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Grid Background="Transparent" MouseEnter="grid_DockArea_MouseEnter" Name="grid_DockArea" Visibility="Collapsed">
            <Border Height="{Binding ElementName=main,Path=ActualHeight}" VerticalAlignment="Center" Width="2" Background="Silver">
                <Border.Effect>
                    <DropShadowEffect Color="Black" Opacity=".3"></DropShadowEffect>
                </Border.Effect>
            </Border>
        </Grid>

        <!--网上随便找的图-->
        <Image Margin="10" Source="https://pic1.zhimg.com/80/v2-46ae37aad7cb70b4dc4ad4489cdaffdd_720w.webp?source=2c26e567" Grid.Column="1" PreviewMouseDown="main_MouseDown" >
            <Image.Effect>
                <DropShadowEffect Opacity=".5"></DropShadowEffect>
            </Image.Effect>
        </Image>
    </Grid>
</blur:BlurWindow>

引入用到的api函数

public struct POINT
    {
        public int x;
        public int y;
    }

    public struct RECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }

    public class User32
    {
        [DllImport("User32.dll")]
        public static extern int GetCursorPos(ref POINT point);

        [DllImport("User32.dll")]
        public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
    }

定义一些用于记录窗体状态的变量

private bool isDocking = true;  //是否启用边缘停靠
private bool isAnimation = false; //是否正在动画中
private bool isDraged = false;     //是否正在拖动中

定义用于窗体显示和隐藏动画的函数

private void HideWindow(double left = -1)
        {
            if (left == -1)
            {
                RECT rect = new RECT();
                User32.GetWindowRect(new WindowInteropHelper(this).Handle, ref rect);
                left = rect.left;
            }

            if (SystemParameters.PrimaryScreenWidth - left - this.Width > 15)
                return;

            if (isAnimation)
                return;

            isAnimation = true;
            hiddenAnimation.Begin();
        }

        private void ShowWindow()
        {
            if (isAnimation)
                return;

            grid_DockArea.Visibility = Visibility.Collapsed;
            isAnimation = true;
            showAnimation.Begin();
        }

处理鼠标移动事件

private void BlurWindow_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                try
                {
                    this.DragMove();
                    isDraged = true;
                }
                catch
                {

                }
            }

            if (e.LeftButton == MouseButtonState.Released && isDocking == true && isDraged == true)
            {
                POINT point = new POINT();
                if (User32.GetCursorPos(ref point) == 1)
                {
                    var pos = e.GetPosition(this);

                    if (pos.X < 0 && pos.Y < 0)
                        HideWindow();
                }

                isDraged = false;
            }
        }

处理鼠标按下事件

private void main_MouseDown(object sender, MouseButtonEventArgs e)
        {
            var pos = e.GetPosition(this);
            if (pos.X >= 0 && pos.Y >= 0)
                isDraged = true;
        }

处理鼠标离开事件

private void main_MouseLeave(object sender, MouseEventArgs e)
        {
            if (isDocking && isDraged == false)
            {
                HideWindow();
            }
        }

这样就可以实现了一个简单的边缘停靠效果。现在只实现了屏幕右侧的边缘停靠,左边和上面可以如法炮制。

窗体第一次运行是不会主动隐藏的,需要手动控制  一下。

到此这篇关于基于WPF实现边缘停靠效果的文章就介绍到这了,更多相关WPF边缘停靠内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C# 多线程读取注册表,加载至TreeView

    C# 多线程读取注册表,加载至TreeView

    C#下多线程读取注册表,加载至TreeView的实现代码。
    2009-09-09
  • c#打开py文件的方法

    c#打开py文件的方法

    在本篇内容里小编给大家分享的是关于c#打开py文件的方法和步骤,需要的朋友们可以跟着学习下。
    2018-12-12
  • C#实现计算器功能(winform版)

    C#实现计算器功能(winform版)

    这篇文章主要为大家详细介绍了C#实现winform版的计算器功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • C#通过标签软件Bartender的ZPL命令打印条码

    C#通过标签软件Bartender的ZPL命令打印条码

    这篇文章介绍了C#通过标签软件Bartender的ZPL命令打印条码,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-01-01
  • C#文件流进行压缩和解压缩的方法

    C#文件流进行压缩和解压缩的方法

    这篇文章主要介绍了C#文件流进行压缩和解压缩的方法,涉及C#文件流操作的相关技巧,需要的朋友可以参考下
    2015-05-05
  • WPF实现时钟特效

    WPF实现时钟特效

    这篇文章主要介绍了WPF实现时钟特效,过程很简单,感兴趣的小伙伴们可以参考一下
    2015-11-11
  • C#和lua相互调用的方法教程

    C#和lua相互调用的方法教程

    lua是一种脚本语言,可以方便的移植到各种宿主语言中,并且可以支持热更新,在游戏开发中也能当做主要的语言来编写游戏的逻辑,所以这篇文章主要给大家介绍了关于C#和lua相互调用的方法教程,需要的朋友可以参考下。
    2017-11-11
  • C#实现图形区域组合操作的方法

    C#实现图形区域组合操作的方法

    这篇文章主要介绍了C#实现图形区域组合操作的方法,涉及C#操作图片实现组合操作的相关技巧,需要的朋友可以参考下
    2015-06-06
  • 用C#编写ActiveX控件(三)

    用C#编写ActiveX控件(三)

    用C#编写ActiveX控件(三)...
    2007-03-03
  • c#反射调用方法示例

    c#反射调用方法示例

    这篇文章主要介绍了c#反射调用方法示例,需要的朋友可以参考下
    2014-04-04

最新评论