65.9K
CodeProject 正在变化。 阅读更多。
Home

运行时控件缩放器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.83/5 (15投票s)

2007 年 1 月 19 日

CPOL

5分钟阅读

viewsIcon

95243

downloadIcon

3780

一个未完成的类,用于在运行时调整控件的大小。

Sample Image - rtcontrolresizer.jpg

引言

我开始编写一个未完成的、简单的类,以回应最近在 microsoft.public.dotnet.languages.vb 新闻组上的一篇文章。

背景

不久前,我像往常一样浏览 VB.NET 新闻组,偶然看到一个让我感到困惑的问题。这个问题是如何在运行时提供调整控件大小的功能。这似乎相当简单,于是我启动了 C#(忘记了我在哪个新闻组看到了这个问题!)并开始编写一个快速解决方案——但它失败了。

于是我花了越来越多的时间在深夜调试它,并解决了大部分问题。最终,发帖人说他找到了一个解决方案,并写了一篇 CodeProject 文章。我心想:“啊哈,我也一样!”于是我停止了对代码的修改,想着至少能让别人有个开始。(也许以后我会完成它——谁知道呢?)

核心组件

用户控件

这里没有什么太复杂的。我只需要一个控件来代表那些“浮动”在待调整大小的控件外部的小白框。控件的主要作用只是根据控件的位置(左上角、顶部等)改变鼠标光标。

控制器类

这里的情况稍微有点冗长,但仍然不复杂。用几句话来说,控制器类首先创建必要的调整大小框(用户控件),并将它们放置在目标控件周围。类的其余部分只是处理鼠标移动事件,并根据特定调整大小框的移动来调整目标控件的大小。

调整大小框的代码

首先,我创建了一个枚举,列出了调整大小框可以拥有的所有可用位置(相对于目标)。然后,当然,我将这个枚举用作控件构造函数中的参数。

public enum BoxPosition
{
    Top,
    Bottom,
    Left,
    Right,
    TopLeft,
    TopRight,
    BottomLeft,
    BottomRight
}

public ResizeBox(BoxPosition position)
{
    InitializeComponent();
    this.Position = position;
}

好的,这没什么复杂的。接下来,我处理控件的 MouseEnterMouseLeave 事件,以便根据控件的 Position 属性(未显示)设置适当的箭头光标。这听起来像是 `switch` 语句的工作,对我来说!

private void ResizeBox_MouseEnter(object sender, EventArgs e)
{
    switch (this.Position)
    {
        case BoxPosition.Top:
            this.Cursor = Cursors.SizeNS;
            break;
        case BoxPosition.Bottom:
            this.Cursor = Cursors.SizeNS;
            break;
        case BoxPosition.Left:
            this.Cursor = Cursors.SizeWE;
            break;
        case BoxPosition.Right:
            this.Cursor = Cursors.SizeWE;
            break;
        case BoxPosition.TopLeft:
            this.Cursor = Cursors.SizeNWSE;
            break;
        case BoxPosition.BottomRight:
            this.Cursor = Cursors.SizeNWSE;
            break;
        case BoxPosition.TopRight:
            this.Cursor = Cursors.SizeNESW;
            break;
        case BoxPosition.BottomLeft:
            this.Cursor = Cursors.SizeNESW;
            break;
        default:
            this.Cursor = Cursors.No;
            break;
    }
}

private void ResizeBox_MouseLeave(object sender, EventArgs e)
{
    this.Cursor = Cursors.Default;
}

这差不多就是用户控件的精彩部分了——就像我说的,它很简单。

控制器类

首先,我需要创建一些变量来表示我将放置在目标周围的实际调整大小框。

private ResizeBox topBox;
private ResizeBox bottomBox;
private ResizeBox leftBox;
private ResizeBox rightBox;
private ResizeBox topLeftBox;
private ResizeBox topRightBox;
private ResizeBox bottomLeftBox;
private ResizeBox bottomRightBox;

在构造函数中,目标控件作为参数传递。我将其设置为一个属性,实例化 ResizeBox 对象,并将必要的事件映射到将处理它们的那些方法。构造函数还提供了一个立即显示调整大小句柄的选项。

public ResizeControl(Control target, Boolean showResizeBoxes)
{
    this._Target = target;

    target.Parent.Paint += new PaintEventHandler(Parent_Paint);

    topBox = new ResizeBox(ResizeBox.BoxPosition.Top);
    bottomBox = new ResizeBox(ResizeBox.BoxPosition.Bottom);
    leftBox = new ResizeBox(ResizeBox.BoxPosition.Left);
    rightBox = new ResizeBox(ResizeBox.BoxPosition.Right);
    topLeftBox = new ResizeBox(ResizeBox.BoxPosition.TopLeft);
    topRightBox = new ResizeBox(ResizeBox.BoxPosition.TopRight);
    bottomLeftBox = new ResizeBox(ResizeBox.BoxPosition.BottomLeft);
    bottomRightBox = new ResizeBox(ResizeBox.BoxPosition.BottomRight);

    this.topLeftBox.MouseDown += new MouseEventHandler(Boxes_MouseDown);
    this.topBox.MouseDown += new MouseEventHandler(Boxes_MouseDown);
    this.topRightBox.MouseDown += new MouseEventHandler(Boxes_MouseDown);
    this.leftBox.MouseDown += new MouseEventHandler(Boxes_MouseDown);
    this.rightBox.MouseDown += new MouseEventHandler(Boxes_MouseDown);
    this.bottomLeftBox.MouseDown += new MouseEventHandler(Boxes_MouseDown);
    this.bottomBox.MouseDown += new MouseEventHandler(Boxes_MouseDown);
    this.bottomRightBox.MouseDown += new MouseEventHandler(Boxes_MouseDown);

    this.topLeftBox.MouseMove += new MouseEventHandler(topLeftBox_MouseMove);
    this.topBox.MouseMove += new MouseEventHandler(topBox_MouseMove);
    this.topRightBox.MouseMove += new MouseEventHandler(topRightBox_MouseMove);
    this.leftBox.MouseMove += new MouseEventHandler(leftBox_MouseMove);
    this.rightBox.MouseMove += new MouseEventHandler(rightBox_MouseMove);
    this.bottomLeftBox.MouseMove += 
         new MouseEventHandler(bottomLeftBox_MouseMove);
    this.bottomBox.MouseMove += new MouseEventHandler(bottomBox_MouseMove);
    this.bottomRightBox.MouseMove += 
         new MouseEventHandler(bottomRightBox_MouseMove);

    if (showResizeBoxes)
        ShowResizeBoxes();
}

接下来是控制器主要方法的代码,第二个方法你会看到是空的。就像我说的,我从未完成这个类,只完成了主要部分。

public void ShowResizeBoxes()
{
    PositionTopLeftBox();
    PositionTopBox();
    PositionTopRightBox();
    PositionLeftBox();
    PositionRightBox();
    PositionBottomLeftBox();
    PositionBottomBox();
    PositionBottomRightBox();
    Target.Parent.Controls.Add(topBox);
    Target.Parent.Controls.Add(bottomBox);
    Target.Parent.Controls.Add(leftBox);
    Target.Parent.Controls.Add(rightBox);
    Target.Parent.Controls.Add(topLeftBox);
    Target.Parent.Controls.Add(topRightBox);
    Target.Parent.Controls.Add(bottomLeftBox);
    Target.Parent.Controls.Add(bottomRightBox);
}

public void HideResizeBoxes()
{

}

正如你所见,ShowResizeBoxes() 开始时会调用所有调整大小框的位置命令,然后将控件添加到目标控件的父控件中。它们基本上都是一样的,所以我只发布其中一个的代码。

private void PositionTopLeftBox()
{
    topLeftBox.Top = Target.Top - topLeftBox.Height - 1;
    topLeftBox.Left = Target.Left - topLeftBox.Width - 1;
}

正如你在上面看到的,所有 ResizeBox 控件的 MouseDown 事件都映射到同一个方法。这个方法只是设置鼠标位置点以跟踪移动。

private Point mouseLocation;

private void Boxes_MouseDown(object sender, MouseEventArgs e)
{
    mouseLocation.X = e.X;
    mouseLocation.Y = e.Y;
}

现在是类的核心部分,即实际调整目标控件大小的方法。让我们以顶部框为例

首先,也是最重要的,我们需要确保是左键被点击了,所以我们使用一个简单的 if 块。接下来,我设置三个变量

if (e.Button == MouseButtons.Left)
{
    Int32 newBoxTop = topBox.Top + (e.Y - mouseLocation.Y);
    Int32 oldTargetTop = Target.Top;
    Int32 newTargetHeight = Target.Height + 
         (Target.Top - (topBox.Top + topBox.Height + 1));

第一个变量 newBoxTop 将用于检查控件的大小是会增加还是减小。第二个变量 oldTargetTop 只是保存当前顶部值,以便稍后当我们更改目标控件的顶部值时,我们会知道应该增加/减少高度值多少。最后,newTargetHeight 是目标控件调整大小后的高度值。我在这里设置它,以便我可以检查它的值以防止目标控件低于某个特定大小。最小高度和宽度值,我本来想放在一个属性里,但我很懒,就硬编码了。这是确保我们不低于最小尺寸的 if 块,以及设置新值并重新定位受影响的调整大小框的代码。

if (newTargetHeight > 15 || newBoxTop <= topBox.Top)
{
    Target.Top = newBoxTop + topBox.Height + 1;
    Target.Height += (oldTargetTop - Target.Top);
    topBox.Top = newBoxTop;
    PositionTopLeftBox();
    PositionTopRightBox();
    PositionLeftBox();
    PositionRightBox();
}
Target.Parent.Invalidate(new Rectangle(Target.Left - 6, 
       Target.Top - 6, Target.Width + 12, Target.Height + 12));

这是整个方法的代码

private void topBox_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        Int32 newBoxTop = topBox.Top + (e.Y - mouseLocation.Y);
        Int32 oldTargetTop = Target.Top;
        Int32 newTargetHeight = Target.Height + 
              (Target.Top - (topBox.Top + topBox.Height + 1));
        
        if (newTargetHeight > 15 || newBoxTop <= topBox.Top)
        {
            Target.Top = newBoxTop + topBox.Height + 1;
            Target.Height += (oldTargetTop - Target.Top);
            topBox.Top = newBoxTop;
            PositionTopLeftBox();
            PositionTopRightBox();
            PositionLeftBox();
            PositionRightBox();
        }
        Target.Parent.Invalidate(new Rectangle(Target.Left - 6, 
               Target.Top - 6, Target.Width + 12, Target.Height + 12));
    }
}

我之前没有解释的那个调用是 Target.Parent.Invalidate(...) 调用。你看,我正在捕获目标父控件的 Paint 事件,以便使用一些简单的 GDI+ 来绘制连接 ResizeBox 控件的虚线。

public void Parent_Paint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;
    Pen pen = new Pen(Brushes.Black, 1);
    pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
    g.DrawRectangle(pen, new Rectangle(Target.Left - 3, 
          Target.Top - 3, Target.Width + 6, Target.Height + 6));
}

这基本上就概括了整个类!基本上,用户控件处理光标,鼠标移动事件处理目标控件的实际大小调整和调整大小框的重新定位。然后,使包含目标控件的区域无效会强制更新虚线。

使用该类

这里没什么复杂的,只需创建该类的一个实例,并将您想要可调整大小的控件传递给构造函数。将 ShowResizeBoxes 设置为立即显示它们,或者只需手动调用它。另外,由于该类实现了 IDisposableusing 块会很有用,因为 Dispose 方法会调用 HideResizeBoxes 方法。

new ResizeControl(this.button1, true);

ResizeControl rc = new ResizeControl(this.button1, false);
rc.ShowResizeBoxes();

using (new ResizeControl(this.button1, true))
{
    //Do whatever you want here
}

问题

太多框了!

当一个控件不允许设置高度或宽度属性时,该类工作不佳。一个很好的例子是单行文本框。将它作为目标控件传递,然后向下拖动底部的调整大小框。您就会明白我的意思了!

快速移动 = 不可预测!

MouseMove/MouseDown 事件的触发频率不够高,无法跟踪快速移动。因此,最小高度/宽度测试在快速移动时可能会被忽略,导致控件变得非常小,在某些情况下可能无法恢复。此外,快速“放大”控件可能会导致事件丢失,从而破坏 GDI+ 矩形,还可能留下孤立或错位的调整大小框。似乎框在移动,但目标控件从未调整大小,其他调整大小框也没有重新定位。

完整代码

我知道很多人不想下载代码文件,为了方便快速查看,我决定包含这个

using System;
using System.Drawing;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

class ResizeControl : IDisposable
{
    #region "Private Controls"

    private ResizeBox topBox;
    private ResizeBox bottomBox;
    private ResizeBox leftBox;
    private ResizeBox rightBox;
    private ResizeBox topLeftBox;
    private ResizeBox topRightBox;
    private ResizeBox bottomLeftBox;
    private ResizeBox bottomRightBox;

    private class ResizeBox : UserControl
    {
        public enum BoxPosition
        {
            Top,
            Bottom,
            Left,
            Right,
            TopLeft,
            TopRight,
            BottomLeft,
            BottomRight
        }

        public ResizeBox(BoxPosition position)
        {
            InitializeComponent();
            this.Position = position;
        }

        private System.ComponentModel.IContainer components = null;

        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void InitializeComponent()
        {
            this.SuspendLayout();
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.BackColor = System.Drawing.Color.White;
            this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.Name = "ResizeBox";
            this.Size = new System.Drawing.Size(6, 6);
            this.MouseEnter += 
                 new System.EventHandler(this.ResizeBox_MouseEnter);
            this.MouseLeave += 
                 new System.EventHandler(this.ResizeBox_MouseLeave);
            this.ResumeLayout(false);
        }

        private BoxPosition _Position = BoxPosition.Top;
        public BoxPosition Position
        {
            get
            {
                return _Position;
            }
            set
            {
                _Position = value;
            }
        }

        private void ResizeBox_MouseEnter(object sender, EventArgs e)
        {
            switch (this.Position)
            {
                case BoxPosition.Top:
                    this.Cursor = Cursors.SizeNS;
                    break;
                case BoxPosition.Bottom:
                    this.Cursor = Cursors.SizeNS;
                    break;
                case BoxPosition.Left:
                    this.Cursor = Cursors.SizeWE;
                    break;
                case BoxPosition.Right:
                    this.Cursor = Cursors.SizeWE;
                    break;
                case BoxPosition.TopLeft:
                    this.Cursor = Cursors.SizeNWSE;
                    break;
                case BoxPosition.BottomRight:
                    this.Cursor = Cursors.SizeNWSE;
                    break;
                case BoxPosition.TopRight:
                    this.Cursor = Cursors.SizeNESW;
                    break;
                case BoxPosition.BottomLeft:
                    this.Cursor = Cursors.SizeNESW;
                    break;
                default:
                    this.Cursor = Cursors.No;
                    break;
            }
        }

        private void ResizeBox_MouseLeave(object sender, EventArgs e)
        {
            this.Cursor = Cursors.Default;
        }
    }

    #endregion

    #region "Public Methods"

    public ResizeControl(Control target, Boolean showResizeBoxes)
    {
        this._Target = target;

        target.Parent.Paint += new PaintEventHandler(Parent_Paint);

        topBox = new ResizeBox(ResizeBox.BoxPosition.Top);
        bottomBox = new ResizeBox(ResizeBox.BoxPosition.Bottom);
        leftBox = new ResizeBox(ResizeBox.BoxPosition.Left);
        rightBox = new ResizeBox(ResizeBox.BoxPosition.Right);
        topLeftBox = new ResizeBox(ResizeBox.BoxPosition.TopLeft);
        topRightBox = new ResizeBox(ResizeBox.BoxPosition.TopRight);
        bottomLeftBox = new ResizeBox(ResizeBox.BoxPosition.BottomLeft);
        bottomRightBox = new ResizeBox(ResizeBox.BoxPosition.BottomRight);

        this.topLeftBox.MouseDown += new MouseEventHandler(Boxes_MouseDown);
        this.topBox.MouseDown += new MouseEventHandler(Boxes_MouseDown);
        this.topRightBox.MouseDown += new MouseEventHandler(Boxes_MouseDown);
        this.leftBox.MouseDown += new MouseEventHandler(Boxes_MouseDown);
        this.rightBox.MouseDown += new MouseEventHandler(Boxes_MouseDown);
        this.bottomLeftBox.MouseDown += 
             new MouseEventHandler(Boxes_MouseDown);
        this.bottomBox.MouseDown += new MouseEventHandler(Boxes_MouseDown);
        this.bottomRightBox.MouseDown += 
             new MouseEventHandler(Boxes_MouseDown);

        this.topLeftBox.MouseMove += 
             new MouseEventHandler(topLeftBox_MouseMove);
        this.topBox.MouseMove += new MouseEventHandler(topBox_MouseMove);
        this.topRightBox.MouseMove += 
             new MouseEventHandler(topRightBox_MouseMove);
        this.leftBox.MouseMove += new MouseEventHandler(leftBox_MouseMove);
        this.rightBox.MouseMove += new MouseEventHandler(rightBox_MouseMove);
        this.bottomLeftBox.MouseMove += 
             new MouseEventHandler(bottomLeftBox_MouseMove);
        this.bottomBox.MouseMove += 
             new MouseEventHandler(bottomBox_MouseMove);
        this.bottomRightBox.MouseMove += 
             new MouseEventHandler(bottomRightBox_MouseMove);

        if (showResizeBoxes)
            ShowResizeBoxes();
    }

    public void Parent_Paint(object sender, PaintEventArgs e)
    {
        Graphics g = e.Graphics;
        Pen pen = new Pen(Brushes.Black, 1);
        pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
        g.DrawRectangle(pen, new Rectangle(Target.Left - 3, 
              Target.Top - 3, Target.Width + 6, Target.Height + 6));
    }

    public void ShowResizeBoxes()
    {
        PositionTopLeftBox();
        PositionTopBox();
        PositionTopRightBox();
        PositionLeftBox();
        PositionRightBox();
        PositionBottomLeftBox();
        PositionBottomBox();
        PositionBottomRightBox();
        Target.Parent.Controls.Add(topBox);
        Target.Parent.Controls.Add(bottomBox);
        Target.Parent.Controls.Add(leftBox);
        Target.Parent.Controls.Add(rightBox);
        Target.Parent.Controls.Add(topLeftBox);
        Target.Parent.Controls.Add(topRightBox);
        Target.Parent.Controls.Add(bottomLeftBox);
        Target.Parent.Controls.Add(bottomRightBox);
    }

    public void HideResizeBoxes()
    {
        topBox.Visible = false;
    }

    void IDisposable.Dispose()
    {
        HideResizeBoxes();
    }

    #endregion

    #region "Move Event Handlers"

    private Point mouseLocation;

    private void Boxes_MouseDown(object sender, MouseEventArgs e)
    {
        mouseLocation.X = e.X;
        mouseLocation.Y = e.Y;
    }

    private void topLeftBox_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            Int32 newBoxTop = topLeftBox.Top + (e.Y - mouseLocation.Y);
            Int32 oldTargetTop = Target.Top;
            Int32 newTargetHeight = Target.Height + 
                 (Target.Top - (topLeftBox.Top + topLeftBox.Height + 1));
            Int32 newBoxLeft = topLeftBox.Left + (e.X - mouseLocation.X);
            Int32 oldTargetLeft = Target.Left;
            Int32 newTargetWidth = Target.Width + (oldTargetLeft - Target.Left);

            if (newTargetWidth > 30 || newBoxLeft <= topLeftBox.Left)
            {
                Target.Left = newBoxLeft + topLeftBox.Width + 1;
                Target.Width += (oldTargetLeft - Target.Left);
                topLeftBox.Left = newBoxLeft;
                PositionTopLeftBox();
                PositionBottomLeftBox();
                PositionTopBox();
                PositionBottomBox();
                PositionLeftBox();
            }
            if (newTargetHeight > 15 || newBoxTop <= topBox.Top)
            {
                Target.Top = newBoxTop + topLeftBox.Height + 1;
                Target.Height += (oldTargetTop - Target.Top);
                topLeftBox.Top = newBoxTop;
                PositionTopLeftBox();
                PositionTopRightBox();
                PositionLeftBox();
                PositionRightBox();
                PositionTopBox();
            }
            Target.Parent.Invalidate(new Rectangle(Target.Left - 6, 
                   Target.Top - 6, Target.Width + 12, Target.Height + 12));
        }
    }

    private void topBox_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            Int32 newBoxTop = topBox.Top + (e.Y - mouseLocation.Y);
            Int32 oldTargetTop = Target.Top;
            Int32 newTargetHeight = Target.Height + 
                 (Target.Top - (topBox.Top + topBox.Height + 1));
            
            if (newTargetHeight > 15 || newBoxTop <= topBox.Top)
            {
                Target.Top = newBoxTop + topBox.Height + 1;
                Target.Height += (oldTargetTop - Target.Top);
                topBox.Top = newBoxTop;
                PositionTopLeftBox();
                PositionTopRightBox();
                PositionLeftBox();
                PositionRightBox();
            }
            Target.Parent.Invalidate(new Rectangle(Target.Left - 6, 
                   Target.Top - 6, Target.Width + 12, Target.Height + 12));
        }
    }

    private void topRightBox_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            Int32 newBoxTop = topRightBox.Top + (e.Y - mouseLocation.Y);
            Int32 oldTargetTop = Target.Top;
            Int32 newTargetHeight = Target.Height + 
                  (Target.Top - (topRightBox.Top + topRightBox.Height + 1));
            Int32 newBoxLeft = topRightBox.Left + (e.X - mouseLocation.X);
            Int32 newTargetWidth = topRightBox.Left - Target.Left - 1;

            if (newTargetWidth > 30 || newBoxLeft >= topRightBox.Left)
            {
                Target.Width = newTargetWidth;
                topRightBox.Left = newBoxLeft;
                PositionBottomRightBox();
                PositionTopBox();
                PositionBottomBox();
            }
            if (newTargetHeight > 15 || newBoxTop <= topRightBox.Top)
            {
                Target.Top = newBoxTop + topRightBox.Height + 1;
                Target.Height += (oldTargetTop - Target.Top);
                topRightBox.Top = newBoxTop;
                PositionTopLeftBox();
                PositionLeftBox();
                PositionRightBox();
            }
            Target.Parent.Invalidate(new Rectangle(Target.Left - 6, 
                   Target.Top - 6, Target.Width + 12, Target.Height + 12));
        }
    }

    private void leftBox_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            Int32 newBoxLeft = leftBox.Left + (e.X - mouseLocation.X);
            Int32 oldTargetLeft = Target.Left;
            Int32 newTargetWidth = Target.Width + (oldTargetLeft - Target.Left);

            if (newTargetWidth > 30 || newBoxLeft <= leftBox.Left)
            {
                Target.Left = newBoxLeft + leftBox.Width + 1;
                Target.Width += (oldTargetLeft - Target.Left);
                leftBox.Left = newBoxLeft;
                PositionTopLeftBox();
                PositionBottomLeftBox();
                PositionTopBox();
                PositionBottomBox();
            }
            Target.Parent.Invalidate(new Rectangle(Target.Left - 6, 
                   Target.Top - 6, Target.Width + 12, Target.Height + 12));
        }
    }

    private void rightBox_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            Int32 newBoxLeft = rightBox.Left + (e.X - mouseLocation.X);
            Int32 newTargetWidth = rightBox.Left - Target.Left - 1;

            if (newTargetWidth > 30 || newBoxLeft >= rightBox.Left)
            {
                Target.Width = newTargetWidth;
                rightBox.Left = newBoxLeft;
                PositionTopRightBox();
                PositionBottomRightBox();
                PositionTopBox();
                PositionBottomBox();
            }
            Target.Parent.Invalidate(new Rectangle(Target.Left - 6, 
                   Target.Top - 6, Target.Width + 12, Target.Height + 12));
        }
    }

    private void bottomLeftBox_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            Int32 newBoxTop = bottomLeftBox.Top + (e.Y - mouseLocation.Y);
            Int32 newTargetHeight = bottomLeftBox.Top - Target.Top - 1;
            Int32 newBoxLeft = bottomLeftBox.Left + (e.X - mouseLocation.X);
            Int32 oldTargetLeft = Target.Left;
            Int32 newTargetWidth = Target.Width + (oldTargetLeft - Target.Left);

            if (newTargetWidth > 30 || newBoxLeft <= bottomLeftBox.Left)
            {
                Target.Left = newBoxLeft + bottomLeftBox.Width + 1;
                Target.Width += (oldTargetLeft - Target.Left);
                bottomLeftBox.Left = newBoxLeft;
                PositionTopLeftBox();
                PositionTopBox();
                PositionBottomBox();
            }
            if (newTargetHeight > 15 || newBoxTop >= bottomLeftBox.Top)
            {
                Target.Height = newTargetHeight;
                bottomLeftBox.Top = newBoxTop;
                PositionBottomRightBox();
                PositionLeftBox();
                PositionRightBox();
            }
            Target.Parent.Invalidate(new Rectangle(Target.Left - 6, 
                   Target.Top - 6, Target.Width + 12, Target.Height + 12));
        }
    }

    private void bottomBox_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            Int32 newBoxTop = bottomBox.Top + (e.Y - mouseLocation.Y);
            Int32 newTargetHeight = bottomBox.Top - Target.Top - 1;

            if (newTargetHeight > 15 || newBoxTop >= bottomBox.Top)
            {
                Target.Height = newTargetHeight;
                bottomBox.Top = newBoxTop;
                PositionBottomLeftBox();
                PositionBottomRightBox();
                PositionLeftBox();
                PositionRightBox();
            }
            Target.Parent.Invalidate(new Rectangle(Target.Left - 6, 
                   Target.Top - 6, Target.Width + 12, Target.Height + 12));
        }
    }

    private void bottomRightBox_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            Int32 newBoxTop = bottomRightBox.Top + (e.Y - mouseLocation.Y);
            Int32 newTargetHeight = bottomRightBox.Top - Target.Top - 1;
            Int32 newBoxLeft = bottomRightBox.Left + (e.X - mouseLocation.X);
            Int32 newTargetWidth = bottomRightBox.Left - Target.Left - 1;

            if (newTargetWidth > 30 || newBoxLeft >= bottomRightBox.Left)
            {
                Target.Width = newTargetWidth;
                bottomRightBox.Left = newBoxLeft;
                PositionTopRightBox();
                PositionTopBox();
                PositionBottomBox();
            }
            if (newTargetHeight > 15 || newBoxTop >= bottomRightBox.Top)
            {
                Target.Height = newTargetHeight;
                bottomRightBox.Top = newBoxTop;
                PositionBottomLeftBox();
                PositionLeftBox();
                PositionRightBox();
            }
            Target.Parent.Invalidate(new Rectangle(Target.Left - 6, 
                   Target.Top - 6, Target.Width + 12, Target.Height + 12));
        }
    }

    #endregion

    #region "Positioning Commands"

    private void PositionTopLeftBox()
    {
        topLeftBox.Top = Target.Top - topLeftBox.Height - 1;
        topLeftBox.Left = Target.Left - topLeftBox.Width - 1;
    }

    private void PositionTopBox()
    {
        topBox.Top = Target.Top - topBox.Height - 1;
        topBox.Left = Target.Left + (Target.Width / 2) - (topBox.Width / 2);
    }

    private void PositionTopRightBox()
    {
        topRightBox.Top = Target.Top - topRightBox.Height - 1;
        topRightBox.Left = Target.Left + Target.Width + 1;
    }

    private void PositionLeftBox()
    {
        leftBox.Top = Target.Top + (Target.Height / 2) - (leftBox.Height / 2);
        leftBox.Left = Target.Left - leftBox.Width - 1;
    }

    private void PositionRightBox()
    {
        rightBox.Top = Target.Top + (Target.Height / 2) - (rightBox.Height / 2);
        rightBox.Left = Target.Left + Target.Width + 1;
    }

    private void PositionBottomLeftBox()
    {
        bottomLeftBox.Top = Target.Top + Target.Height + 1;
        bottomLeftBox.Left = Target.Left - leftBox.Width - 1;
    }

    private void PositionBottomBox()
    {
        bottomBox.Top = Target.Top + Target.Height + 1;
        bottomBox.Left = Target.Left + 
                 (Target.Width / 2) - (bottomBox.Width / 2);
    }

    private void PositionBottomRightBox()
    {
        bottomRightBox.Top = Target.Top + Target.Height + 1;
        bottomRightBox.Left = Target.Left + Target.Width + 1;
    }

    #endregion

    #region "Properties"

    private Control _Target;
    public Control Target
    {
        get
        {
            if (_Target == null)
                _Target = new Control();
            return _Target;
        }
    }

    #endregion
}

历史

  • 2007/1/19 - 首次发布。
© . All rights reserved.