Advertisement
Guest User

SnapFormFixed

a guest
Jun 30th, 2014
292
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 11.91 KB | None | 0 0
  1. //
  2. // SnapFormExtender.cs
  3. //
  4. // This class extends MDI child window behavior: it sticks to parents' client
  5. // area edges and to another child windows while moving or resizing.
  6. //
  7. // Author: Eugene Pankov, 2004
  8.  
  9. using System;
  10. using System.Windows.Forms;
  11. using System.ComponentModel;
  12. using System.ComponentModel.Design;
  13. using System.Globalization;
  14. using System.Drawing;
  15. using System.Collections;
  16.  
  17. namespace SnapFormExtenderFixed
  18. {
  19.     public class SnapFormExtenderFixed : Component, IExtenderProvider, ISupportInitialize
  20.     {
  21.         private bool    enableSnap = true;
  22.         private int     snapDistance = 4;
  23.         private Form    parentForm = null;
  24.  
  25.         private enum Orientation
  26.         {
  27.             Vertical,
  28.             Horizontal
  29.         };
  30.  
  31.         public SnapFormExtenderFixed( System.ComponentModel.IContainer container ) : this()
  32.         {
  33.             container.Add( this );
  34.         }
  35.  
  36.         public SnapFormExtenderFixed()
  37.         {
  38.         }
  39.  
  40.         #region CanExtend
  41.  
  42.         public bool CanExtend( object component )
  43.         {
  44.             // only support MDI parent forms
  45.             if( component is Form )
  46.             {
  47.                 Form form = ( Form )component;
  48.                 return form.IsMdiContainer;
  49.             }
  50.             return false ;
  51.         }
  52.         #endregion
  53.  
  54.         [Description("Enable to align MDI child forms on moving and resizing.")]
  55.         [Category("Misc")]
  56.         [DefaultValue(true)]
  57.  
  58.         public bool Enabled
  59.         {
  60.             get{ return enableSnap; }
  61.             set{ enableSnap = value; }
  62.         }
  63.  
  64.         [Description("Parent MDI form which childs should be aligned.")]
  65.         [Category("Misc")]
  66.         [DefaultValue(null)]
  67.  
  68.         public Form Form
  69.         {
  70.             get{ return parentForm; }
  71.             set{ parentForm = value; }
  72.         }
  73.  
  74.         [Description("Distance at which the adhesion will occur.")]
  75.         [Category("Misc")]
  76.         [DefaultValue(4)]
  77.  
  78.         public int Distance
  79.         {
  80.             get{ return snapDistance; }
  81.             set{
  82.                 if( value < 0 || value > 20 )
  83.                     throw new ArgumentOutOfRangeException("Distance", value, "Distance must be a positive number less or equal to 20.");       
  84.                 snapDistance = value;
  85.             }
  86.         }
  87.  
  88.         #region ISupportInitialize Members
  89.  
  90.         void ISupportInitialize.BeginInit()
  91.         {
  92.         }
  93.  
  94.         void ISupportInitialize.EndInit()
  95.         {
  96.             if( !DesignMode && parentForm != null )
  97.             {
  98.                 parentForm.MdiChildActivate +=new EventHandler(parentForm_MdiChildActivate);
  99.             }
  100.         }
  101.         #endregion
  102.  
  103.         private void parentForm_MdiChildActivate(object sender, EventArgs e)
  104.         {
  105.             if( parentForm.ActiveMdiChild != null )
  106.             {
  107.                 Form child = parentForm.ActiveMdiChild;
  108.                 child.Move   -= new EventHandler(child_Move);
  109.                 child.Resize -= new EventHandler(child_Resize);
  110.                 if( enableSnap )
  111.                 {
  112.                     child.Move   += new EventHandler(child_Move);
  113.                     child.Resize += new EventHandler(child_Resize);
  114.                 }
  115.             }
  116.         }
  117.  
  118.         private void child_Move(object sender, EventArgs e)
  119.         {
  120.             if( sender == null ) return;
  121.             Form form = ( Form )sender;
  122.             if( form.WindowState != FormWindowState.Normal ) return;
  123.             Rectangle mdiClientArea = GetMdiClientArea();
  124.             SnapOnMove( form, mdiClientArea, Orientation.Vertical );
  125.             SnapOnMove( form, mdiClientArea, Orientation.Horizontal );
  126.         }
  127.  
  128.         private void child_Resize(object sender, EventArgs e)
  129.         {
  130.             if( sender == null ) return;
  131.             Form form = ( Form )sender;
  132.             if( form.WindowState != FormWindowState.Normal ) return;
  133.             Rectangle mdiClientArea = GetMdiClientArea();
  134.             SnapOnResize( form, mdiClientArea );
  135.         }
  136.  
  137.         private void SnapOnMove( Form form, Rectangle mdiClientArea, Orientation orientation )
  138.         {
  139.             int x       = form.Location.X;
  140.             int y       = form.Location.Y;
  141.             int width   = form.Size.Width;
  142.             int height  = form.Size.Height;
  143.             Edge formEdge1, formEdge2, clientEdge1, clientEdge2;
  144.  
  145.             if( orientation == Orientation.Vertical )   // Check vertical edges
  146.             {
  147.                 formEdge1   = new Edge( x, y, y+height-1 );
  148.                 formEdge2   = new Edge( x+width-1, y, y+height-1 );
  149.                 clientEdge1 = new Edge( 0, 0, mdiClientArea.Height-1 );
  150.                 clientEdge2 = new Edge( mdiClientArea.Width-1, 0, mdiClientArea.Height-1 );
  151.             }
  152.             else                                        // Check horizontal edges
  153.             {
  154.                 formEdge1   = new Edge( y, x, x+width-1 );
  155.                 formEdge2   = new Edge( y+height-1, x, x+width-1 );
  156.                 clientEdge1 = new Edge( 0, 0, mdiClientArea.Width-1 );
  157.                 clientEdge2 = new Edge( mdiClientArea.Height-1, 0, mdiClientArea.Width-1 );
  158.             }
  159.  
  160.             int childs = parentForm.MdiChildren.Length;
  161.  
  162.             int newPosition = 0;
  163.             int distance = 0;
  164.             int minDistance = snapDistance + 1;
  165.  
  166.             for( int i=0; i < childs && minDistance > 0; i++ )
  167.             {
  168.                 Form mdiChild = parentForm.MdiChildren[i];
  169.                 if( mdiChild == form || !mdiChild.Visible ) continue;
  170.  
  171.                 int xCh     = mdiChild.Location.X;
  172.                 int yCh     = mdiChild.Location.Y;
  173.                 int widthCh = mdiChild.Size.Width;
  174.                 int heightCh= mdiChild.Size.Height;
  175.                 Edge mdiChildEdge1, mdiChildEdge2;
  176.  
  177.                 if( orientation == Orientation.Vertical )
  178.                 {
  179.                     mdiChildEdge1 = new Edge( xCh, yCh, yCh+heightCh-1 );
  180.                     mdiChildEdge2 = new Edge( xCh+widthCh, yCh, yCh+heightCh-1 );
  181.                 }
  182.                 else
  183.                 {
  184.                     mdiChildEdge1 = new Edge( yCh, xCh, xCh+widthCh-1 );
  185.                     mdiChildEdge2 = new Edge( yCh+heightCh, xCh, xCh+widthCh-1 );
  186.                 }
  187.  
  188.                 if((distance = MinDistance( mdiChildEdge1, formEdge1 )) < minDistance )
  189.                 {
  190.                     minDistance = distance;
  191.                     newPosition = mdiChildEdge1.position;
  192.                 }
  193.                 if((distance = MinDistance( mdiChildEdge2, formEdge1 )) < minDistance )
  194.                 {
  195.                     minDistance = distance;
  196.                     newPosition = mdiChildEdge2.position;
  197.                 }
  198.                 mdiChildEdge1.position -= 1;
  199.                 mdiChildEdge2.position -= 1;
  200.  
  201.                 if((distance = MinDistance( mdiChildEdge1, formEdge2 )) < minDistance )
  202.                 {
  203.                     minDistance = distance;
  204.                     newPosition = mdiChildEdge1.position -
  205.                         ( formEdge2.position-formEdge1.position );
  206.                 }
  207.                 if((distance = MinDistance( mdiChildEdge2, formEdge2 )) < minDistance )
  208.                 {
  209.                     minDistance = distance;
  210.                     newPosition = mdiChildEdge2.position -
  211.                         ( formEdge2.position-formEdge1.position );
  212.                 }
  213.             }
  214.  
  215.             if((distance = MinDistance( clientEdge1, formEdge1 )) < minDistance )
  216.             {
  217.                 minDistance = distance;
  218.                 newPosition = clientEdge1.position;
  219.             }
  220.             if((distance = MinDistance( clientEdge2, formEdge2 )) < minDistance )
  221.             {
  222.                 minDistance = distance;
  223.                 newPosition = clientEdge2.position -
  224.                     ( formEdge2.position-formEdge1.position );
  225.             }
  226.             if( minDistance <= snapDistance && minDistance > 0 )
  227.             {
  228.                 Point newLoc = Point.Empty;
  229.                 if (orientation == Orientation.Vertical)
  230.                 {
  231.                     //form.Location = new Point(newPosition, y);
  232.                     newLoc = new Point(newPosition, y);
  233.                 }
  234.                 else
  235.                 {
  236.                     //form.Location = new Point(x, newPosition);
  237.                     newLoc = new Point(x, newPosition);
  238.                 }
  239.  
  240.                 DrawPossiblePosition(form, newLoc);
  241.             }
  242.         }
  243.  
  244.         private void DrawPossiblePosition(Form form, Point possibleLocation)
  245.         {
  246.             float[] dashValues = { 20, 5 };
  247.             Console.Out.WriteLine("Drawing possible position");
  248.             using (Pen blackPen = new Pen(Color.Yellow, 5))
  249.             {
  250.                 blackPen.DashPattern = dashValues;
  251.                 Console.Out.WriteLine("Got a black dashed pen");
  252.                 using (Graphics parentGfx = parentForm.CreateGraphics())
  253.                 {
  254.                     int xLoc = possibleLocation.X;
  255.                     int yLoc = possibleLocation.Y;
  256.                     Console.Out.WriteLine("Got gfx object, drawing lines");
  257.                     parentGfx.DrawLine(blackPen, new Point(xLoc, yLoc), new Point(xLoc+form.Width, yLoc));
  258.                     parentGfx.DrawLine(blackPen, new Point(xLoc+form.Width, yLoc), new Point(xLoc+form.Width, yLoc+form.Height));
  259.                     parentGfx.DrawLine(blackPen, new Point(xLoc + form.Width, yLoc + form.Height), new Point(xLoc, yLoc + form.Height));
  260.                     parentGfx.DrawLine(blackPen, new Point(xLoc, yLoc + form.Height), new Point(xLoc, yLoc));
  261.                 }
  262.             }
  263.         }
  264.  
  265.         private void SnapOnResize( Form form, Rectangle mdiClientArea )
  266.         {
  267.             int x       = form.Location.X;
  268.             int y       = form.Location.Y;
  269.             int width   = form.Size.Width;
  270.             int height  = form.Size.Height;
  271.             Edge formEdge1, formEdge2, clientEdge1, clientEdge2;
  272.  
  273.             formEdge1   = new Edge( x+width-1, y, y+height-1 );
  274.             formEdge2   = new Edge( y+height-1, x, x+width-1 );
  275.             clientEdge1 = new Edge( mdiClientArea.Width-1, 0, mdiClientArea.Height-1 );
  276.             clientEdge2 = new Edge( mdiClientArea.Height-1, 0, mdiClientArea.Width-1 );
  277.  
  278.             int childs = parentForm.MdiChildren.Length;
  279.  
  280.             int newSizeX, newSizeY, distanceX, distanceY, minDistanceX, minDistanceY;
  281.             newSizeX  = newSizeY = 0;
  282.             distanceX = distanceY = 0;
  283.             minDistanceX = minDistanceY = snapDistance + 1;
  284.  
  285.             for( int i=0; i < childs; i++ )
  286.             {
  287.                 Form mdiChild = parentForm.MdiChildren[i];
  288.                 if( mdiChild == form || !mdiChild.Visible ) continue;
  289.  
  290.                 int xCh     = mdiChild.Location.X;
  291.                 int yCh     = mdiChild.Location.Y;
  292.                 int widthCh = mdiChild.Size.Width;
  293.                 int heightCh= mdiChild.Size.Height;
  294.                 Edge mdiChildEdge1, mdiChildEdge2, mdiChildEdge3, mdiChildEdge4;
  295.  
  296.                 mdiChildEdge1 = new Edge( xCh-1, yCh, yCh+heightCh-1 );
  297.                 mdiChildEdge2 = new Edge( xCh+widthCh-1, yCh, yCh+heightCh-1 );
  298.                 mdiChildEdge3 = new Edge( yCh-1, xCh, xCh+widthCh-1 );
  299.                 mdiChildEdge4 = new Edge( yCh+heightCh-1, xCh, xCh+widthCh-1 );
  300.  
  301.                 if((distanceX = MinDistance( mdiChildEdge1, formEdge1 )) < minDistanceX )
  302.                 {
  303.                     minDistanceX = distanceX;
  304.                     newSizeX = mdiChildEdge1.position - x + 1;
  305.                 }
  306.                 if((distanceX = MinDistance( mdiChildEdge2, formEdge1 )) < minDistanceX )
  307.                 {
  308.                     minDistanceX = distanceX;
  309.                     newSizeX = mdiChildEdge2.position - x + 1;
  310.                 }
  311.                 if((distanceY = MinDistance( mdiChildEdge3, formEdge2 )) < minDistanceY )
  312.                 {
  313.                     minDistanceY = distanceY;
  314.                     newSizeY = mdiChildEdge3.position - y + 1;
  315.                 }
  316.                 if((distanceY = MinDistance( mdiChildEdge4, formEdge2 )) < minDistanceY )
  317.                 {
  318.                     minDistanceY = distanceY;
  319.                     newSizeY = mdiChildEdge4.position - y + 1;
  320.                 }
  321.             }
  322.  
  323.             if((distanceX = MinDistance( clientEdge1, formEdge1 )) < minDistanceX )
  324.             {
  325.                 minDistanceX = distanceX;
  326.                 newSizeX = clientEdge1.position - x + 1;
  327.             }
  328.             if((distanceY = MinDistance( clientEdge2, formEdge2 )) < minDistanceY )
  329.             {
  330.                 minDistanceY = distanceY;
  331.                 newSizeY = clientEdge2.position - y + 1;
  332.             }
  333.  
  334.             if( minDistanceX <= snapDistance && minDistanceX > 0 )
  335.             {
  336.                 form.Size = new Size( newSizeX, height );
  337.             }
  338.             if( minDistanceY <= snapDistance && minDistanceY > 0 )
  339.             {
  340.                 form.Size = new Size( width, newSizeY );
  341.             }
  342.         }
  343.  
  344.         private int MinDistance( Edge edge1, Edge edge2 )
  345.         {
  346.             int distance = edge1.DistanceTo( edge2 );
  347.             if( distance > snapDistance      ||
  348.                 edge1.top > (edge2.bottom+1) ||
  349.                 edge1.bottom < (edge2.top-1) )
  350.                 return int.MaxValue;        // Edges do not intersect each other
  351.             return distance;
  352.         }
  353.  
  354.         private Rectangle GetMdiClientArea()
  355.         {
  356.             Rectangle mdiClientArea = Rectangle.Empty;
  357.  
  358.             if( parentForm == null )
  359.                 return mdiClientArea;
  360.  
  361.             foreach( Control c in parentForm.Controls )
  362.             {
  363.                 if( c is MdiClient )
  364.                     mdiClientArea = c.ClientRectangle;
  365.             }
  366.             return mdiClientArea;
  367.         }
  368.  
  369.         #region private Edge Class
  370.  
  371.         /// <summary>
  372.         /// Auxiliary class to define an edge of a form.
  373.         /// <param name='position'>X coordinate for vertical edges and Y - for horizontal ones.</param>
  374.         /// <param name='top'>Y top coordinate for vertical and X left - for horizontal.</param>
  375.         /// <param name='bottom'>Y bottom coordinate for vertical and X right - for horizontal.</param>
  376.         /// </summary>
  377.         private class Edge
  378.         {
  379.             public int  position = 0;
  380.             public int  top = 0;
  381.             public int  bottom = 0;
  382.  
  383.             public Edge( int position, int top, int bottom )
  384.             {
  385.                 this.position = position;
  386.                 this.top = top;
  387.                 this.bottom = bottom;
  388.             }
  389.  
  390.             public int DistanceTo( Edge edge )
  391.             {
  392.                 return Math.Abs( edge.position - this.position );
  393.             }
  394.         }
  395.         #endregion
  396.     }
  397. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement