Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // SnapFormExtender.cs
- //
- // This class extends MDI child window behavior: it sticks to parents' client
- // area edges and to another child windows while moving or resizing.
- //
- // Author: Eugene Pankov, 2004
- using System;
- using System.Windows.Forms;
- using System.ComponentModel;
- using System.ComponentModel.Design;
- using System.Globalization;
- using System.Drawing;
- using System.Collections;
- namespace SnapFormExtenderFixed
- {
- public class SnapFormExtenderFixed : Component, IExtenderProvider, ISupportInitialize
- {
- private bool enableSnap = true;
- private int snapDistance = 4;
- private Form parentForm = null;
- private enum Orientation
- {
- Vertical,
- Horizontal
- };
- public SnapFormExtenderFixed( System.ComponentModel.IContainer container ) : this()
- {
- container.Add( this );
- }
- public SnapFormExtenderFixed()
- {
- }
- #region CanExtend
- public bool CanExtend( object component )
- {
- // only support MDI parent forms
- if( component is Form )
- {
- Form form = ( Form )component;
- return form.IsMdiContainer;
- }
- return false ;
- }
- #endregion
- [Description("Enable to align MDI child forms on moving and resizing.")]
- [Category("Misc")]
- [DefaultValue(true)]
- public bool Enabled
- {
- get{ return enableSnap; }
- set{ enableSnap = value; }
- }
- [Description("Parent MDI form which childs should be aligned.")]
- [Category("Misc")]
- [DefaultValue(null)]
- public Form Form
- {
- get{ return parentForm; }
- set{ parentForm = value; }
- }
- [Description("Distance at which the adhesion will occur.")]
- [Category("Misc")]
- [DefaultValue(4)]
- public int Distance
- {
- get{ return snapDistance; }
- set{
- if( value < 0 || value > 20 )
- throw new ArgumentOutOfRangeException("Distance", value, "Distance must be a positive number less or equal to 20.");
- snapDistance = value;
- }
- }
- #region ISupportInitialize Members
- void ISupportInitialize.BeginInit()
- {
- }
- void ISupportInitialize.EndInit()
- {
- if( !DesignMode && parentForm != null )
- {
- parentForm.MdiChildActivate +=new EventHandler(parentForm_MdiChildActivate);
- }
- }
- #endregion
- private void parentForm_MdiChildActivate(object sender, EventArgs e)
- {
- if( parentForm.ActiveMdiChild != null )
- {
- Form child = parentForm.ActiveMdiChild;
- child.Move -= new EventHandler(child_Move);
- child.Resize -= new EventHandler(child_Resize);
- if( enableSnap )
- {
- child.Move += new EventHandler(child_Move);
- child.Resize += new EventHandler(child_Resize);
- }
- }
- }
- private void child_Move(object sender, EventArgs e)
- {
- if( sender == null ) return;
- Form form = ( Form )sender;
- if( form.WindowState != FormWindowState.Normal ) return;
- Rectangle mdiClientArea = GetMdiClientArea();
- SnapOnMove( form, mdiClientArea, Orientation.Vertical );
- SnapOnMove( form, mdiClientArea, Orientation.Horizontal );
- }
- private void child_Resize(object sender, EventArgs e)
- {
- if( sender == null ) return;
- Form form = ( Form )sender;
- if( form.WindowState != FormWindowState.Normal ) return;
- Rectangle mdiClientArea = GetMdiClientArea();
- SnapOnResize( form, mdiClientArea );
- }
- private void SnapOnMove( Form form, Rectangle mdiClientArea, Orientation orientation )
- {
- int x = form.Location.X;
- int y = form.Location.Y;
- int width = form.Size.Width;
- int height = form.Size.Height;
- Edge formEdge1, formEdge2, clientEdge1, clientEdge2;
- if( orientation == Orientation.Vertical ) // Check vertical edges
- {
- formEdge1 = new Edge( x, y, y+height-1 );
- formEdge2 = new Edge( x+width-1, y, y+height-1 );
- clientEdge1 = new Edge( 0, 0, mdiClientArea.Height-1 );
- clientEdge2 = new Edge( mdiClientArea.Width-1, 0, mdiClientArea.Height-1 );
- }
- else // Check horizontal edges
- {
- formEdge1 = new Edge( y, x, x+width-1 );
- formEdge2 = new Edge( y+height-1, x, x+width-1 );
- clientEdge1 = new Edge( 0, 0, mdiClientArea.Width-1 );
- clientEdge2 = new Edge( mdiClientArea.Height-1, 0, mdiClientArea.Width-1 );
- }
- int childs = parentForm.MdiChildren.Length;
- int newPosition = 0;
- int distance = 0;
- int minDistance = snapDistance + 1;
- for( int i=0; i < childs && minDistance > 0; i++ )
- {
- Form mdiChild = parentForm.MdiChildren[i];
- if( mdiChild == form || !mdiChild.Visible ) continue;
- int xCh = mdiChild.Location.X;
- int yCh = mdiChild.Location.Y;
- int widthCh = mdiChild.Size.Width;
- int heightCh= mdiChild.Size.Height;
- Edge mdiChildEdge1, mdiChildEdge2;
- if( orientation == Orientation.Vertical )
- {
- mdiChildEdge1 = new Edge( xCh, yCh, yCh+heightCh-1 );
- mdiChildEdge2 = new Edge( xCh+widthCh, yCh, yCh+heightCh-1 );
- }
- else
- {
- mdiChildEdge1 = new Edge( yCh, xCh, xCh+widthCh-1 );
- mdiChildEdge2 = new Edge( yCh+heightCh, xCh, xCh+widthCh-1 );
- }
- if((distance = MinDistance( mdiChildEdge1, formEdge1 )) < minDistance )
- {
- minDistance = distance;
- newPosition = mdiChildEdge1.position;
- }
- if((distance = MinDistance( mdiChildEdge2, formEdge1 )) < minDistance )
- {
- minDistance = distance;
- newPosition = mdiChildEdge2.position;
- }
- mdiChildEdge1.position -= 1;
- mdiChildEdge2.position -= 1;
- if((distance = MinDistance( mdiChildEdge1, formEdge2 )) < minDistance )
- {
- minDistance = distance;
- newPosition = mdiChildEdge1.position -
- ( formEdge2.position-formEdge1.position );
- }
- if((distance = MinDistance( mdiChildEdge2, formEdge2 )) < minDistance )
- {
- minDistance = distance;
- newPosition = mdiChildEdge2.position -
- ( formEdge2.position-formEdge1.position );
- }
- }
- if((distance = MinDistance( clientEdge1, formEdge1 )) < minDistance )
- {
- minDistance = distance;
- newPosition = clientEdge1.position;
- }
- if((distance = MinDistance( clientEdge2, formEdge2 )) < minDistance )
- {
- minDistance = distance;
- newPosition = clientEdge2.position -
- ( formEdge2.position-formEdge1.position );
- }
- if( minDistance <= snapDistance && minDistance > 0 )
- {
- Point newLoc = Point.Empty;
- if (orientation == Orientation.Vertical)
- {
- //form.Location = new Point(newPosition, y);
- newLoc = new Point(newPosition, y);
- }
- else
- {
- //form.Location = new Point(x, newPosition);
- newLoc = new Point(x, newPosition);
- }
- DrawPossiblePosition(form, newLoc);
- }
- }
- private void DrawPossiblePosition(Form form, Point possibleLocation)
- {
- float[] dashValues = { 20, 5 };
- Console.Out.WriteLine("Drawing possible position");
- using (Pen blackPen = new Pen(Color.Yellow, 5))
- {
- blackPen.DashPattern = dashValues;
- Console.Out.WriteLine("Got a black dashed pen");
- using (Graphics parentGfx = parentForm.CreateGraphics())
- {
- int xLoc = possibleLocation.X;
- int yLoc = possibleLocation.Y;
- Console.Out.WriteLine("Got gfx object, drawing lines");
- parentGfx.DrawLine(blackPen, new Point(xLoc, yLoc), new Point(xLoc+form.Width, yLoc));
- parentGfx.DrawLine(blackPen, new Point(xLoc+form.Width, yLoc), new Point(xLoc+form.Width, yLoc+form.Height));
- parentGfx.DrawLine(blackPen, new Point(xLoc + form.Width, yLoc + form.Height), new Point(xLoc, yLoc + form.Height));
- parentGfx.DrawLine(blackPen, new Point(xLoc, yLoc + form.Height), new Point(xLoc, yLoc));
- }
- }
- }
- private void SnapOnResize( Form form, Rectangle mdiClientArea )
- {
- int x = form.Location.X;
- int y = form.Location.Y;
- int width = form.Size.Width;
- int height = form.Size.Height;
- Edge formEdge1, formEdge2, clientEdge1, clientEdge2;
- formEdge1 = new Edge( x+width-1, y, y+height-1 );
- formEdge2 = new Edge( y+height-1, x, x+width-1 );
- clientEdge1 = new Edge( mdiClientArea.Width-1, 0, mdiClientArea.Height-1 );
- clientEdge2 = new Edge( mdiClientArea.Height-1, 0, mdiClientArea.Width-1 );
- int childs = parentForm.MdiChildren.Length;
- int newSizeX, newSizeY, distanceX, distanceY, minDistanceX, minDistanceY;
- newSizeX = newSizeY = 0;
- distanceX = distanceY = 0;
- minDistanceX = minDistanceY = snapDistance + 1;
- for( int i=0; i < childs; i++ )
- {
- Form mdiChild = parentForm.MdiChildren[i];
- if( mdiChild == form || !mdiChild.Visible ) continue;
- int xCh = mdiChild.Location.X;
- int yCh = mdiChild.Location.Y;
- int widthCh = mdiChild.Size.Width;
- int heightCh= mdiChild.Size.Height;
- Edge mdiChildEdge1, mdiChildEdge2, mdiChildEdge3, mdiChildEdge4;
- mdiChildEdge1 = new Edge( xCh-1, yCh, yCh+heightCh-1 );
- mdiChildEdge2 = new Edge( xCh+widthCh-1, yCh, yCh+heightCh-1 );
- mdiChildEdge3 = new Edge( yCh-1, xCh, xCh+widthCh-1 );
- mdiChildEdge4 = new Edge( yCh+heightCh-1, xCh, xCh+widthCh-1 );
- if((distanceX = MinDistance( mdiChildEdge1, formEdge1 )) < minDistanceX )
- {
- minDistanceX = distanceX;
- newSizeX = mdiChildEdge1.position - x + 1;
- }
- if((distanceX = MinDistance( mdiChildEdge2, formEdge1 )) < minDistanceX )
- {
- minDistanceX = distanceX;
- newSizeX = mdiChildEdge2.position - x + 1;
- }
- if((distanceY = MinDistance( mdiChildEdge3, formEdge2 )) < minDistanceY )
- {
- minDistanceY = distanceY;
- newSizeY = mdiChildEdge3.position - y + 1;
- }
- if((distanceY = MinDistance( mdiChildEdge4, formEdge2 )) < minDistanceY )
- {
- minDistanceY = distanceY;
- newSizeY = mdiChildEdge4.position - y + 1;
- }
- }
- if((distanceX = MinDistance( clientEdge1, formEdge1 )) < minDistanceX )
- {
- minDistanceX = distanceX;
- newSizeX = clientEdge1.position - x + 1;
- }
- if((distanceY = MinDistance( clientEdge2, formEdge2 )) < minDistanceY )
- {
- minDistanceY = distanceY;
- newSizeY = clientEdge2.position - y + 1;
- }
- if( minDistanceX <= snapDistance && minDistanceX > 0 )
- {
- form.Size = new Size( newSizeX, height );
- }
- if( minDistanceY <= snapDistance && minDistanceY > 0 )
- {
- form.Size = new Size( width, newSizeY );
- }
- }
- private int MinDistance( Edge edge1, Edge edge2 )
- {
- int distance = edge1.DistanceTo( edge2 );
- if( distance > snapDistance ||
- edge1.top > (edge2.bottom+1) ||
- edge1.bottom < (edge2.top-1) )
- return int.MaxValue; // Edges do not intersect each other
- return distance;
- }
- private Rectangle GetMdiClientArea()
- {
- Rectangle mdiClientArea = Rectangle.Empty;
- if( parentForm == null )
- return mdiClientArea;
- foreach( Control c in parentForm.Controls )
- {
- if( c is MdiClient )
- mdiClientArea = c.ClientRectangle;
- }
- return mdiClientArea;
- }
- #region private Edge Class
- /// <summary>
- /// Auxiliary class to define an edge of a form.
- /// <param name='position'>X coordinate for vertical edges and Y - for horizontal ones.</param>
- /// <param name='top'>Y top coordinate for vertical and X left - for horizontal.</param>
- /// <param name='bottom'>Y bottom coordinate for vertical and X right - for horizontal.</param>
- /// </summary>
- private class Edge
- {
- public int position = 0;
- public int top = 0;
- public int bottom = 0;
- public Edge( int position, int top, int bottom )
- {
- this.position = position;
- this.top = top;
- this.bottom = bottom;
- }
- public int DistanceTo( Edge edge )
- {
- return Math.Abs( edge.position - this.position );
- }
- }
- #endregion
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement