Introduction
An unfinished, simple class I started to write in response to a recent post on the microsoft.public.dotnet.languages.vb newsgroup.
Background
Not too long ago, I was browsing the VB.NET newsgroup like I normally do, and ran across a question that stumped me. The question was on how to provide the ability to resize a control during runtime. It seemed fairly straightforward, so I fired up C# (forgetting which newsgroup I read the question in!) and started typing up a quick solution - and it failed.
So I spent more and more time tweaking this late at night, and got most things worked out. Eventually, the OP stated he found a solution and wrote a CodeProject article about it. "Ah hah," I said, "I'll do the same!". And so I quit working on the code, and figured this would at least get someone else started. (Maybe, I'll finish it later - who knows?)
The Principle Components
The User Control
Nothing too complex here. I just needed a control that would represent the little white boxes that "float" around the outside of the control to be resized. The main job of the control is to just change the mouse cursor based on the position of the control (top left, top, etc.).
The Controller Class
Here, things get a little more verbose, but still not too complex. In a few sentences, the controller class first creates the necessary resize boxes (the user controls) and places them around the target control. The rest of the class simply handles the mouse-move events, and resizes the target control based on the movement of the specific resize box.
The Resize Box's Code
First off, I created an enum that listed all the available positions (relative to the target) that the resize box could have. Then, of course, I used this enum as a parameter in the control's constructor.
public enum BoxPosition
{
Top,
Bottom,
Left,
Right,
TopLeft,
TopRight,
BottomLeft,
BottomRight
}
public ResizeBox(BoxPosition position)
{
InitializeComponent();
this.Position = position;
}
OK, nothing complex there. Next up, I handled both the MouseEnter
and MouseLeave
events of the control in order to set the appropriate arrow cursor depending on the Position
property (not shown) of the control. Sounds like a job for a switch
statement to me!
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;
}
That pretty much takes care of the juicy bits for the user control - like I said, it's pretty simple.
The Controller Class
First of all, I need to create some variables to represent the actual resize boxes I'll place around the target.
private ResizeBox topBox;
private ResizeBox bottomBox;
private ResizeBox leftBox;
private ResizeBox rightBox;
private ResizeBox topLeftBox;
private ResizeBox topRightBox;
private ResizeBox bottomLeftBox;
private ResizeBox bottomRightBox;
In the constructor, the target control is passed as a parameter. I set this into a property, instantiate the ResizeBox
objects, and map the the necessary events to the methods that will handle them. The constructor also provides an option to immediately show the resize handles.
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();
}
Next is the code for the main methods for the controller, the second of which you'll see is empty. Like I said, I never finished the class, just the main parts.
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()
{
}
As you can see, the ShowResizeBoxes()
starts out by calling the position commands for all of the resize boxes and then adding the controls to the parent of the target control. They're basically all the same, so I'll just post the code for one.
private void PositionTopLeftBox()
{
topLeftBox.Top = Target.Top - topLeftBox.Height - 1;
topLeftBox.Left = Target.Left - topLeftBox.Width - 1;
}
As you saw above, the MouseDown
events for all of the ResizeBox
es is mapped to the same method. This method just sets the mouse location point for tracking movement.
private Point mouseLocation;
private void Boxes_MouseDown(object sender, MouseEventArgs e)
{
mouseLocation.X = e.X;
mouseLocation.Y = e.Y;
}
And now for the heart of the class, the methods that actually resize the target control. Let's take the top-box as an example:
First and foremost, we need to make sure the left mouse button was the one that was clicked, so we use a simple if
block. Next, I set three variables:
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));
The first variable, newBoxTop
, will be used to check whether the size of the control will increase or decrease in size. The second, oldTargetTop
, just saves the current top value so later when we change the top value of the target, we will know how much we should increase/decrease the height value by. Finally, newTargetHeight
is the value that the height value of the target will be after we resize it. I set it here so I can check its value to prevent the target from going below a certain size. The minimum height and width values, I had wanted to put in a property, but I was lazy and just hard-coded them in. Here's, the if
block that makes sure we don't drop below the minimum size, and the code that sets the new values and re-positions the effected resize-boxes:
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));
Here's the code for the entire method:
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));
}
}
The one call I didn't explain earlier is the Target.Parent.Invalidate(...)
call. You see, I'm trapping the target's parent's Paint
event in order to use some simple GDI+ to draw the dotted line connecting the ResizeBox
es.
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));
}
And that pretty much sums up the class! Basically, the user control handles the cursors, and the mouse-move events handle the actual resizing of the target control and re-positioning the resize boxes. Then, invalidating the region containing the target control forces the updating of the dotted line.
Using the Class
Nothing complex here, just create an instance of the class and pass the control you want to be resizable to the constructor. Setting the ShowResizeBoxes
to show them immediately, or just calling it manually. Also, since the class implements IDisposable
, using
blocks could come in handy since the Dispose
methods calls the HideResizeBoxes
method.
new ResizeControl(this.button1, true);
ResizeControl rc = new ResizeControl(this.button1, false);
rc.ShowResizeBoxes();
using (new ResizeControl(this.button1, true))
{
}
The Problems
Too many boxes!
The class doesn't work well when a control doesn't allow either the height or width property to be set. A good example of this is a single line textbox. Pass that as the target and then drag the bottom resize box down. You'll see what I mean!
Speedy Moves = Unpredictable!
The MouseMove
/MouseDown
events don't fire near often enough to track fast movements. As a result, the minimum height/width tests can be ignored on fast moves, causing super small controls that may not be recoverable in some cases. Also, quickly "growing" the control can cause missed events that mess up the GDI+ rectangle, and can also leave orphaned or misplaced resize boxes. It seems the boxes move, but the target never resizes and the other resize boxes don't reposition.
The Complete Code
Since I know a lot of people don't want to download a code file, for a quick look-see, I figured I'd include this:
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
}
History
- 1/19/2007 - First release.