首页 > 其他分享 >WPF实现边缘停靠效果

WPF实现边缘停靠效果

时间:2024-07-29 13:55:58浏览次数:10  
标签:动画 int private 边缘 窗体 停靠 WPF true public

最近做的某个功能需要用到边缘停靠,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);
    }

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

1  private bool isDocking = true;  //是否启用边缘停靠
2  private bool isAnimation = false; //是否正在动画中
3  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;
            }
        }

处理鼠标按下事件

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

处理鼠标离开事件

1         private void main_MouseLeave(object sender, MouseEventArgs e)
2         {
3             if (isDocking && isDraged == false)
4             {
5                 HideWindow();
6             }
7         }

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

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

示例代码

标签:动画,int,private,边缘,窗体,停靠,WPF,true,public
From: https://blog.csdn.net/zhaotianff/article/details/140769607

相关文章

  • WPF ZoomIn ZoomOut Pan ListBox Image
    <ListBoxx:Name="lbx"Grid.Row="1"Grid.Column="0"ItemsSource="{BindingImgsList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"SelectionChanged="lbx_SelectionChanged&quo......
  • 【WPF】Command 的一些使用方案
    Command,即命令,具体而言,指的是实现了 ICommand接口的对象。此接口要求实现者包含这些成员:1、CanExecute方法:确定该命令是否可以执行,若可,返回true;若不可,返回false;2、CanExecuteChanged事件:发送命令(命令源)的控件可以订阅此事件,当命令的可执行性改变时能得到通知;3、Execute......
  • 在WPF中使用WebView2详解
    MicrosoftEdgeWebView2MicrosoftEdgeWebView2 控件允许在本机应用中嵌入web技术(HTML、CSS以及JavaScript)。 WebView2 控件使用 MicrosoftEdge 作为绘制引擎,以在本机应用中显示web内容。使用 WebView2 可以在本机应用的不同部分嵌入Web代码,或在单个 We......
  • 一种减少在 OpenGL 中看到 3D 纹理中纹理边缘的方法
    我是OpenGL新手,我正在尝试使用python和OpenGL实现基于纹理的体积渲染。我成功加载数据文件并使用OpenGL3d纹理显示3D体积。我应用了深度测试混合。纹理从后向前加载。我添加了一些基本的鼠标回调。到目前为止,一切看起来都很好。当我旋转体积并达到纹理彼此平行的90......
  • 边缘计算PCDN的使用场景及优势
    一、定义PCDN,全称为PrivateContentDeliveryNetwork,即私有内容分发网络。它是一种基于P2P技术和CDN的内容分发加速网络,通过在网络中添加大量的低成本缓存服务器,将用户请求的内容从原始服务器分发到这些缓存服务器,从而实现内容更快、更稳定地传输到终端用户。二、功能PCDN......
  • 界面控件Telerik UI for WPF 2024 Q2亮点 - 全新的AIPrompt组件
    TelerikUIforWPF拥有超过100个控件来创建美观、高性能的桌面应用程序,同时还能快速构建企业级办公WPF应用程序。UIforWPF支持MVVM、触摸等,创建的应用程序可靠且结构良好,非常容易维护,其直观的API将无缝地集成VisualStudio工具箱中。本文将介绍界面组件TelerikUIforWPF在今......
  • WPF TextBox not allowed illegal characters to be input and limit the text length
    //xaml<Windowx:Class="WpfApp224.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.mi......
  • [WPF] 脱机环境实现支持拼音模糊搜索的AutoCompleteBox
    AutoCompleteBox是一个常见的提高输入效率的组件,很多WPF的第三方控件库都提供了这个组件,但基本都是字符串的子串匹配,不支持拼音模糊匹配,例如无法通过输入ldh或liudehua匹配到刘德华。要实现拼音模糊搜索功能,通常会采用分词、数据库等技术对待匹配数据集进行预处理。某些场景受制于......
  • 边缘设备使用记录--阿加犀AIBox 6490(realsense+yolox部署)
    边缘设备使用记录--阿加犀AIBox6490:realsense+yolox部署前言RealsenseSDK+ROSYOLOx部署预处理后处理可视化ROS节点总结前言由于6490这个板子是有type-c接口的,所以这里准备用Realsense+YOLOx来先简单做一个实时的目标检测的东西出来,这里也用到上一篇文章所提到......
  • wpf样式学习
    学习大佬视频地址:https://www.bilibili.com/video/BV1nY411a7T8/?p=58&spm_id_from=333.788.top_right_bar_window_history.content.click&vd_source=a4e06be300e655612460fd5149552558wpf样式加载窗体加载<Window.Resources><StyleTargetType="Button"......