使用鼠标拖动边缘来调整 Thumb 控件的大小

2024-02-03

我需要一个可以使用鼠标调整大小的拇指控件。当用户将鼠标悬停在其中一端时,应显示一个大小光标,当用户单击并拖动控件的一端时,它将重新调整大小。

如何才能做到这一点?


这是我不久前制作的一个,它允许Move and Resize,但您可以删除Move逻辑,它应该工作得很好(风格仍然有点混乱,但工作得很好)

其基于ContentControl所以你可以添加任何Element内部并移动/调整大小Canvas,它使用 3Adorners,一个用于调整大小,一个用于移动,一个用于显示信息(当前大小)

如果您想测试/使用/修改/改进,这里有一个完整的工作示例:)

Code:

namespace WpfApplication21
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }

    public class ResizeThumb : Thumb
    {
        public ResizeThumb()
        {
            DragDelta += new DragDeltaEventHandler(this.ResizeThumb_DragDelta);
        }

        private void ResizeThumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            Control designerItem = this.DataContext as Control;

            if (designerItem != null)
            {
                double deltaVertical, deltaHorizontal;

                switch (VerticalAlignment)
                {
                    case VerticalAlignment.Bottom:
                        deltaVertical = Math.Min(-e.VerticalChange, designerItem.ActualHeight - designerItem.MinHeight);
                        designerItem.Height -= deltaVertical;
                        break;
                    case VerticalAlignment.Top:
                        deltaVertical = Math.Min(e.VerticalChange, designerItem.ActualHeight - designerItem.MinHeight);
                        Canvas.SetTop(designerItem, Canvas.GetTop(designerItem) + deltaVertical);
                        designerItem.Height -= deltaVertical;
                        break;
                    default:
                        break;
                }

                switch (HorizontalAlignment)
                {
                    case HorizontalAlignment.Left:
                        deltaHorizontal = Math.Min(e.HorizontalChange, designerItem.ActualWidth - designerItem.MinWidth);
                        Canvas.SetLeft(designerItem, Canvas.GetLeft(designerItem) + deltaHorizontal);
                        designerItem.Width -= deltaHorizontal;
                        break;
                    case HorizontalAlignment.Right:
                        deltaHorizontal = Math.Min(-e.HorizontalChange, designerItem.ActualWidth - designerItem.MinWidth);
                        designerItem.Width -= deltaHorizontal;
                        break;
                    default:
                        break;
                }
            }

            e.Handled = true;
        }
    }


    public class MoveThumb : Thumb
    {
        public MoveThumb()
        {
            DragDelta += new DragDeltaEventHandler(this.MoveThumb_DragDelta);
        }

        private void MoveThumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            Control designerItem = this.DataContext as Control;

            if (designerItem != null)
            {
                double left = Canvas.GetLeft(designerItem);
                double top = Canvas.GetTop(designerItem);

                Canvas.SetLeft(designerItem, left + e.HorizontalChange);
                Canvas.SetTop(designerItem, top + e.VerticalChange);
            }
        }
    }

    public class SizeAdorner : Adorner
    {
        private Control chrome;
        private VisualCollection visuals;
        private ContentControl designerItem;

        protected override int VisualChildrenCount
        {
            get
            {
                return this.visuals.Count;
            }
        }

        public SizeAdorner(ContentControl designerItem)
            : base(designerItem)
        {
            this.SnapsToDevicePixels = true;
            this.designerItem = designerItem;
            this.chrome = new Control();
            this.chrome.DataContext = designerItem;
            this.visuals = new VisualCollection(this);
            this.visuals.Add(this.chrome);
        }

        protected override Visual GetVisualChild(int index)
        {
            return this.visuals[index];
        }

        protected override Size ArrangeOverride(Size arrangeBounds)
        {
            this.chrome.Arrange(new Rect(new Point(0.0, 0.0), arrangeBounds));
            return arrangeBounds;
        }
    }
}

Xaml:

<Window x:Class="WpfApplication21.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication21"
        Title="MainWindow" Height="350" Width="525">

    <Window.Resources>

        <Style TargetType="{x:Type ContentControl}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ContentControl}">
                        <Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
                            <local:MoveThumb Cursor="SizeAll">
                                <local:MoveThumb.Style>
                                    <Style TargetType="{x:Type local:MoveThumb}">
                                        <Setter Property="Template">
                                            <Setter.Value>
                                                <ControlTemplate TargetType="{x:Type local:MoveThumb}">
                                                    <Rectangle Fill="Transparent" />
                                                </ControlTemplate>
                                            </Setter.Value>
                                        </Setter>
                                    </Style>
                                </local:MoveThumb.Style>
                            </local:MoveThumb>
                            <Control x:Name="resizer">
                                <Control.Style>
                                    <Style TargetType="{x:Type Control}">
                                        <Setter Property="Template">
                                            <Setter.Value>
                                                <ControlTemplate TargetType="{x:Type Control}">
                                                    <Grid>
                                                        <Grid Opacity="0" Margin="-3">
                                                            <local:ResizeThumb Height="3" Cursor="SizeNS" VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
                                                            <local:ResizeThumb Width="3" Cursor="SizeWE" VerticalAlignment="Stretch" HorizontalAlignment="Left"/>
                                                            <local:ResizeThumb Width="3" Cursor="SizeWE" VerticalAlignment="Stretch" HorizontalAlignment="Right"/>
                                                            <local:ResizeThumb Height="3" Cursor="SizeNS" VerticalAlignment="Bottom" HorizontalAlignment="Stretch"/>
                                                            <local:ResizeThumb Width="7" Height="7" Margin="-2" Cursor="SizeNWSE" VerticalAlignment="Top" HorizontalAlignment="Left"/>
                                                            <local:ResizeThumb Width="7" Height="7" Margin="-2" Cursor="SizeNESW" VerticalAlignment="Top" HorizontalAlignment="Right"/>
                                                            <local:ResizeThumb Width="7" Height="7" Margin="-2" Cursor="SizeNESW" VerticalAlignment="Bottom" HorizontalAlignment="Left"/>
                                                            <local:ResizeThumb Width="7" Height="7" Margin="-2" Cursor="SizeNWSE" VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
                                                        </Grid>
                                                        <Grid IsHitTestVisible="False" Opacity="1" Margin="-3">
                                                            <Grid.Resources>
                                                                <Style TargetType="{x:Type Ellipse}">
                                                                    <Setter Property="SnapsToDevicePixels" Value="true" />
                                                                    <Setter Property="Stroke" Value="#FFC8C8C8" />
                                                                    <Setter Property="StrokeThickness" Value=".5" />
                                                                    <Setter Property="Width" Value="7" />
                                                                    <Setter Property="Height" Value="7" />
                                                                    <Setter Property="Margin" Value="-2" />
                                                                    <Setter Property="Fill" Value="Silver" />
                                                                </Style>
                                                            </Grid.Resources>
                                                            <Rectangle SnapsToDevicePixels="True" StrokeThickness="1" Margin="1" Stroke="Black"  StrokeDashArray="4 4"/>
                                                            <Ellipse  HorizontalAlignment="Left" VerticalAlignment="Top"/>
                                                            <Ellipse  HorizontalAlignment="Right" VerticalAlignment="Top"/>
                                                            <Ellipse HorizontalAlignment="Left" VerticalAlignment="Bottom"/>
                                                            <Ellipse  HorizontalAlignment="Right" VerticalAlignment="Bottom"/>
                                                        </Grid>
                                                    </Grid>
                                                </ControlTemplate>
                                            </Setter.Value>
                                        </Setter>
                                    </Style>
                                </Control.Style>
                            </Control>
                            <Grid x:Name="sizeInfo" SnapsToDevicePixels="True">
                                <Path Stroke="Red" StrokeThickness="1" Height="10" VerticalAlignment="Bottom" Margin="-2,0,-2,-15" Stretch="Fill" Data="M0,0 0,10 M 0,5 100,5 M 100,0 100,10"/>
                                <TextBlock Text="{Binding Width}" Background="White" Padding="3,0,3,0" Foreground="Red" Margin="0,0,0,-18" HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
                                <Path Stroke="Red" StrokeThickness="1" Width="10" HorizontalAlignment="Right" Margin="0,-2,-15,-2" Stretch="Fill" Data="M5,0 5,100 M 0,0 10,0 M 0,100 10,100"/>
                                <TextBlock Text="{Binding Height}" Background="White" Foreground="Red" Padding="3,0,3,0" Margin="0,0,-18,0" HorizontalAlignment="Right" VerticalAlignment="Center">
                                    <TextBlock.LayoutTransform>
                                        <RotateTransform Angle="90" CenterX="1" CenterY="0.5"/>
                                    </TextBlock.LayoutTransform>
                                </TextBlock>
                            </Grid>
                            <ContentPresenter Content="{TemplateBinding Content}"/>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger  Property="IsMouseOver" Value="True">
                                <Setter TargetName="sizeInfo" Property="Visibility" Value="Visible" />
                            </Trigger>
                            <Trigger  Property="IsMouseOver" Value="False">
                                <Setter TargetName="sizeInfo" Property="Visibility" Value="Hidden" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    </Window.Resources>

    <Canvas>
        <ContentControl Width="183" Height="110"  Canvas.Left="166" Canvas.Top="50" />
    </Canvas>
</Window>

Result:

里面有内容(按钮)

抱歉,使用 SnipTool 时光标不显示

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用鼠标拖动边缘来调整 Thumb 控件的大小 的相关文章

随机推荐

  • Spring MVC:如何修改从spring控制器发送的响应?

    我有一个使用 Spring MVC 3 1 3 的应用程序和使用 Dojo 1 4 开发的 UI 该应用程序有几个控制器来处理通过上传的二进制文件dojo io iframe send 控制器发送一个 json 响应 该响应必须用
  • 面板未获得焦点

    我继续在我的简单图形程序中 使用 C 编写某种键盘导航 而我又遇到了麻烦 我的问题是我想处理键盘输入以移动图层 用鼠标移动图层已经可以很好地工作 但控件没有获得焦点 此控件既不会触发 KeyUp KeyDown KeyPress 也不会触发
  • 使用 Zend 框架进行连接更新

    我试图在 mysql 上使用 zend 更新带有连接的表 下面是我想通过 zend 执行的查询 已经谢谢了 UPDATE tbproduto LEFT JOIN SELECT codigo as codTipoProduto cdTipo
  • 如何从.Net Core 3创建Windows服务[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 最近我需要将 Net Core 3 0控制台应用程序转换为Windows服务 由于我不需要将此流程移植
  • Gif 帧持续时间似乎比预期慢

    我正在使用枕头图像库创建 GIF 我遇到了一个问题 我试图以尽可能最小的帧持续时间使某些帧闪烁得非常快 但是当我将帧的持续时间设置为 1 可能的最低持续时间 GIF 的持续时间为 100 实际上它的持续时间似乎比预期的要长 我用一个简单的方
  • 如何使一个 跨越两列表中的两列?

    如何使用 HTML 和 CSS 创建像上面示例一样的表格 我尝试过以下方法 table tr td style width 50 TEXT td td style width 50 TEXT td tr tr td style width
  • 以编程方式创建 UITableView

    我在 Xcode 4 6 中有一个使用故事板的应用程序 我将 UITableView 添加到视图控制器类中 它按预期工作 然而 当我尝试删除故事板中的 UITableView 并以编程方式将其添加回同一个类时 我遇到了两个具体问题 1 虽然
  • 具有自定义身份验证的 ASP.NET Web API

    我正在寻求帮助创建具有自定义用户名 密码身份验证的 Web API 我有自己的数据库来验证用户 我不想使用 Windows 身份验证 我希望能够用类似的属性来装饰我的 Web api 调用 Authorize 这样在未登录的情况下进行的调用
  • VSCode:无法导入 Golang 包

    我正在 GoPath 中编写一个 Go 项目 并使用 Redigo 包连接到 Redis 服务器 应用程序运行良好 但是在 VSCode 中 包导入时出现这个烦人的错误 这导致 VSCode 无法提供智能感知建议 无法导入 github c
  • 具有 facebook 身份验证和唯一 ID 的 Firebase 规则

    我正在寻找一些建议或可能的解决方案来加强我的火力规则 这是我在 Firebase 中的用户树 users male uid female uid UID 将是创建帐户时的纪元时间戳 它是一个有符号整数 这些是 firebase 规则 基本上
  • 为什么我不能在此查询中使用WITH(通用表表达式)?

    这只是一个 SSCCE CREATE TABLE test i INTEGER NOT NULL WITH max i AS SELECT MAX i FROM test SELECT FROM test WHERE max i i lt
  • jQuery 的 :first 和 :last 在元素的第一个子元素上

    我有一些简单的表 多个 全部带有 class parent 其中有多个 tr 行 这 td 这些行中的单元格有自己的表格 我正在尝试瞄准 tr 的行first 父 表 如下所示 HTML table class parent tr lt m
  • pip3读取超时错误

    sudo pip3 install scikit learn 任何模块实际上只是使用最近的尝试 sudo pip3 install U scikit learn sudo H pip3 install U scikit learn sudo
  • 我应该在 Android 应用程序中将全局方法和变量放在哪里?

    当我编写方法或使用成员变量时 我经常发现需要在应用程序中共享它们 但他们应该去哪里呢 我可以对 Activity 进行子类化 但是一旦我使用 MapView 并被迫使用 MapActivity 这种情况就会失败 因此并非所有活动都继承自我的
  • 如何找到 virtualenv python 的路径

    如何找到使用本教程构建的 virtualenv python 的路径 我想在这个环境中找到python并在我的eclipse中使用它 sudo pip install virtualenv virtualenvwrapper export
  • C中声明语句和赋值语句的区别? [复制]

    这个问题在这里已经有答案了 我是编程新手 正在尝试学习 C 我正在读一本书 我在其中读到了这些语句 但无法理解它们的含义 宣言 int a 任务 a 3 声明和赋值在一个语句中 int a 3 声明说 我将使用一个名为 的变量a 存储一个整
  • 我在pandas DataFrame中有字符串索引,如何通过startswith进行选择?

    在数据框中 我有一个来自国家列的索引 但我做不到 df df Nation str startswith U 无需重置索引 如何获取索引的 str 对象 Use index与str nice df df index str startswi
  • JSEncrypt(js)加密,但python无法解密

    我正在尝试使用 JSEncrypt javascript 进行 RSA 加密文本 并使用 python crypto python3 7 进行解密 大多数时候 它是有效的 但有时 python无法解密 const encrypt new J
  • 将 AssemblyInfo.cs 中的程序集版本放入 Web.config 中

    我有这样的场景 其中我有来自 AssemblyInfo cs 的项目的程序集版本 例如 2 0 0 如下所示 assembly AssemblyVersion 2 0 0 此外 我想检索此 AssemblyVersion 并将其动态设置为
  • 使用鼠标拖动边缘来调整 Thumb 控件的大小

    我需要一个可以使用鼠标调整大小的拇指控件 当用户将鼠标悬停在其中一端时 应显示一个大小光标 当用户单击并拖动控件的一端时 它将重新调整大小 如何才能做到这一点 这是我不久前制作的一个 它允许Move and Resize 但您可以删除Mov