C# wpf 附加属性实现任意控件拖动调整大小

摘自这里 https://blog.csdn.net/u013113678/article/details/121719278
调试效果如下

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace Wpf
{
    public class GridAdorner : Adorner
    { //4条边
        Thumb _leftThumb, _topThumb, _rightThumb, _bottomThumb;
        //4个角
        Thumb _leftTopThumb, _rightTopThumb, _rightBottomThumb, _leftbottomThumb;
        //布局容器,如果不使用布局容器,则需要给上述8个控件布局,实现和Grid布局定位是一样的,会比较繁琐且意义不大。
        Grid _grid;
        UIElement _adornedElement;

        public GridAdorner(UIElement adornedEleemnt) : base(adornedEleemnt)
        {
            _adornedElement = adornedEleemnt;
            //初始化thumb
            _leftThumb = new Thumb();
            _leftThumb.HorizontalAlignment = HorizontalAlignment.Left;
            _leftThumb.VerticalAlignment = VerticalAlignment.Center;
            _leftThumb.Cursor = Cursors.SizeWE;
            _topThumb = new Thumb();
            _topThumb.HorizontalAlignment = HorizontalAlignment.Center;
            _topThumb.VerticalAlignment = VerticalAlignment.Top;
            _topThumb.Cursor = Cursors.SizeNS;
            _rightThumb = new Thumb();
            _rightThumb.HorizontalAlignment = HorizontalAlignment.Right;
            _rightThumb.VerticalAlignment = VerticalAlignment.Center;
            _rightThumb.Cursor = Cursors.SizeWE;
            _bottomThumb = new Thumb();
            _bottomThumb.HorizontalAlignment = HorizontalAlignment.Center;
            _bottomThumb.VerticalAlignment = VerticalAlignment.Bottom;
            _bottomThumb.Cursor = Cursors.SizeNS;
            _leftTopThumb = new Thumb();
            _leftTopThumb.HorizontalAlignment = HorizontalAlignment.Left;
            _leftTopThumb.VerticalAlignment = VerticalAlignment.Top;
            _leftTopThumb.Cursor = Cursors.SizeNWSE;
            _rightTopThumb = new Thumb();
            _rightTopThumb.HorizontalAlignment = HorizontalAlignment.Right;
            _rightTopThumb.VerticalAlignment = VerticalAlignment.Top;
            _rightTopThumb.Cursor = Cursors.SizeNESW;
            _rightBottomThumb = new Thumb();
            _rightBottomThumb.HorizontalAlignment = HorizontalAlignment.Right;
            _rightBottomThumb.VerticalAlignment = VerticalAlignment.Bottom;
            _rightBottomThumb.Cursor = Cursors.SizeNWSE;
            _leftbottomThumb = new Thumb();
            _leftbottomThumb.HorizontalAlignment = HorizontalAlignment.Left;
            _leftbottomThumb.VerticalAlignment = VerticalAlignment.Bottom;
            _leftbottomThumb.Cursor = Cursors.SizeNESW;
            _grid = new Grid();
            _grid.Children.Add(_leftThumb);
            _grid.Children.Add(_topThumb);
            _grid.Children.Add(_rightThumb);
            _grid.Children.Add(_bottomThumb);
            _grid.Children.Add(_leftTopThumb);
            _grid.Children.Add(_rightTopThumb);
            _grid.Children.Add(_rightBottomThumb);
            _grid.Children.Add(_leftbottomThumb);
            AddVisualChild(_grid);
            foreach (Thumb thumb in _grid.Children)
            {
                thumb.Width = 16;
                thumb.Height = 16;
                thumb.Background = Brushes.Red;
                thumb.Template = new ControlTemplate(typeof(Thumb))
                {
                    VisualTree = GetFactory(new SolidColorBrush(Colors.Red))
                };
                thumb.DragDelta += Thumb_DragDelta;
            }
        }

        protected override Visual GetVisualChild(int index)
        {
            return _grid;
        }

        protected override int VisualChildrenCount
        {
            get { return 1; }
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            Debug.WriteLine(finalSize.Width + ":" + finalSize.Height);
            //直接给grid布局,grid内部的thumb会自动布局。
            _grid.Arrange(new Rect(new Point(-_leftThumb.Width / 2, -_leftThumb.Height / 2), new Size(finalSize.Width + _leftThumb.Width, finalSize.Height + _leftThumb.Height)));
            Debug.WriteLine(finalSize.Width + ":1      " + finalSize.Height);

            return finalSize;
        }

        private FrameworkElementFactory GetFactory(SolidColorBrush back)
        {
            var fef = new FrameworkElementFactory(typeof(Ellipse));
            fef.SetValue(Ellipse.FillProperty, back);
            fef.SetValue(Ellipse.StrokeProperty, new SolidColorBrush((Color)ColorConverter.ConvertFromString("#999999")));
            fef.SetValue(Ellipse.StrokeThicknessProperty, (double)2);

            return fef;
        }

        private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            var c = _adornedElement as FrameworkElement;
            var thumb = sender as FrameworkElement;
            double left, top, right, bottom, width, height;
            if (thumb.HorizontalAlignment == HorizontalAlignment.Left)
            {
                right = c.Margin.Right;
                left = c.Margin.Left + e.HorizontalChange;
                width = (double.IsNaN(c.Width) ? c.ActualWidth : c.Width) - e.HorizontalChange;
            }
            else
            {
                left = c.Margin.Left;
                right = c.Margin.Right - e.HorizontalChange;
                width = (double.IsNaN(c.Width) ? c.ActualWidth : c.Width) + e.HorizontalChange;
            }

            if (thumb.VerticalAlignment == VerticalAlignment.Top)
            {
                bottom = c.Margin.Bottom;
                top = c.Margin.Top + e.VerticalChange;
                height = (double.IsNaN(c.Height) ? c.ActualHeight : c.Height) - e.VerticalChange;
            }
            else
            {
                top = c.Margin.Top;
                bottom = c.Margin.Bottom - e.VerticalChange;
                height = (double.IsNaN(c.Height) ? c.ActualHeight : c.Height) + e.VerticalChange;
            }

            if (thumb.HorizontalAlignment != HorizontalAlignment.Center)
            {
                if (width > 0)
                {
                    c.Margin = new Thickness(left, c.Margin.Top, right, c.Margin.Bottom);
                    c.Width = width;
                }
            }
            if (thumb.VerticalAlignment != VerticalAlignment.Center)
            {
                if (height > 0)
                {
                    c.Margin = new Thickness(c.Margin.Left, top, c.Margin.Right, bottom);
                    c.Height = height;
                }
            }
        }
    }
}

用法

<Window>
<Grid>
        <Border x:Name="border" Width="200" Height="200" Background="Gray" />
    </Grid>
</Window>

public partial class WinResize : Window
    {
        public WinResize()
        {
            InitializeComponent();
            this.Loaded += (s, e) => {
               var layer  =  AdornerLayer.GetAdornerLayer(border);
                layer.Add(new GridAdorner(border));
            };
        }
    }

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/32462.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【信号】信号处理与进程通信:快速上手

目录 0. 信号概述 1. 产生信号的方式&#xff1a; 1.1 当用户按某些终端键时&#xff0c;将产生信号。 1.2 硬件异常将产生信号。 1.3 软件异常将产生信号。 1.4 调用kill函数将发送信号。 1.5 运行kill命令将发送信号。 2. 信号的默认&#xff08;缺省&#xff09;处理…

Visual C++类的继承及类中成员的访问特性——搞懂public、protected、private

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天来说说Visual C中类的继承及类中成员的访问特性&#xff0c;也就是来搞懂public、protected、private这三个东西。 很多人搞不清楚这三个东西&#xff0c;并且很容易弄错&#xff0c;其实不是学习的人的…

ModaHub魔搭社区:向量数据库MIlvus服务端配置(三)

目录 gpu 区域 logs 区域 metric_config 区域 gpu 区域 在该区域选择是否在 Milvus 里启用 GPU 用于搜索和索引创建。同时使用 CPU 和 GPU 可以达到资源的最优利用&#xff0c;在特别大的数据集里做搜索时性能更佳。 若要切换到 CPU-only 模式&#xff0c;只要将 enable 设…

【VMD-LSTM】变分模态分解-长短时记忆神经网络研究(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

数据库大题

(计算题&#xff0c;20分) 设有两个关系R和S,求① R ∪ S R \cup S R∪S;② R − S R - S R−S;③ R S R \times S RS;④ ∏ C , A ( R ) \prod_{C,A}(R) ∏C,A​(R);⑤ σ B > ′ 4 ′ ( R ) \sigma_{B>4}(R) σB>′4′​(R) 关系R关系S (简答题&#xff0c;10…

基于深度学习FasterRCNN模型Restnet50 的生活垃圾智能分类(准确率达84%)-含python工程全源码

目录 前言总体设计系统整体结构图系统流程图 运行环境1. 硬件环境2. Python 环境 模块实现1. 数据预处理2. 数据加载3. 模型构建4. 模型训练及保存5. 模型加载与调用 系统测试1. 模型准确率2. 分类别准确率 工程源代码下载其它资料下载 前言 本项目基于Faster R-CNN模型&#…

jenkins流水线Pipeline的使用

pipeline流水线 1、jenkins安装pipeline插件 2、创建流水线项目 1、创建pipeline的流水线项目 2、编写流水线 pipeline {agent anystages {stage(拉去代码) {steps {git credentialsId: gitee, url: https://gitee.com/xwb1056481167/jenkins-demo.gitecho 拉去代码}}stage(m…

Vue中如何进行数据导入与Excel导入

Vue中如何进行数据导入与Excel导入 Vue是一款非常流行的JavaScript框架&#xff0c;它提供了一套用于构建用户界面的工具和库。在Vue中&#xff0c;我们可以使用多种方式来导入数据&#xff0c;包括从服务器获取数据、从本地存储获取数据、从文件中读取数据等等。其中&#xf…

NVIDIA Jetson TX1,TX2,TX2 NX,AGX Xavier 和 Nano开发板GPIO口配置及应用

NVIDIA Jetson TX1&#xff0c;TX2&#xff0c;TX2 NX&#xff0c;AGX Xavier 和 Nano开发板GPIO口配置及应用 简介 ​ Jetson TX1、TX2、TX2 NX、AGX Xavier和Nano开发板都配备了一个包含40个引脚的GPIO接头&#xff0c;这些引脚可以用于数字输入输出。如下图 ​ 类似于Rasp…

Solid Converter PDF v10 安装及使用教程

目录 一、软件介绍二、下载教程三、安装教程四、使用教程1.PDF转Word、Html等2.合并PDF文件 一、软件介绍 Solid Converter PDF是一套专门将PDF文件转换成Word的软件。 能够将PDF转换为Word、Excel、HTML、PowerPoint、纯文本文件从PDF文档中提取数据并以CSV等格式保存能够转…

【人工智能】— 深度神经网络、卷积神经网络(CNN)、多卷积核、全连接、池化

【人工智能】— 深度神经网络、卷积神经网络&#xff08;CNN&#xff09;、多卷积核、全连接、池化 深度神经网络训练训练深度神经网络参数共享 卷积神经网络&#xff08;CNN&#xff09;卷积多卷积核卷积全连接最大池化卷积池化拉平向量激活函数优化小结 深度神经网络训练 Pr…

Pytest+selenium+allure+Jenkins自动化测试框架搭建及使用

一、 环境搭建 1. Python下载及安装 Python可应用于多平台包括windows, Linux 和 Mac OS X, 本文主要介绍windows环境下。你可以通过终端窗口输入 "python" 命令来查看本地是否已经安装Python以及Python的安装版本。 如未安装python, 推荐下载python 3.8.3以…

Prompt的技巧持续总结

Prompt 有很多网站已经收录了&#xff0c;比如&#xff1a;aimappro 有些直接抄上述网站的作业即可&#xff0c;不过也来看看&#xff0c; 有一些日常提问大概的咒语该怎么写。 1 三种微调下的提示写法 chatgpt时代的创新&#xff1a;LLM的应用模式比较 实际案例说明AI时代大…

将win上的文件传输到Ubuntu虚拟机

首先获取Ubuntu系统的ip地址&#xff0c;在Ubuntu的Terminal中输入ifconfig&#xff0c;可以看到Ubuntu的ip地址 可以看到我电脑的ip地址是10.0.2.15。更改虚拟机的网络连接 这里以VirtualBox为例&#xff0c;打开VirtualBox设置&#xff0c;选择网络&#xff0c;将连接方式改…

通付盾入围《2023年度中国数字安全能力图谱(行业版)》

近日&#xff0c;数世咨询发布《2023年度中国数字安全能力图谱&#xff08;行业版&#xff09;》。通付盾作为以分布式数字身份和大数据决策智能技术为核心的数字化高端软件与服务提供商&#xff0c;凭借在数字安全领域的实力和影响力&#xff0c;入选政府、互联网两大行业细分…

ElasticSearch的安装和访问

ElasticSearch的安装 前言: 本次下载是在Windows系统进行操作,版本为7.6.1,因为下周最新版本的8.1.2有问题 ElasticSearch基于Java开发,JDK最低1.8版本 ElasticSearch的版本要和之后引入的Maven的Jar包版本对应 1 下载ElasticSearch 官网:https://www.elastic.co/cn/ 产品…

【yocto1】利用yocto工具构建嵌入式Linux系统

文章目录 1.获取Yocto软件源码2.初始化Yocto构建目录2.1 imx-setup-release.sh脚本运行2.2 imx-setup-release.sh脚本解析2.2.1 setup-environment脚本解析 3.构建嵌入式Linux系统3.1 BitBake构建系统3.2 BitBake构建系统过程简要解析3.2.1 解析Metadata基本配置Metadatarecipe…

Spring Boot面试题

什么是 Spring Boot&#xff1f; Spring Boot 是一个简化 Spring 应用程序开发的框架&#xff0c;通过自动配置、起步依赖和简化的配置方式&#xff0c;使开发人员能够更快速、方便地创建和配置 Spring 应用程序&#xff0c;提高开发效率和开发体验。 Spring Boot 的设计目标…

如何做一份干净的git提交记录

背景 毕业工作有一些年头了&#xff0c;之前在写工作代码或者给开源项目贡献的时候&#xff0c;提交代码都不是很规范&#xff0c;甚至可以说十分的随意&#xff0c;想到什么就提交什么&#xff0c;根本没有管理提交记录的概念或者想法&#xff08;当你身边的人都不怎么在意的…

基于 Wav2Lip-GFPGAN 深度学习模型的数字人Demo

写在前面 工作中遇到简单整理博文为 Wav2Lip-GFPGAN 环境搭建运行的 Demo理解不足小伙伴帮忙指正 对每个人而言&#xff0c;真正的职责只有一个&#xff1a;找到自我。然后在心中坚守其一生&#xff0c;全心全意&#xff0c;永不停息。所有其它的路都是不完整的&#xff0c;是…