using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using System.Drawing.Drawing2D;
namespace DariusArnold
{
public partial class MoveControl : Button
{
/// <summary>
/// Neue Instanz des bewegbaren Benutzersteuerelements.
/// </summary>
public MoveControl()
{
CanMove = true;
CanResize = true;
SnapsToGrid = true;
SizesToGrid = true;
ChangeCursor = true;
Grid = GridMode.ShowWhileMoving;
ViewGrid = GridViewingTypes.Draw;
CustomGridPixel = new bool[]{ false,
false,
false,
true,
true,
true,
true,
true,
false,
false };
GridColor = SystemColors.ControlDarkDark;
GridLineWidth = 2f;
GridDashStyle = DashStyle.Dot;
ResizeCornerSize = new Size(5, 5);
MinimumSize = new Size(20, 20);
AutoSize = false;
MarkResizeCorner = true;
ShowValueBoxes = true;
ResizeCornerMarkingColor = Color.Blue;
DoubleBuffered = true;
this.MouseDown += new MouseEventHandler(c_MouseDown);
this.MouseUp += new MouseEventHandler(c_MouseUp);
this.MouseMove += new MouseEventHandler(c_MouseMove);
this.Paint += new PaintEventHandler(c_Paint);
}
private int x, y;
private bool move, resize;
private Rectangle oControl = new Rectangle();
private Form form = null;
private GridMode gm = GridMode.ShowNever;
/// <summary>
/// Sets, if control can be moved during runtime.
/// </summary>
[CategoryAttribute("MoveAndResize"), DescriptionAttribute("Gibt an, ob das Element zur Laufzeit verschoben werden kann."), DefaultValue(true)]
public bool CanMove { get; set; }
/// <summary>
/// Sets, if control can be resized during runtime.
/// </summary>
[CategoryAttribute("MoveAndResize"), DescriptionAttribute("Gibt an, ob die Größe des Elements zur Laufzeit verändert werden kann."), DefaultValue(true)]
public bool CanResize { get; set; }
/// <summary>
/// Sets, if the control snaps to a 10x10 px grid automaticly.
/// </summary>
[CategoryAttribute("Grid"), DescriptionAttribute("Gibt an, ob sich das Element automatisch an einem 10x10-Raster ausrichten soll."), DefaultValue(true)]
public bool SnapsToGrid { get; set; }
/// <summary>
/// Sets, if the control's size is adapted to a 10x10 px grid automaticly.
/// </summary>
[CategoryAttribute("Grid"), DescriptionAttribute("Gibt an, ob die Größße des Elements automatisch an ein 10x10-Raster angepasst werden soll."), DefaultValue(true)]
public bool SizesToGrid { get; set; }
/// <summary>
/// Sets whether the cursor is changed if user moves the control or is able to resize it.
/// </summary>
[CategoryAttribute("Darstellung"), DescriptionAttribute("Gibt an, ob sich der Cursor ändern soll, wenn das Element verschoben wird oder seine Größe verändert werden kann."), DefaultValue(true)]
public bool ChangeCursor { get; set; }
/// <summary>
/// Sets, if the area to drag for resize the control is colored.
/// </summary>
[CategoryAttribute("Darstellung"), DescriptionAttribute("Gibt an, ob der \"Angriffspunkt\" zur Größenänderung farbig hinterlegt werden soll."), DefaultValue(true)]
public bool MarkResizeCorner { get; set; }
/// <summary>
/// Sets the color of the 10x10 px grid.
/// </summary>
[CategoryAttribute("Grid"), DescriptionAttribute("Gibt an, in welcher Farbe das Raster gezeichnet werden soll. (Wenn Grid auf ShowAlways oder ShowWhileMoving steht)")]
public Color GridColor { get; set; }
/// <summary>
/// Sets the dash style of the 10x10 px grid.
/// </summary>
[CategoryAttribute("Grid"), DescriptionAttribute("Gibt an, in welcher Punktierungsweise das Raster gezeichnet werden soll. (Wenn Grid auf ShowAlways oder ShowWhileMoving steht)")]
public DashStyle GridDashStyle { get; set; }
/// <summary>
/// Sets the width of the grid lines.
/// </summary>
[CategoryAttribute("Grid"), DescriptionAttribute("Breite der Linien des Grid")]
public float GridLineWidth { get; set; }
/// <summary>
/// Sets the size of the resize area.
/// </summary>
[CategoryAttribute("Darstellung"), DescriptionAttribute("Gibt die Größe des \"Angriffspunktes\" zur Größenänderung an.")]
public Size ResizeCornerSize { get; set; }
/// <summary>
/// Sets the color of the resize area (if MarkResizeCorner is true).
/// </summary>
[CategoryAttribute("Darstellung"), DescriptionAttribute("Gibt die Farbe der Markierung des\"Angriffspunktes\" zur Größenänderung an. (Wenn MarkResizeCorner auf true steht)")]
public Color ResizeCornerMarkingColor { get; set; }
/// <summary>
/// Sets, if there are shown little boxes containing size or location while move or resize process.
/// </summary>
[CategoryAttribute("Darstellung"), DescriptionAttribute("Gibt an, ob beim Ändern der Größe oder der Position kleine Kästchen mit den entsprechenden Werten angezeigt werden."), DefaultValue(true)]
public bool ShowValueBoxes { get; set; }
/// <summary>
/// Sets a custom dash style for the grid (only if ShowGrid is Show). It has to contain at least 10 values (if there are more, they won't be used). true says the pixel is colored. false says it isn't.
/// </summary>
[CategoryAttribute("Grid"), DescriptionAttribute("Gibt das Linien-Museter für das Raster der BGImage-Property an. Ein Wert entspricht einem Pixel. true = Linie; false = Lücke")]
public bool[] CustomGridPixel { get; set; }
public enum GridViewingTypes { Draw, Show }
/// <summary>
/// Sets the type of viewing the grid. Type 1 (Draw) is drawing it on the form. Type 2 (Show) is showing it as the form's background image.
/// </summary>
[CategoryAttribute("Grid"), DescriptionAttribute("Gibt an, ob das Raster gezeichnet oder über die Background-Image-Property dargestellt werden soll. Bei letzterem wird die Verwendung eines BackgroundImages unmöglich.")]
public GridViewingTypes ViewGrid { get; set; }
public enum GridMode { ShowAlways, ShowNever, ShowWhileMoving }
/// <summary>
/// Sets, when the grid is shown.
/// </summary>
[CategoryAttribute("Grid"), DescriptionAttribute("Gibt an, ob das Raster nie, immer oder nur beim Verschieben oder Ändern der Größe angezeigt wird."), DefaultValue(GridMode.ShowNever)]
public GridMode Grid
{
get
{
return gm;
}
set
{
gm = value;
try { form.Refresh(); } catch { }
}
}
/// <summary>
/// Enable grid functionality for control. Also make the size value box appear next to the cursor instead of above the control.
/// </summary>
/// <param name="f">The form the things (grid and value size value box) should be shown on.</param>
public void EnableGrid(Form f)
{
form = f;
if (ViewGrid == GridViewingTypes.Show)
f.BackgroundImage = null;
f.Paint += new PaintEventHandler(form_Paint);
SetDoubleBuffered(f);
if (SnapsToGrid)
SnapToGrid();
if (SizesToGrid)
SizeToGrid();
try
{
form.Refresh();
}
catch
{
}
}
/// <summary>
/// Snap the control to the 10x10 px grid.
/// </summary>
public void SnapToGrid()
{
this.Left = (int)Math.Round((decimal)this.Left / 10, 0) * 10;
this.Top = (int)Math.Round((decimal)this.Top / 10, 0) * 10;
}
/// <summary>
/// Adapt the control's size to the 10x10 px grid.
/// </summary>
public void SizeToGrid()
{
this.Width = ((int)Math.Round((decimal)this.Width / 10, 0) * 10) + (((int)Math.Round((decimal)this.Left / 10, 0) * 10) - this.Left);
this.Height = ((int)Math.Round((decimal)this.Height / 10, 0) * 10) + (((int)Math.Round((decimal)this.Top / 10, 0) * 10) - this.Top);
}
public new event EventHandler Click;
protected virtual void OnMCClick(EventArgs e)
{
EventHandler eh = Click;
if (eh != null)
{
eh(this, e);
}
}
private void form_Paint(object sender, PaintEventArgs e)
{
switch (Grid)
{
case GridMode.ShowAlways:
ShowGrid(e);
break;
case GridMode.ShowWhileMoving:
if (move | resize)
ShowGrid(e);
else
HideGrid();
break;
case GridMode.ShowNever:
HideGrid();
break;
}
if (resize & ShowValueBoxes)
{
Point mouse = PointToClient(MousePosition);
Point draw = mouse;
draw.Offset(this.Location);
draw.Offset(10, 10);
DrawStringBox("X: " + (Math.Round((decimal)mouse.X / 10, 0) * 10).ToString() + "; Y: " + (Math.Round((decimal)mouse.Y / 10, 0) * 10).ToString(), Font, Color.Black, Color.White, SystemColors.ControlDarkDark, 1, 10, draw, e.Graphics);
}
}
private void c_MouseMove(object sender, MouseEventArgs e)
{
if (move)
{
if (Grid != GridMode.ShowAlways)
try { form.Refresh(); } catch { }
Point p = new Point();
p.X = e.X + this.Left;
p.Y = e.Y + this.Top;
this.Left = p.X - x;
this.Top = p.Y - y;
Point mouse = this.Location;
mouse.Offset(e.Location);
}
else if (resize)
{
SetBottomRightPt(this, new Point(this.Left + e.X, this.Top + e.Y));
if (Grid != GridMode.ShowAlways)
try { form.Refresh(); } catch { }
}
else
{
if (((e.X > (this.Width - ResizeCornerSize.Width)) & (e.Y > (this.Height - ResizeCornerSize.Height))) & CanResize & ChangeCursor)
this.Cursor = Cursors.SizeNWSE;
else
this.Cursor = Cursors.Default;
}
}
private void c_MouseUp(object sender, MouseEventArgs e)
{
move = false;
resize = false;
if (SnapsToGrid)
SnapToGrid();
if (SizesToGrid)
SizeToGrid();
if (this.Bounds == oControl)
{
OnMCClick(EventArgs.Empty);
}
this.Cursor = Cursors.Default;
if (Grid != GridMode.ShowAlways)
try { form.Refresh(); } catch { }
}
private void c_MouseDown(object sender, MouseEventArgs e)
{
this.BringToFront();
oControl = this.Bounds;
if (((e.X > (this.Width - ResizeCornerSize.Width)) & (e.Y > (this.Height - ResizeCornerSize.Height))) & CanResize)
{
resize = true;
}
else if (CanMove)
{
if (ChangeCursor)
this.Cursor = Cursors.SizeAll;
x = e.X;
y = e.Y;
move = true;
}
}
private void SetBottomRightPt(Control c, Point p)
{
c.Width = (p.X - c.Left);
c.Height = (p.Y - c.Top);
}
private void c_Paint(object sender, PaintEventArgs e)
{
if (MarkResizeCorner & CanResize)
e.Graphics.FillRectangle(new SolidBrush(ResizeCornerMarkingColor), new Rectangle(new Point(Width - ResizeCornerSize.Width, Height - ResizeCornerSize.Height), ResizeCornerSize));
if (resize & form == null & ShowValueBoxes)
DrawStringBox("X: " + (Math.Round((decimal)Width / 10, 0) * 10).ToString() + "; Y: " + (Math.Round((decimal)Height / 10, 0) * 10).ToString(), Font, Color.Black, Color.White, SystemColors.ControlDarkDark, 1, 10, new Point(5, 5), e.Graphics);
else if (move & ShowValueBoxes)
DrawStringBox("X: " + (Math.Round((decimal)Left / 10, 0) * 10).ToString() + "; Y: " + (Math.Round((decimal)Right / 10, 0) * 10).ToString(), Font, Color.Black, Color.White, SystemColors.ControlDarkDark, 1, 10, new Point(5, 5), e.Graphics);
}
/// <summary>
/// Show the grid. If ViewGrid is on 'Draw' it, will disapear when form is redrawn.
/// </summary>
/// <param name="e">The PaintEventArgs. Can be null, if ViewGrid is on 'Show'.</param>
public void ShowGrid(PaintEventArgs e)
{
if (ViewGrid == GridViewingTypes.Draw)
DrawGrid(form, GridColor, GridDashStyle, GridLineWidth, e);
else
ShowGrid(form, GridColor, CustomGridPixel);
}
/// <summary>
/// Hide the grid. Works only if ShowGrid is on 'Show'.
/// </summary>
public void HideGrid()
{
if (ViewGrid == GridViewingTypes.Show & Grid != GridMode.ShowAlways)
HideGrid(form);
}
private void SetDoubleBuffered(System.Windows.Forms.Control c)
{
if (System.Windows.Forms.SystemInformation.TerminalServerSession)
return;
System.Reflection.PropertyInfo aProp =
typeof(System.Windows.Forms.Control).GetProperty(
"DoubleBuffered",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
aProp.SetValue(c, true, null);
}
private void DrawStringBox(string sText, Font fText, Color cText, Color cBox, Color cBorder, int iOuterBorderWidth, int iInnerBorderWidth, Point pLocation, Graphics g)
{
Point pBorder = pLocation;
Point pBox = pLocation;
Point pText = pLocation;
pBox.Offset(iOuterBorderWidth, iOuterBorderWidth);
pText.Offset(iOuterBorderWidth + iInnerBorderWidth, iOuterBorderWidth + iInnerBorderWidth);
Size szText = TextRenderer.MeasureText(sText, fText);
Size szBox = szText;
Size szBorder = szText;
szBox.Width += (2 * iInnerBorderWidth);
szBox.Height += (2 * iInnerBorderWidth);
szBorder.Width += (2 * iInnerBorderWidth) + (2 * iOuterBorderWidth);
szBorder.Height += (2 * iInnerBorderWidth) + (2 * iOuterBorderWidth);
g.FillRectangle(new SolidBrush(cBorder), new Rectangle(pBorder, szBorder));
g.FillRectangle(new SolidBrush(cBox), new Rectangle(pBox, szBox));
g.DrawString(sText, fText, new SolidBrush(cText), pText);
}
private static void ShowGrid(Form f, Color c, bool[] Px)
{
ShowGrid(f, c, Px, false);
}
private static void ShowGrid(Form f, Color c, bool[] Px, bool invert)
{
try
{
if (f.BackgroundImage == null)
{
if (invert)
Px = Px.invert();
Bitmap b = new Bitmap(10, 10);
for (int i = 0; i < 10; i++)
{
if (Px[i])
b.SetPixel(i, 0, c);
}
for (int i = 1; i < 10; i++)
{
if (Px[i])
b.SetPixel(0, i, c);
}
f.BackgroundImageLayout = ImageLayout.Tile;
f.BackgroundImage = b;
if (invert)
Px = Px.invert();
}
}
catch
{
}
}
private static void HideGrid(Form f)
{
try
{
f.BackgroundImage = null;
}
catch
{
}
}
private static Grid g;
public static void DrawGrid(Form f, Color c, DashStyle d, float penWidth, PaintEventArgs e)
{
g = new Grid();
g.HorizontalCells = f.Height / 10 + 1;
g.VerticalCells = f.Width / 10 + 1;
Pen myPen = new Pen(c, penWidth);
myPen.DashStyle = d;
myPen.DashCap = DashCap.Triangle;
g.Draw(e.Graphics, myPen);
}
}
public static class Ext
{
public static bool[] invert(this bool[] input)
{
for (int i = 0; i < input.Length; i++)
input[i] = !input[i];
return input;
}
}
public class Grid
{
public Grid()
{
Origin = new Point(0, 0);
GridCellSize = new Size(10, 10);
HorizontalCells = 1;
VerticalCells = 1;
}
public int HorizontalCells { get; set; }
public int VerticalCells { get; set; }
public Point Origin { get; set; }
public Size GridCellSize { get; set; }
public virtual void Draw(Graphics Graf, Pen pencil)
{
Point startP = new Point();
Point endP = new Point();
// Draw horizontals
startP.X = Origin.X;
endP.X = Origin.X + VerticalCells * GridCellSize.Width;
for (int i = 0; i <= HorizontalCells; i++)
{
startP.Y = Origin.Y + i * GridCellSize.Height;
endP.Y = startP.Y;
Graf.DrawLine(pencil, startP, endP);
}
// Draw verticals
startP.Y = Origin.Y;
endP.Y = Origin.Y + HorizontalCells * GridCellSize.Height;
for (int i = 0; i <= VerticalCells; i++)
{
startP.X = Origin.X + i * GridCellSize.Width;
endP.X = startP.X;
Graf.DrawLine(pencil, startP, endP);
}
}
}
}