WPF实现窗体中的悬浮按钮

简介: 原文:WPF实现窗体中的悬浮按钮WPF实现窗体中的悬浮按钮,按钮可拖动,吸附停靠在窗体边缘。 控件XAML代码: ...
原文: 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 left = parent.ActualWidth - this.ActualWidth - this._distanceNew;
                double top = parent.ActualHeight - this.ActualHeight - this._distanceNew;
                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;

                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 = e.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 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

效果图:

 

目录
相关文章
|
C#
WPF 界面实现多语言支持 中英文切换 动态加载资源字典
原文:WPF 界面实现多语言支持 中英文切换 动态加载资源字典 1、使用资源字典,首先新建两个字典文件en-us.xaml、zh-cn.xaml。定义中英文的字符串在这里面【注意:添加xmlns:s="clr-namespace:System;assembly=mscorlib】 zh-cn.
3209 0
WPF控件和窗体一起放大一起缩小
WPF控件和窗体一起放大一起缩小
254 0
|
C# 容器
WPF框架下,窗体的嵌套显示
WPF框架下,窗体的嵌套显示
238 0
|
IDE C# 开发工具
WPF钟表效果实现
中WPF中的RotateTransform实现UI元素的旋转,并模拟钟表的秒针、分针和时针。
1204 0
WPF钟表效果实现
|
IDE 编译器 C#
WPF实现强大的动态公式计算
数据库可以定义表不同列之间的计算公式,进行自动公式计算,但如何实现行上的动态公式计算呢?行由于可以动态扩展,在某些应用场景下将能很好的解决实际问题。本文就探讨一下如何在WPF中实现一种基于行字段的动态公式计算。
1087 0
WPF实现强大的动态公式计算
|
网络协议 C# 移动开发
C# WPF上位机实现和下位机TCP通讯
C# WPF上位机实现和下位机TCP通讯下位机使用北京大华程控电源DH1766-1,上位机使用WPF。实现了电压电流实时采集,曲线显示。上午在公司调试成功,手头没有程控电源,使用TCP服务端模拟。昨天写的TCP服务端正好排上用场。
2416 0
|
C#
wpf窗体定位
原文:wpf窗体定位 据WPF外包小编了解,通常,不需要在屏幕上明确定位窗口。而是简单地将WindowState属性设置为Normal,并忽略其他所有细节。另一方面,很少会将WindowStartupLocation属性设置为Manual,并使用Left属性和Right属性明确设置窗口的位置。
881 0
|
C#
在WPF中快速实现键盘钩子
原文:在WPF中快速实现键盘钩子 大部分的时候,当我们需要键盘事件的时候,可以通过在主窗口注册KeyBinding来实现,不过,有的时候我们需要的是全局键盘事件,想在任何一个地方都能使用,最开始的时候我是通过键盘钩子来实现的, 不过键盘钩子这种DLL调用的方式怎么都看着不大爽,这里介绍一种通过EventManager快速实现键盘事件感知的例子。
1099 0
|
C# C++ Windows
WPF中不规则窗体与WindowsFormsHost控件的兼容问题完美解决方案
原文:WPF中不规则窗体与WindowsFormsHost控件的兼容问题完美解决方案          首先先得瑟一下,有关WPF中不规则窗体与WindowsFormsHost控件不兼容的问题,网上给出的解决方案不能满足所有的情况,是有特定条件的,比如  WPF中不规则窗体与WebBrowser控件的兼容问题解决办法。
1326 0
|
C#
WPF中获取TreeView以及ListView获取其本身滚动条的方法,可实现自行调节scoll滚动的位置(可相应获取任何控件中的内部滚动条)
原文:WPF中获取TreeView以及ListView获取其本身滚动条的方法,可实现自行调节scoll滚动的位置(可相应获取任何控件中的内部滚动条) 对于TreeView而言: TreeViewAutomationPeer lvap = new TreeViewAuto...
2408 0