抛砖引玉 【镜像控件】 WPF实现毛玻璃控件不要太简单

简介: 原文:抛砖引玉 【镜像控件】 WPF实现毛玻璃控件不要太简单 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Vblegend_2013/article/details/83447420 ...
原文: 抛砖引玉 【镜像控件】 WPF实现毛玻璃控件不要太简单

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Vblegend_2013/article/details/83447420

源码已封装成 MirrorGrid类 可以直接在XAML里添加

根据需要可以把Grid 改为  button border等控件

注意 Target必须为当前控件下层的控件对象

 

加个BlurEffect就是毛玻璃效果

<!--玻璃层控件-->
        <local:MirrorGrid
            Background="Red"
            Target="{Binding ElementName=box}"
            Width="150"
            Height="100"
            x:Name="thumb" Margin="0,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" MouseDown="thumb_MouseDown" MouseMove="thumb_MouseMove" MouseUp="thumb_MouseUp">
            <local:MirrorGrid.Effect>
                <BlurEffect  Radius="20" RenderingBias="Performance"/>
            </local:MirrorGrid.Effect>
        </local:MirrorGrid>

 

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace WpfApp2
{
    /// <summary>
    /// 镜像格子
    /// </summary>
    public class MirrorGrid : Grid
    {

        /// <summary>
        /// 目标对象
        /// </summary>
        public FrameworkElement Target
        {
            get { return (FrameworkElement)GetValue(TargetProperty); }
            set { SetValue(TargetProperty, value); }
        }

        /// <summary>
        /// 目标对象属性
        /// </summary>
        public static readonly DependencyProperty TargetProperty =
        DependencyProperty.Register("Target", typeof(FrameworkElement), typeof(MirrorGrid),
        new FrameworkPropertyMetadata(null));

        /// <summary>
        /// 重写基类 Margin
        /// </summary>
        public new Thickness Margin
        {
            get { return (Thickness)GetValue(MarginProperty); }
            set { SetValue(MarginProperty, value); }
        }
        public new static readonly DependencyProperty MarginProperty = DependencyProperty.Register("Margin", typeof(Thickness), typeof(MirrorGrid), new FrameworkPropertyMetadata(new Thickness(0), new PropertyChangedCallback(OnMarginChanged)));
        private static void OnMarginChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            ((FrameworkElement)target).Margin = (Thickness)e.NewValue;
            //强制渲染
            ((FrameworkElement)target).InvalidateVisual();
        }

        protected override void OnRender(DrawingContext dc)
        {
            var Rect = new Rect(0, 0, RenderSize.Width, RenderSize.Height);
            if (Target == null)
            {
                dc.DrawRectangle(this.Background, null, Rect);
            }
            else
            {
                this.DrawImage(dc, Rect);
            }

        }

        private void DrawImage(DrawingContext dc, Rect rect)
        {
            VisualBrush brush = new VisualBrush(Target)
            {
                Stretch = Stretch.Fill,
            };
            var tl = this.GetElementLocation(Target);
            var sl = this.GetElementLocation(this);
            var lx = (sl.X - tl.X) / Target.ActualWidth;
            var ly = (sl.Y - tl.Y) / Target.ActualHeight;
            var pw = this.ActualWidth / Target.ActualWidth;
            var ph = this.ActualHeight / Target.ActualHeight;
            brush.Viewbox = new Rect(lx, ly, pw, ph);
            dc.DrawRectangle(brush, null, rect);
        }


        /// <summary>
        /// 获取控件元素在窗口的实际位置
        /// </summary>
        /// <param name="Control"></param>
        /// <returns></returns>
        public Point GetElementLocation(FrameworkElement Control)
        {
            Point location = new Point(0, 0);
            FrameworkElement element = Control;
            while (element != null)
            {
                var Offset = VisualTreeHelper.GetOffset(element);
                location = location + Offset;
                element = (FrameworkElement)VisualTreeHelper.GetParent(element);
            }
            return location;
        }

    }
}

 

测试源码

<Window x:Class="WpfApp2.Window1"
        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:WpfApp2"
        mc:Ignorable="d"
        Title="Window1" Height="450" Width="800">
    <Grid ClipToBounds="True">
        <!--下层被模糊层-->
        <Grid x:Name="box"
              Background="AntiqueWhite"
              HorizontalAlignment="Left" Height="332" VerticalAlignment="Top" Width="551">
            <Grid HorizontalAlignment="Left" Height="260" Margin="0,0,0,0" VerticalAlignment="Top" Width="345">
                <Grid.Background>
                    <ImageBrush ImageSource="123.png"/>
                </Grid.Background>
            </Grid>
            <Ellipse Fill="#FFF4F4F5" HorizontalAlignment="Left" Height="114" Margin="345,218,0,0" Stroke="Black" VerticalAlignment="Top" Width="206"/>
        </Grid>
        <!--玻璃层控件-->
        <local:MirrorGrid
            Background="Red"
            Target="{Binding ElementName=box}"
            Width="150"
            Height="100"
            x:Name="thumb" Margin="0,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" MouseDown="thumb_MouseDown" MouseMove="thumb_MouseMove" MouseUp="thumb_MouseUp">
            <local:MirrorGrid.Effect>
                <BlurEffect  Radius="20" RenderingBias="Performance"/>
            </local:MirrorGrid.Effect>
        </local:MirrorGrid>
        <!--测试边框线-->
        <Rectangle Stroke="#FF2DEC0E"  
                   IsHitTestVisible="False"
                   Width="{Binding ElementName=thumb, Path=Width}"
                   Height="{Binding ElementName=thumb, Path=Height}"
                   Margin="{Binding ElementName=thumb, Path=Margin}"
                   HorizontalAlignment="Left" VerticalAlignment="Top"/>


    </Grid>
</Window>

 

后台

using System.Windows;
using System.Windows.Input;

namespace WpfApp2
{
    /// <summary>
    /// Window1.xaml 的交互逻辑
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }


        private bool isDragging;
        private Point clickPosition;

        private void thumb_MouseDown(object sender, MouseButtonEventArgs e)
        {
            isDragging = true;
            var draggableElement = sender as UIElement;
            clickPosition = e.GetPosition(this);
            draggableElement.CaptureMouse();
        }

        private void thumb_MouseUp(object sender, MouseButtonEventArgs e)
        {
            isDragging = false;
            var draggableElement = sender as UIElement;
            draggableElement.ReleaseMouseCapture();
        }

        private void thumb_MouseMove(object sender, MouseEventArgs e)
        {
            var draggableElement = sender as UIElement;
            if (isDragging && draggableElement != null)
            {
                Point currentPosition = e.GetPosition(this.Parent as UIElement);
                Thickness s = new Thickness(thumb.Margin.Left + currentPosition.X - clickPosition.X, thumb.Margin.Top + currentPosition.Y - clickPosition.Y,0,0);
                thumb.Margin = s;
                clickPosition = currentPosition;
            }
        }



    }
}

 

 

目录
相关文章
|
14天前
|
C# 开发者 Windows
基于Material Design风格开源、易用、强大的WPF UI控件库
基于Material Design风格开源、易用、强大的WPF UI控件库
|
4月前
|
C#
浅谈WPF之装饰器实现控件锚点
使用过visio的都知道,在绘制流程图时,当选择或鼠标移动到控件时,都会在控件的四周出现锚点,以便于修改大小,移动位置,或连接线等,那此功能是如何实现的呢?在WPF开发中,想要在控件四周实现锚点,可以通过装饰器来实现,今天通过一个简单的小例子,简述如何在WPF开发中,应用装饰器,仅供学习分享使用,如有不足之处,还请指正。
65 1
|
8月前
|
C# Windows
WPF技术之图形系列Polygon控件
WPF Polygon是Windows Presentation Foundation (WPF)框架中的一个标记元素,用于绘制多边形形状。它可以通过设置多个点的坐标来定义多边形的形状,可以绘制任意复杂度的多边形。
454 0
|
8月前
|
C# Windows
WPF技术之RichTextBox控件
WPF RichTextBox是Windows Presentation Foundation (WPF)中提供的一个强大的文本编辑控件,它可以显示富文本格式的文本,支持多种文本处理操作。
346 0
|
4月前
|
前端开发 C# 容器
浅谈WPF之控件拖拽与拖动
使用过office的visio软件画图的小伙伴都知道,画图软件分为两部分,左侧图形库,存放各种图标,右侧是一个画布,将左侧图形库的图标控件拖拽到右侧画布,就会生成一个新的控件,并且可以自由拖动。那如何在WPF程序中,实现类似的功能呢?今天就以一个简单的小例子,简述如何在WPF中实现控件的拖拽和拖动,仅供学习分享使用,如有不足之处,还请指正。
107 2
|
8月前
|
数据挖掘 数据处理 C#
WPF技术之DataGrid控件
WPF DataGrid是一种可以显示和编辑数据的界面控件。它可以作为表格形式展示数据,支持添加、删除、修改、排序和分组操作。
180 0
|
15天前
|
C# 开发者 C++
一套开源、强大且美观的WPF UI控件库
一套开源、强大且美观的WPF UI控件库
128 0
|
5月前
|
算法 C# UED
浅谈WPF之控件模板和数据模板
WPF不仅支持传统的Windows Forms编程的用户界面和用户体验设计,同时还推出了以模板为核心的新一代设计理念。在WPF中,通过引入模板,将数据和算法的“内容”和“形式”进行解耦。模板主要分为两大类:数据模板【Data Template】和控件模板【Control Template】。
95 8
|
8月前
|
定位技术 C# UED
WPF技术之ScrollViewer控件
WPF ScrollViewer是WPF中常用的一个控件,它提供了滚动视图的功能,可用于显示超出容器可视区域的内容。ScrollViewer通常用于容纳大量内容的控件,以在有限的空间内显示这些内容,并允许用户通过滚动来查看隐藏的部分。
699 0
|
8月前
|
前端开发 C#
WPF技术之ContentControl 控件
ContentControl 是 WPF 中的一个常见控件,用于显示单个内容元素。它可以包含任意类型的内容,包括文本、图像、控件等。
769 0