WPF实现窗体中的悬浮按钮

WPF实现窗体中的悬浮按钮,按钮可拖动,吸附停靠在窗体边缘。

控件XAML代码:

<Button x:Class="SunCreate.Common.Controls.FloatButton"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300"
             Width="50" Height="50" Margin="0" 
             HorizontalAlignment="Left" VerticalAlignment="Top" 
             x:Name="btn"
             Loaded="btn_Loaded" Click="btn_Click" >
    <Button.Template>
        <ControlTemplate>
            <Grid MouseLeftButtonDown="Border_MouseLeftButtonDown">
                <Border CornerRadius="25" Background="#022938" Opacity="0.2" >
                </Border>
                <Border CornerRadius="20" Width="40" Height="40" Background="#022938" Opacity="0.3" >
                </Border>
                <Border CornerRadius="14" Width="28" Height="28" Background="#b06919" Opacity="0.8" >
                </Border>
            </Grid>
        </ControlTemplate>
    </Button.Template>
</Button>
View Code

控件cs代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SunCreate.Common.Controls
{
    /// <summary>
    /// 悬浮按钮
    /// </summary>
    public partial class FloatButton : Button
    {
        public event EventHandler ClickEvent;

        private bool _move = false;
        double _distance = 200;
        double _distanceNew = 5;
        private Point _lastPos;
        private Point _newPos;
        private Point _oldPos;

        public FloatButton()
        {
            InitializeComponent();
        }

        private void btn_Loaded(object sender, RoutedEventArgs e)
        {
            if (this.Parent != null && this.Parent is FrameworkElement)
            {
                FrameworkElement parent = this.Parent as FrameworkElement;
                double left1 = parent.ActualWidth - this.ActualWidth - this._distanceNew;
                double top1 = parent.ActualHeight - this.ActualHeight - this._distanceNew;
                this.Margin = new Thickness(left1, top1, 0, 0);

                parent.PreviewMouseMove += (s, ee) =>
                {
                    if (_move)
                    {
                        Point pos = ee.GetPosition(parent);
                        double left = this.Margin.Left + pos.X - this._lastPos.X;
                        double top = this.Margin.Top + pos.Y - this._lastPos.Y;
                        this.Margin = new Thickness(left, top, 0, 0);

                        _lastPos = ee.GetPosition(parent);
                    }
                };

                parent.PreviewMouseUp += (s, ee) =>
                {
                    if (_move)
                    {
                        _move = false;

                        Point pos = ee.GetPosition(parent);
                        _newPos = pos;
                        double left = this.Margin.Left + pos.X - this._lastPos.X;
                        double top = this.Margin.Top + pos.Y - this._lastPos.Y;
                        double right = parent.ActualWidth - left - this.ActualWidth;
                        double bottom = parent.ActualHeight - top - this.ActualHeight;

                        if (left < _distance && top < _distance) //左上
                        {
                            left = this._distanceNew;
                            top = this._distanceNew;
                        }
                        else if (left < _distance && bottom < _distance) //左下
                        {
                            left = this._distanceNew;
                            top = parent.ActualHeight - this.ActualHeight - this._distanceNew;
                        }
                        else if (right < _distance && top < _distance) //右上
                        {
                            left = parent.ActualWidth - this.ActualWidth - this._distanceNew;
                            top = this._distanceNew;
                        }
                        else if (right < _distance && bottom < _distance) //右下
                        {
                            left = parent.ActualWidth - this.ActualWidth - this._distanceNew;
                            top = parent.ActualHeight - this.ActualHeight - this._distanceNew;
                        }
                        else if (left < _distance && top > _distance && bottom > _distance) //
                        {
                            left = this._distanceNew;
                            top = this.Margin.Top;
                        }
                        else if (right < _distance && top > _distance && bottom > _distance) //
                        {
                            left = parent.ActualWidth - this.ActualWidth - this._distanceNew;
                            top = this.Margin.Top;
                        }
                        else if (top < _distance && left > _distance && right > _distance) //
                        {
                            left = this.Margin.Left;
                            top = this._distanceNew;
                        }
                        else if (bottom < _distance && left > _distance && right > _distance) //
                        {
                            left = this.Margin.Left;
                            top = parent.ActualHeight - this.ActualHeight - this._distanceNew;
                        }

                        ThicknessAnimation marginAnimation = new ThicknessAnimation();
                        marginAnimation.From = this.Margin;
                        marginAnimation.To = new Thickness(left, top, 0, 0);
                        marginAnimation.Duration = TimeSpan.FromMilliseconds(200);

                        Storyboard story = new Storyboard();
                        story.FillBehavior = FillBehavior.Stop;
                        story.Children.Add(marginAnimation);
                        Storyboard.SetTargetName(marginAnimation, "btn");
                        Storyboard.SetTargetProperty(marginAnimation, new PropertyPath("(0)", Border.MarginProperty));

                        story.Begin(this);

                        this.Margin = new Thickness(left, top, 0, 0);
                    }
                };
            }
        }

        private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (this.Parent != null && this.Parent is FrameworkElement)
            {
                FrameworkElement parent = this.Parent as FrameworkElement;
                _move = true;
                _lastPos = e.GetPosition(parent);
                _oldPos = _lastPos;
            }
        }

        private void btn_Click(object sender, RoutedEventArgs e)
        {
            if (_newPos.Equals(_oldPos))
            {
                if (ClickEvent != null)
                {
                    ClickEvent(sender, e);
                }
            }
        }
    }
}
View Code

如何使用:

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ui="clr-namespace:SunCreate.Common.Controls;assembly=SunCreate.Common.Controls"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="SunCreate.Common.Controls.Demo.MainWindow"
        Title="MainWindow" 
        Height="700" Width="1200" 
        Background="#ff10498c" 
        WindowStartupLocation="CenterScreen">
    <Grid>
        <ui:FloatButton x:Name="floatBtn" ></ui:FloatButton>
    </Grid>
</Window>
View Code

效果图:

 

posted @ 2018-11-22 16:43  0611163  阅读(6102)  评论(1编辑  收藏  举报