ParentControlDesigner.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / fx / src / Designer / WinForms / System / WinForms / Design / ParentControlDesigner.cs / 1 / ParentControlDesigner.cs

                            //------------------------------------------------------------------------------
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
//  
//-----------------------------------------------------------------------------
 
/* 
 */
namespace System.Windows.Forms.Design { 
    using Microsoft.Win32;
    using System;
    using System.Collections;
    using System.ComponentModel; 
    using System.ComponentModel.Design;
    using System.Design; 
    using System.Diagnostics; 
    using System.Diagnostics.CodeAnalysis;
    using System.Drawing; 
    using System.Drawing.Design;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Threading; 
    using System.Windows.Forms;
    using System.Windows.Forms.Design.Behavior; 
    using ArrayList = System.Collections.ArrayList; 

 
    /// 
    /// 
    ///     The ParentControlDesigner class builds on the ControlDesigner.  It adds the ability
    ///     to manipulate child components, and provides a selection UI handler for all 
    ///     components it contains.
    ///  
    public class ParentControlDesigner : ControlDesigner, IOleDragClient { 

#if DEBUG 
        private static TraceSwitch containerSelectSwitch     = new TraceSwitch("ContainerSelect", "Debug container selection");
#endif
        private static BooleanSwitch StepControls = new BooleanSwitch("StepControls", "ParentControlDesigner: step added controls");
 
        private Point                           mouseDragBase = InvalidPoint;      // the base point of the drag
        private Rectangle                       mouseDragOffset = Rectangle.Empty;    // always keeps the current rectangle 
        private ToolboxItem                     mouseDragTool;      // the tool that's being dragged, if we're creating a component 
        private FrameStyle                      mouseDragFrame;     // the frame style of this mouse drag
 
        private OleDragDropHandler              oleDragDropHandler; // handler for ole drag drop operations
        private EscapeHandler                   escapeHandler;      // active during drags to override escape.
        private Control                         pendingRemoveControl; // we've gotten an OnComponentRemoving, and are waiting for OnComponentRemove
        private IComponentChangeService         componentChangeSvc; 
        private DragAssistanceManager           dragManager; //used to apply snaplines when dragging a new tool rect on the designer's surface
        private ToolboxSnapDragDropEventArgs    toolboxSnapDragDropEventArgs;//used to store extra info about a beh. svc. dragdrop from the toolbx 
        private ToolboxItemSnapLineBehavior     toolboxItemSnapLineBehavior;//this is our generic snapline box for dragging comps from the toolbx 
        private Graphics                        graphics;//graphics object of the adornerwindow (via BehaviorService)
 
        // Services that we keep around for the duration of a drag.  you should always check
        // to see if you need to get this service.  We cache it, but demand create it.
        //
        private IToolboxService toolboxService; 

        private const int   minGridSize = 2; 
        private const int   maxGridSize = 200; 

        // designer options... 
        //
        private Point  adornerWindowToScreenOffset;//quick lookup for offsetting snaplines for new tools

        private bool checkSnapLineSetting = true;  // Since layout options is global for the duration of the designer, we should only query it once. 
        private bool defaultUseSnapLines = false;
 
        private bool    gridSnap = true; 
        private Size    gridSize = Size.Empty;
        private bool    drawGrid = true; 

        private bool parentCanSetDrawGrid = true; //since we can inherit the grid/snap setting of our parent,
        private bool parentCanSetGridSize = true; //  these 3 properties let us know if these values have
        private bool parentCanSetGridSnap = true; //  been set explicitly by a user - so to ignore the parent's setting 

        private bool getDefaultDrawGrid = true; 
        private bool getDefaultGridSize = true; 
        private bool getDefaultGridSnap = true;
        private StatusCommandUI               statusCommandUI;   // UI for setting the StatusBar Information.. 


        private int suspendChanging = 0;
        ///  
        /// 
        ///     This is called after the user selects a toolbox item (that has a ParentControlDesigner 
        ///     associated with it) and draws a reversible rectangle on a designer's surface.  If 
        ///     this property returns true, it is indicating that the Controls that were lasso'd on the
        ///     designer's surface will be re-parented to this designer's control. 
        /// 
        protected virtual bool AllowControlLasso {
            get {
                return true; 
            }
        } 
 
        /// 
        ///  
        ///     This is called to check whether a generic dragbox should be drawn when dragging a toolbox item
        ///     over the designer's surface.
        /// 
        protected virtual bool AllowGenericDragBox { 
            get {
                return true; 
            } 
        }
 
        /// 
        /// 
        ///     This is called to check whether the z-order of dragged controls should be maintained when dropped on a
        ///     ParentControlDesigner. By default it will, but e.g. FlowLayoutPanelDesigner wants to do its own z-ordering. 
        ///
        ///     If this returns true, then the DropSourceBehavior will attempt to set the index of the controls being 
        ///     dropped to preserve the original order (in the dragSource). If it returns false, the index will not 
        ///     be set.
        /// 
        ///     If this is set to false, then the DropSourceBehavior will not treat a drag as a local drag even
        ///     if the dragSource and the dragTarget are the same. This will allow a ParentControlDesigner to hook
        ///     OnChildControlAdded to set the right child index, since in this case, the control(s) being dragged
        ///     will be removed from the dragSource and then added to the dragTarget. 
        ///
        ///  
        protected internal virtual bool AllowSetChildIndexOnDrop { 
            get {
                return true; 
            }
        }

        ///  
        /// 
        ///     This can be called to determine the current grid spacing and mode. 
        ///     It is sensitive to what modifier keys the user currently has down and 
        ///     will either return the current grid snap dimensons, or a 1x1 point
        ///     indicating no snap. 
        /// 
        private Size CurrentGridSize {
            get {
                return GridSize; 
            }
        } 
 
        /// 
        ///  
        /// Determines the default location for a control added to this designer.
        /// it is usualy (0,0), but may be modified if the container has special borders, etc.
        /// 
        protected virtual Point DefaultControlLocation { 
            get {
                return new Point(0,0); 
            } 
        }
 

        private bool DefaultUseSnapLines {
            get {
 
                if (checkSnapLineSetting) {
                    checkSnapLineSetting = false; 
                    defaultUseSnapLines = DesignerUtils.UseSnapLines(Component.Site); 
                }
 
                return defaultUseSnapLines;

            }
        } 

        ///  
        ///  
        ///     Accessor method for the DrawGrid property.  This property determines
        ///     if the grid should be drawn on a control. 
        /// 
        protected virtual bool DrawGrid {
            get {
 
                // If snaplines are on, the we never want to draw the grid
 
                if (DefaultUseSnapLines) { 
                    return false;
                } 
                else if (getDefaultDrawGrid) {

                    drawGrid = true;
 
                    //Before we check our options page, we need to see if our parent
                    //is a ParentControlDesigner, is so, then we will want to inherit all 
                    //our grid/snap setting from it - instead of our options page 
                    //
                    ParentControlDesigner parent = GetParentControlDesignerOfParent(); 
                    if (parent != null) {
                        drawGrid = parent.DrawGrid;
                    }
                    else { 

                        object value = DesignerUtils.GetOptionValue(ServiceProvider, "ShowGrid"); 
                        if (value is bool) { 
                            drawGrid = (bool)value;
                        } 
                    }

                }
 
                return drawGrid;
            } 
 
            set {
 
                if (value != drawGrid) {

                    if (parentCanSetDrawGrid) {
                        parentCanSetDrawGrid = false; 
                    }
 
                    if (getDefaultDrawGrid) { 
                        getDefaultDrawGrid = false;
                    } 

                    drawGrid = value;

                    //invalidate the cotnrol to remove or draw the grid based on the new value 
                    Control control = Control;
                    if (control != null) { 
                        control.Invalidate(true); 
                    }
 
                    //now, notify all child parent control designers that we have changed our setting
                    // 'cause they might to change along with us, unless the user has explicitly set
                    // those values...
                    IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); 
                    if (host != null) {
                        // for (int i = 0; i < children.Length; i++) { 
                        foreach(Control child in Control.Controls) { 
                            ParentControlDesigner designer = host.GetDesigner(child) as ParentControlDesigner;
                            if (designer != null) { 
                                designer.DrawGridOfParentChanged(drawGrid);
                            }
                        }
                    } 
                }
            } 
        } 

        ///  
        /// 
        ///     Determines whether drag rects can be drawn on this designer.
        /// 
        protected override bool EnableDragRect { 
            get {
                return true; 
            } 
        }
 

        internal Size ParentGridSize {
            get {
                return GridSize; 
            }
        } 
 
        /// 
        ///  
        ///     Gets/Sets the GridSize property for a form or user control.
        /// 
        protected Size GridSize {
            get { 

                if (getDefaultGridSize) { 
                    gridSize = new Size(8,8); 

                    //Before we check our options page, we need to see if our parent 
                    //is a ParentControlDesigner, is so, then we will want to inherit all
                    //our grid/snap setting from it - instead of our options page
                    //
                    ParentControlDesigner parent = GetParentControlDesignerOfParent(); 
                    if (parent != null) {
                        gridSize = parent.GridSize; 
                    } 
                    else {
                        object value = DesignerUtils.GetOptionValue(ServiceProvider, "GridSize"); 
                        if (value is Size) {
                            gridSize = (Size)value;
                        }
                    } 

                } 
 
                return gridSize;
            } 
            set {
                if (parentCanSetGridSize) {
                    parentCanSetGridSize = false;
                } 

                if (getDefaultGridSize) { 
                    getDefaultGridSize = false; 
                }
 
                //do some validation checking here, against min & max GridSize
                //
                if ( value.Width < minGridSize || value.Height < minGridSize ||
                     value.Width > maxGridSize || value.Height > maxGridSize) 
                    throw new ArgumentException(SR.GetString(SR.InvalidArgument,
                                                              "GridSize", 
                                                              value.ToString())); 
                gridSize = value;
 
                //invalidate the control
                Control control = Control;
                if (control != null) {
                    control.Invalidate(true); 
                }
 
                //now, notify all child parent control designers that we have changed our setting 
                // 'cause they might to change along with us, unless the user has explicitly set
                // those values... 
                IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
                if (host != null) {
                    foreach(Control child in Control.Controls) {
                        ParentControlDesigner designer = host.GetDesigner(child) as ParentControlDesigner; 
                        if (designer != null) {
                            designer.GridSizeOfParentChanged(gridSize); 
                        } 
                    }
                } 
            }
        }

        ///  
        /// 
        ///     This property is used by deriving classes to determine if the designer is 
        ///     in a state where it has a valid MouseDragTool. 
        /// 
        protected ToolboxItem MouseDragTool { 
            get {
                return mouseDragTool;
            }
        } 

        ///  
        ///     This property is used by deriving classes to determine if it returns the control being designed or some other Container ... 
        ///     while adding a component to it.
        ///     e.g: When SplitContainer is selected and a component is being added ... the SplitContainer designer would return a 
        ///     SelectedPanel as the ParentControl for all the items being added rather than itself.
        /// 
        protected virtual Control GetParentForComponent(IComponent component) {
            return Control; 
        }
 
 
        [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
        // We need to allocation new ArrayList and pass it to the caller.. 
        // So its ok to Suppress this.
        protected void AddPaddingSnapLines(ref ArrayList snapLines) {

            if (snapLines == null) { 
                snapLines = new ArrayList(4);
            } 
 
            //In order to add padding, we need to get the offset from the usable client area of our control
            //and the actual origin of our control.  In other words: how big is the non-client area here? 
            // Ex: we want to add padding on a form to the insides of the borders and below the titlebar.
            Point offset = GetOffsetToClientArea();

            //the desplay rectangle should be the client area combined with the padding value 
            Rectangle displayRectangle = Control.DisplayRectangle;
            displayRectangle.X += offset.X;//offset for non-client area 
            displayRectangle.Y += offset.Y;//offset for non-client area 

            //add the four paddings of our control 

            // Even if a control does not have padding, we still want to add Padding snaplines.
            // This is because we only try to match to matching snaplines. Makes the code a little easier...
            snapLines.Add( new SnapLine(SnapLineType.Vertical, displayRectangle.Left, SnapLine.PaddingLeft, SnapLinePriority.Always)); 
            snapLines.Add( new SnapLine(SnapLineType.Vertical, displayRectangle.Right, SnapLine.PaddingRight, SnapLinePriority.Always));
            snapLines.Add( new SnapLine(SnapLineType.Horizontal, displayRectangle.Top, SnapLine.PaddingTop, SnapLinePriority.Always)); 
            snapLines.Add( new SnapLine(SnapLineType.Horizontal, displayRectangle.Bottom, SnapLine.PaddingBottom, SnapLinePriority.Always)); 
        }
 
        /// 
        /// 
        ///     Returns a list of SnapLine objects representing interesting
        ///     alignment points for this control.  These SnapLines are used 
        ///     to assist in the positioning of the control on a parent's
        ///     surface. 
        ///  
        public override IList SnapLines {
            get { 
                ArrayList snapLines = base.SnapLines as ArrayList;

                if (snapLines == null) {
                    Debug.Fail("why did base.SnapLines return null?"); 
                    snapLines = new ArrayList(4);
                } 
 
                AddPaddingSnapLines(ref snapLines);
                return snapLines; 
            }
        }

        private IServiceProvider ServiceProvider { 
            get {
                if (Component != null) { 
                    return Component.Site; 
                }
 
                return null;
            }
        }
 

        ///  
        ///  
        ///     Determines if we should snap to grid or not.
        ///  
        private bool SnapToGrid {
            get{

                // If snaplines are on, the we never want to snap to grid 
                if (DefaultUseSnapLines) {
 
                    return false; 
                }
                else if (getDefaultGridSnap) { 

                    gridSnap = true;

                    //Before we check our options page, we need to see if our parent 
                    //is a ParentControlDesigner, is so, then we will want to inherit all
                    //our grid/snap setting from it - instead of our options page 
                    // 
                    ParentControlDesigner parent = GetParentControlDesignerOfParent();
                    if (parent != null) { 
                        gridSnap = parent.SnapToGrid;
                    }
                    else {
 
                        object optionValue = DesignerUtils.GetOptionValue(ServiceProvider, "SnapToGrid");
                        if (optionValue != null && optionValue is bool) { 
                            gridSnap = (bool)optionValue; 
                        }
                    } 

                }

                return gridSnap; 
            }
            set{ 
 
                if (gridSnap != value) {
                    if (parentCanSetGridSnap) { 
                        parentCanSetGridSnap = false;
                    }

                    if (getDefaultGridSnap) { 
                        getDefaultGridSnap = false;
                    } 
 
                    gridSnap = value;
 
                    //now, notify all child parent control designers that we have changed our setting
                    // 'cause they might to change along with us, unless the user has explicitly set
                    // those values...
                    IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); 
                    if (host != null) {
                        foreach(Control child in Control.Controls) { 
                            ParentControlDesigner designer = host.GetDesigner(child) as ParentControlDesigner; 
                            if (designer != null) {
                                designer.GridSnapOfParentChanged(gridSnap); 
                            }
                        }
                    }
 
                }
            } 
        } 

        internal static int DetermineTopChildIndex(Control parent) { 
            // ASURT 78699 -- only bring the new control as far forward as the last inherited control ... we can't
            // go in front of that because the base class AddRange will happen before us so we'll always be added
            // under them.
            // 
            int bestIndex = 0;
            for (bestIndex = 0; bestIndex < parent.Controls.Count - 1; bestIndex++) { 
 
                Control child = parent.Controls[bestIndex];
 
                if (child.Site == null) {
                    continue;
                }
 
                InheritanceAttribute inheritanceAttribute = (InheritanceAttribute)TypeDescriptor.GetAttributes(child)[typeof(InheritanceAttribute)];
                InheritanceLevel inheritanceLevel = InheritanceLevel.NotInherited; 
 
                if (inheritanceAttribute != null) {
                    inheritanceLevel = inheritanceAttribute.InheritanceLevel; 
                }

                if (inheritanceLevel == InheritanceLevel.NotInherited) {
                    break; 
                }
            } 
            return bestIndex; 
        }
 
        internal virtual void AddChildControl(Control newChild) {
            if (newChild.Left == 0 && newChild.Top == 0 && newChild.Width >= this.Control.Width && newChild.Height >= this.Control.Height) {
                // bump the control down one gridsize just so it's selectable...
                // 
                Point loc = newChild.Location;
                loc.Offset(GridSize.Width, GridSize.Height); 
                newChild.Location = loc; 
            }
 
            this.Control.Controls.Add(newChild);

            int bestIndex = DetermineTopChildIndex(this.Control);
            this.Control.Controls.SetChildIndex(newChild, bestIndex); 
        }
 
        internal void AddControl(Control newChild, IDictionary defaultValues) { 
            Point location = Point.Empty;
            Size size = Size.Empty; 
            Size offset = new Size(0, 0);
            bool hasLocation = (defaultValues != null && defaultValues.Contains("Location"));
            bool hasSize = (defaultValues != null && defaultValues.Contains("Size"));
 
            if (hasLocation) location = (Point)defaultValues["Location"];
            if (hasSize) size = (Size)defaultValues["Size"]; 
            if (defaultValues != null && defaultValues.Contains("Offset")) { 
                offset = (Size)defaultValues["Offset"];
            } 

            // If this component doesn't have a control designer, or if this control
            // is top level, then ignore it.  We have the reverse logic in OnComponentAdded
            // in the document designer so that we will add those guys to the tray. 
            // Also, if the child-control has already been parented, we assume it's also been located and return immediately.
            // Otherwise, proceed with the parenting and locating. 
            // 
            IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
            if (host != null 
                && newChild != null
                && !this.Control.Contains(newChild)
                && (host.GetDesigner(newChild) as ControlDesigner) != null
                && !(newChild is Form && ((Form)newChild).TopLevel)) { 

                Rectangle bounds = new Rectangle(); 
 
                // If we were provided with a location, convert it to parent control coordinates.
                // Otherwise, get the control's size and put the location in the middle of it 
                //
                if (hasLocation) {
                    location = this.Control.PointToClient(location);
                    bounds.X = location.X; 
                    bounds.Y = location.Y;
                } 
                else { 

                    // is the currently selected control this container? 
                    //
                    ISelectionService selSvc = (ISelectionService)GetService(typeof(ISelectionService));
                    object primarySelection = selSvc.PrimarySelection;
                    Control selectedControl = null; 
                    if (primarySelection != null) {
                        selectedControl = ((IOleDragClient)this).GetControlForComponent(primarySelection); 
                    } 

                    // If the resulting control that came back isn't sited, it's not part of the 
                    // design surface and should not be used as a marker.
                    //
                    if (selectedControl != null && selectedControl.Site == null) {
                        selectedControl = null; 
                    }
 
                    // if the currently selected container is this parent 
                    // control, default to 0,0
                    // 
                    if (primarySelection == this.Component || selectedControl == null) {
                        bounds.X = DefaultControlLocation.X;
                        bounds.Y = DefaultControlLocation.Y;
                    } 
                    else {
                        // otherwise offset from selected control. 
                        // 
                        bounds.X = selectedControl.Location.X + GridSize.Width;
                        bounds.Y = selectedControl.Location.Y + GridSize.Height; 
                    }

                }
 
                // If we were not given a size, ask the control for its default.  We
                // also update the location here so the control is in the middle of 
                // the user's point, rather than at the edge. 
                //
                if (hasSize) { 
                    bounds.Width = size.Width;
                    bounds.Height = size.Height;
                }
                else { 
                    bounds.Size = GetDefaultSize(newChild);
                } 
 
                // If we were given neither, center the control
                // 
                if (!hasSize && !hasLocation) {

                    // get the adjusted location, then inflate
                    // the rect so we can find a nice spot 
                    // for this control to live.
                    // 
                    Rectangle tempBounds = GetAdjustedSnapLocation(Rectangle.Empty, bounds); 

                    // compute the stacking location 
                    //
                    tempBounds = GetControlStackLocation(tempBounds);
                    bounds = tempBounds;
                } 
                else {
                    // Finally, convert the bounds to the appropriate grid snaps 
                    // 
                    bounds = GetAdjustedSnapLocation(Rectangle.Empty, bounds);
                } 

                // Adjust for the offset, if any
                //
                bounds.X += offset.Width; 
                bounds.Y += offset.Height;
 
                //check to see if we have additional information for bounds from 
                //the behaviorservice dragdrop logic
                if (defaultValues != null && defaultValues.Contains("ToolboxSnapDragDropEventArgs")) { 

                    ToolboxSnapDragDropEventArgs e = defaultValues["ToolboxSnapDragDropEventArgs"] as ToolboxSnapDragDropEventArgs;
                    Debug.Assert(e != null, "Why can't we get a ToolboxSnapDragDropEventArgs object out of our default values?");
 
                    Rectangle snappedBounds = DesignerUtils.GetBoundsFromToolboxSnapDragDropInfo(e, bounds, Control.IsMirrored);
 
                    //Make sure the snapped bounds intersects with the bounds of the root control before we go 
                    //adjusting the drag offset.  A race condition exists where the user can drag a tbx item so fast
                    //that the adorner window will never receive the proper drag/mouse move messages and 
                    //never properly adjust the snap drag info.  This cause the control to be added @ 0,0 w.r.t.
                    //the adorner window.
                    Control rootControl = host.RootComponent as Control;
                    if (rootControl != null && snappedBounds.IntersectsWith(rootControl.ClientRectangle)) { 
                        bounds = snappedBounds;
                    } 
                } 

 
                // Parent the control to the designer and set it to the front.
                //
                //
                PropertyDescriptor controlsProp = TypeDescriptor.GetProperties(this.Control)["Controls"]; 
                if (componentChangeSvc != null) {
                    componentChangeSvc.OnComponentChanging(this.Control, controlsProp); 
                } 

                AddChildControl(newChild); 



                // Now see if the control has size and location properties.  Update 
                // these values if it does.
                // 
                PropertyDescriptorCollection props = TypeDescriptor.GetProperties(newChild); 
                if (props != null) {
                    PropertyDescriptor prop = props["Size"]; 
                    if (prop != null) {
                        prop.SetValue(newChild, new Size(bounds.Width, bounds.Height));
                    }
 
                    //VSWhidbey# 364133 - ControlDesigner shadows the Location property. If the control is parented
                    //and the parent is a scrollable control, then it expects the Location to be in displayrectangle coordinates. 
                    //At this point bounds are in clientrectangle coordinates, so we need to check if we need to adjust the coordinates. 
                    //The reason this worked in Everett was that the AddChildControl was done AFTER this. The AddChildControl was moved
                    //above a while back. Not sure what will break if AddChildControl is moved down below, so let's just fix up things 
                    //here.

                    Point pt = new Point(bounds.X, bounds.Y);
                    ScrollableControl p = newChild.Parent as ScrollableControl; 
                    if (p != null) {
                        Point ptScroll = p.AutoScrollPosition; 
                        pt.Offset(-ptScroll.X, -ptScroll.Y); //always want to add the control below/right of the AutoScrollPosition 
                    }
 
                    prop = props["Location"];
                    if (prop != null) {
                        prop.SetValue(newChild, pt);
                    } 
                }
 
                if (componentChangeSvc != null) { 
                    componentChangeSvc.OnComponentChanged(this.Control, controlsProp, this.Control.Controls, this.Control.Controls);
                } 

                newChild.Update();
            }
        } 

        ///  
        ///  
        ///      Adds all the child components of a component
        ///      to the given container 
        /// 
        private void AddChildComponents(IComponent component, IContainer container, IDesignerHost host) {

            Control control = GetControl(component); 

            if (control != null) { 
                Control  parent = control; 

                Control[] children = new Control[parent.Controls.Count]; 
                parent.Controls.CopyTo(children, 0);

                string name;
                ISite childSite; 
                IContainer childContainer = null;
 
                object parentDesigner = host.GetDesigner(component); 

                for (int i = 0; i < children.Length; i++) { 
                    childSite = ((IComponent)children[i]).Site;

                    if (childSite != null) {
                        name = childSite.Name; 
                        if (container.Components[name] != null) {
                            name = null; 
                        } 
                        childContainer = childSite.Container;
                    } 
                    else {
                        //name = null;
                        // we don't want to add unsited child controls because
                        // these may be items from a composite control.  if they 
                        // are legitamite children, the ComponentModelPersister would have
                        // sited them already. 
                        // 
                        continue;
                    } 

                    if (childContainer != null) {
                        childContainer.Remove(children[i]);
                    } 

                    if (name != null) { 
                        container.Add(children[i], name); 
                    }
                    else { 
                        container.Add(children[i]);
                    }

                    if (children[i].Parent != parent) { 
                        parent.Controls.Add(children[i]);
                    } 
                    else { 
                        // ugh, last resort
                        int childIndex = parent.Controls.GetChildIndex(children[i]); 
                        parent.Controls.Remove(children[i]);
                        parent.Controls.Add(children[i]);
                        parent.Controls.SetChildIndex(children[i], childIndex);
                    } 

                    IComponentInitializer init = host.GetDesigner(component) as IComponentInitializer; 
                    if (init != null) { 
                        init.InitializeExistingComponent(null);
                    } 

                    // recurse;
                    AddChildComponents(children[i], container, host);
                } 
            }
        } 
 
        /// 
        ///  
        ///      Disposes this component.
        /// 
        protected override void Dispose(bool disposing) {
 
            if (disposing) {
                // Stop any drag that we are currently processing. 
                OnMouseDragEnd(false); 

                EnableDragDrop(false); 

                if (Control is ScrollableControl) {
                    ((ScrollableControl)Control).Scroll -= new ScrollEventHandler(this.OnScroll);
                } 

                IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); 
                if (host != null) { 
                    componentChangeSvc.ComponentRemoving -= new ComponentEventHandler(this.OnComponentRemoving);
                    componentChangeSvc.ComponentRemoved -= new ComponentEventHandler(this.OnComponentRemoved); 
                    componentChangeSvc = null;
                }

            } 

            base.Dispose(disposing); 
        } 

        ///  
        /// 
        ///     This is called by the parent when the ParentControlDesigner's
        ///     grid/snap settings have changed.  Unless the user has explicitly
        ///     set these values, this designer will just inherit the new ones 
        ///     from the parent.
        ///  
        private void DrawGridOfParentChanged(bool drawGrid) { 
            if (parentCanSetDrawGrid) {
                // If the parent sets us, then treat this as if no one set us 
                bool getDefaultDrawGridTemp = getDefaultDrawGrid;
                DrawGrid = drawGrid;
                parentCanSetDrawGrid = true;
                getDefaultDrawGrid = getDefaultDrawGridTemp; 
            }
        } 
 
        /// 
        ///  
        ///     This is called by the parent when the ParentControlDesigner's
        ///     grid/snap settings have changed.  Unless the user has explicitly
        ///     set these values, this designer will just inherit the new ones
        ///     from the parent. 
        /// 
        private void GridSizeOfParentChanged(Size gridSize) { 
            if (parentCanSetGridSize) { 
                // If the parent sets us, then treat this as if no one set us
                bool getDefaultGridSizeTemp = getDefaultGridSize; 
                GridSize = gridSize;
                parentCanSetGridSize = true;
                getDefaultGridSize = getDefaultGridSizeTemp;
            } 
        }
 
        ///  
        /// 
        ///     This is called by the parent when the ParentControlDesigner's 
        ///     grid/snap settings have changed.  Unless the user has explicitly
        ///     set these values, this designer will just inherit the new ones
        ///     from the parent.
        ///  
        private void GridSnapOfParentChanged(bool gridSnap) {
            if (parentCanSetGridSnap) { 
                // If the parent sets us, then treat this as if no one set us 
                bool getDefaultGridSnapTemp = getDefaultGridSnap;
                SnapToGrid = gridSnap; 
                parentCanSetGridSnap = true;
                getDefaultGridSnap = getDefaultGridSnapTemp;
            }
        } 

        ///  
        ///  
        ///    [To be supplied.]
        ///  
        protected static void InvokeCreateTool(ParentControlDesigner toInvoke, ToolboxItem tool) {
            toInvoke.CreateTool(tool);
        }
 
         /// 
         ///  
        ///     Determines if the this designer can parent to the specified desinger -- 
        ///     generally this means if the control for this designer can parent the
        ///     given ControlDesigner's control. 
        /// 
        public virtual bool CanParent(ControlDesigner controlDesigner) {
            return CanParent(controlDesigner.Control);
        } 

        ///  
        ///  
        ///     Determines if the this designer can parent to the specified desinger --
        ///     generally this means if the control for this designer can parent the 
        ///     given ControlDesigner's control.
        /// 
        public virtual bool CanParent(Control control) {
            return !control.Contains(this.Control); 
        }
 
        ///  
        /// 
        ///      Creates the given tool in the center of the currently selected 
        ///      control.  The default size for the tool is used.
        /// 
        protected void CreateTool(ToolboxItem tool) {
            CreateToolCore(tool, 0, 0, 0, 0, false, false); 
        }
 
        ///  
        /// 
        ///      Creates the given tool in the currently selected control at the 
        ///      given position.  The default size for the tool is used.
        /// 
        protected void CreateTool(ToolboxItem tool, Point location) {
            CreateToolCore(tool, location.X, location.Y, 0, 0, true, false); 
        }
 
        ///  
        /// 
        ///      Creates the given tool in the currently selected control.  The 
        ///      tool is created with the provided shape.
        /// 
        protected void CreateTool(ToolboxItem tool, Rectangle bounds) {
            CreateToolCore(tool, bounds.X, bounds.Y, bounds.Width, bounds.Height, true, true); 
        }
 
 
        /// 
        ///  
        ///      This is the worker method of all CreateTool methods.  It is the only one
        ///      that can be overridden.
        /// 
        protected virtual IComponent[] CreateToolCore(ToolboxItem tool, int x, int y, int width, int height, bool hasLocation, bool hasSize) { 

            IComponent[] comp = null; 
 
            try {
                // We invoke the drag drop handler for this.  This implementation is shared between all designers that 
                // create components.
                //
                comp = GetOleDragHandler().CreateTool(tool, Control, x, y, width, height, hasLocation, hasSize, toolboxSnapDragDropEventArgs);
            } 
            finally {
                //clear the toolboxSnap drag args so we won't provide bad information the next time around 
                toolboxSnapDragDropEventArgs = null; 
            }
 

            return comp;
        }
 
        /// 
        ///  
        ///     Used when draggin a new tool rect on the designer's surface - 
        ///     this will return some generic snaplines Allowing the rect to
        ///     snap to existing control edges on the surface. 
        /// 
        private SnapLine[] GenerateNewToolSnapLines(Rectangle r) {
            return new SnapLine[] {new SnapLine(SnapLineType.Left, r.Right),
                               new SnapLine(SnapLineType.Right, r.Right), 
                               new SnapLine(SnapLineType.Bottom, r.Bottom),
                               new SnapLine(SnapLineType.Top, r.Bottom)}; 
        } 

        ///  
        /// 
        ///     Finds the array of components within the given rectangle.  This uses the rectangle to
        ///     find controls within our control, and then uses those controls to find the actual
        ///     components.  It returns an object array so the output can be directly fed into 
        ///     the selection service.
        ///  
        internal object[] GetComponentsInRect(Rectangle value, bool screenCoords, bool containRect) { 
            ArrayList list = new ArrayList();
            Rectangle rect = screenCoords ? Control.RectangleToClient(value) : value; 

            IContainer container = Component.Site.Container;

            Control control = Control; 
            int controlCount = control.Controls.Count;
 
            for (int i = 0; i < controlCount; i++) { 
                Control child = control.Controls[i];
                Rectangle bounds = child.Bounds; 

                container = DesignerUtils.CheckForNestedContainer(container); // ...necessary to support SplitterPanel components

                if (child.Visible && ((containRect && rect.Contains(bounds)) || (!containRect && bounds.IntersectsWith(rect))) && 
                    child.Site != null && child.Site.Container == container) {
                        list.Add(child); 
                } 
            }
 
            return list.ToArray();
        }

        ///  
        /// 
        /// Returns the control that represents the UI for the given component. 
        ///  
        protected Control GetControl(object component) {
            IComponent comp = component as IComponent; 
            if (comp != null) {
                IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
                if (host != null) {
                    ControlDesigner cd = host.GetDesigner(comp) as ControlDesigner; 
                    if (cd != null) {
                        return cd.Control; 
                    } 
                }
            } 

            return null;
        }
 
        /// 
        ///  
        /// Computes the next default location for a control. It tries to find a spot 
        /// where no other controls are being obscured and the new control has 2 corners
        /// that don't have other controls under them. 
        /// 
        private Rectangle GetControlStackLocation(Rectangle centeredLocation) {

            Control parent = this.Control; 

            int     parentHeight = parent.ClientSize.Height; 
            int     parentWidth = parent.ClientSize.Width; 

            if (centeredLocation.Bottom >= parentHeight || 
                centeredLocation.Right >= parentWidth) {

                centeredLocation.X = DefaultControlLocation.X;
                centeredLocation.Y = DefaultControlLocation.Y; 
            }
 
            return centeredLocation; 
        }
 
        /// 
        /// 
        ///     Retrieves the default dimensions for the given component class.
        ///  
        [SuppressMessage("Microsoft.Performance", "CA1808:AvoidCallsThatBoxValueTypes")]
        private Size GetDefaultSize(IComponent component) { 
 
            Size size = Size.Empty;
            DefaultValueAttribute sizeAttr = null; 

            //Check to see if the control is AutoSized. VSWhidbey #416721
            PropertyDescriptor prop = TypeDescriptor.GetProperties(component)["AutoSize"];
 
            if (prop != null &&
                !(prop.Attributes.Contains(DesignerSerializationVisibilityAttribute.Hidden) || 
                  prop.Attributes.Contains(BrowsableAttribute.No))) { 
                bool autoSize = (bool)prop.GetValue(component);
                if (autoSize) { 
                    prop = TypeDescriptor.GetProperties(component)["PreferredSize"];
                    if (prop != null) {
                        size = (Size)prop.GetValue(component);
                        if (size != Size.Empty) { 
                            return size;
                        } 
                    } 
                }
            } 

            // attempt to get the size property of our component
            //
            prop = TypeDescriptor.GetProperties(component)["Size"]; 

            if (prop != null) { 
 
                // first, let's see if we can get a valid size...
                size = (Size)prop.GetValue(component); 

                // ...if not, we'll see if there's a default size attribute...
                if (size.Width <= 0 || size.Height <= 0) {
                    sizeAttr = (DefaultValueAttribute)prop.Attributes[typeof(DefaultValueAttribute)]; 
                    if (sizeAttr != null) {
                        return((Size)sizeAttr.Value); 
                    } 
                }
                else { 
                    return size;
                }
            }
 
            // Couldn't get the size or a def size attrib, returning 75,23...
            // 
            return(new Size(75, 23)); 
        }
 
        /// 
        /// 
        ///     Returns a 'BodyGlyph' representing the bounds of this control.
        ///     The BodyGlyph is responsible for hit testing the related CtrlDes 
        ///     and forwarding messages directly to the designer.
        ///  
        protected override ControlBodyGlyph GetControlGlyph(GlyphSelectionType selectionType) { 

            OnSetCursor(); 

            Rectangle controlRect = BehaviorService.ControlRectInAdornerWindow(Control);

            Control parent = Control.Parent; 
            IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
 
            if (parent != null && host != null && host.RootComponent != Component) { 

                Rectangle parentRect = BehaviorService.ControlRectInAdornerWindow(parent); 
                Rectangle nonClipRect= Rectangle.Intersect(parentRect, controlRect);

                // If we are not selected...
 
                if (selectionType == GlyphSelectionType.NotSelected) {
                    // If we are partially clipped (not fully clipped or wholly contained) by 
                    // our parent,then adjust the bounds of the glyph to be the "visible" rect. VSWhidbey 530929 
                    if (!nonClipRect.IsEmpty && !parentRect.Contains(controlRect)) {
                        return new ControlBodyGlyph(nonClipRect, Cursor.Current, Control, this); 
                    }

                    // If we are completely clipped, then we do not want to be a drop target at all
                    else if (nonClipRect.IsEmpty) { 
                        return null;
                    } 
                } 

            } 

            return new ControlBodyGlyph(controlRect, Cursor.Current, Control, this);
        }
 

        ///  
        ///  
        ///     Adds our ContainerSelectorGlyph to the selection glyphs.
        ///  
        public override GlyphCollection GetGlyphs(GlyphSelectionType selectionType) {
            GlyphCollection glyphs = base.GetGlyphs(selectionType);

            //only add this glyph if our container is 1) moveable 2) not read-only 
            //AND 3) it is selected .
            if ((SelectionRules & SelectionRules.Moveable) != 0 && 
              InheritanceAttribute != InheritanceAttribute.InheritedReadOnly && selectionType != GlyphSelectionType.NotSelected) { 

                //get the adornerwindow-relative coords for the container control 
                Point loc = BehaviorService.ControlToAdornerWindow((Control)Component);
                Rectangle translatedBounds = new Rectangle(loc, ((Control)Component).Size);

                int glyphOffset = (int)(DesignerUtils.CONTAINERGRABHANDLESIZE * .5); 

                //if the control is too small for our ideal position... 
                if (translatedBounds.Width < 2 * DesignerUtils.CONTAINERGRABHANDLESIZE) { 
                    glyphOffset = -1 * glyphOffset;
                } 

                ContainerSelectorBehavior behavior = new ContainerSelectorBehavior((Control)Component, Component.Site, true);
                ContainerSelectorGlyph containerSelectorGlyph = new ContainerSelectorGlyph(translatedBounds, DesignerUtils.CONTAINERGRABHANDLESIZE, glyphOffset, behavior);
 
                glyphs.Insert(0, containerSelectorGlyph);
            } 
 
            return glyphs;
        } 

        internal OleDragDropHandler GetOleDragHandler() {
            if (oleDragDropHandler == null) {
                oleDragDropHandler = new OleDragDropHandler(null, ( IServiceProvider )GetService(typeof(IDesignerHost)), this); 
            }
            return oleDragDropHandler; 
        } 

        ///  
        /// 
        /// This method return the ParentControlDesigner of the parenting control,
        /// it is used for inheriting the grid size, snap to grid, and draw grid
        /// of parenting controls. 
        /// 
        private ParentControlDesigner GetParentControlDesignerOfParent() { 
            Control parent = Control.Parent; 
            IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
            if (parent != null && host != null) { 
                return (host.GetDesigner(parent) as ParentControlDesigner);
            }
            return null;
        } 

        ///  
        ///  
        ///     Updates the location of the control according to the GridSnap and Size.
        ///     This method simply calls GetUpdatedRect(), then ignores the width and 
        ///     height
        /// 
        private Rectangle GetAdjustedSnapLocation(Rectangle originalRect, Rectangle dragRect) {
            Rectangle adjustedRect = GetUpdatedRect(originalRect, dragRect, true); 

            //now, preserve the width and height that was originally passed in 
            adjustedRect.Width = dragRect.Width; 
            adjustedRect.Height = dragRect.Height;
 
            //we need to keep in mind that if we adjust to the snap, that we could
            //have possibly moved the control's position outside of the display rect.
            //ex: groupbox's display rect.x = 3, but we might snap to 0.
            //so we need to check with the control's designer to make sure this 
            //doesn't happen
            // 
            Point minimumLocation = DefaultControlLocation; 
            if (adjustedRect.X < minimumLocation.X) {
                adjustedRect.X = minimumLocation.X; 
            }
            if (adjustedRect.Y < minimumLocation.Y) {
                adjustedRect.Y = minimumLocation.Y;
            } 

            //here's our rect that has been snapped to grid 
            return adjustedRect; 

        } 


        internal Point GetSnappedPoint(Point pt) {
            Rectangle r = GetUpdatedRect(Rectangle.Empty, new Rectangle(pt.X, pt.Y, 0, 0), false); 
            return new Point(r.X, r.Y);
        } 
 
        internal Rectangle GetSnappedRect(Rectangle originalRect, Rectangle dragRect, bool updateSize) {
            return GetUpdatedRect(originalRect, dragRect, updateSize); 
        }

        /// 
        ///  
        ///     Updates the given rectangle, adjusting it for grid snaps as
        ///     needed. 
        ///  
        protected Rectangle GetUpdatedRect(Rectangle originalRect, Rectangle dragRect, bool updateSize) {
           Rectangle updatedRect = Rectangle.Empty;//the rectangle with updated coords that we will return 

           if (SnapToGrid) {
               Size gridSize = GridSize;
               Point halfGrid = new Point(gridSize.Width/2, gridSize.Height/2); 

               updatedRect = dragRect; 
 
               // Calculate the new x,y coordinates of our rectangle...
               // 
               int dragBottom = dragRect.Y + dragRect.Height;
               int dragRight  = dragRect.X + dragRect.Width;

               updatedRect.X =  originalRect.X; 
               updatedRect.Y =  originalRect.Y;
 
               // decide to snap the start location to grid ... 
               //
               if (dragRect.X != originalRect.X) { 
                   updatedRect.X  = (dragRect.X / gridSize.Width) * gridSize.Width;

                   // Snap the location to the grid point closest to the dragRect location
                   // 
                   if (dragRect.X - updatedRect.X > halfGrid.X) {
                       updatedRect.X += gridSize.Width; 
                   } 
               }
 
               if (dragRect.Y != originalRect.Y) {
                   updatedRect.Y  = (dragRect.Y / gridSize.Height) * gridSize.Height;

                   // Snap the location to the grid point closest to the dragRect location 
                   //
                   if (dragRect.Y - updatedRect.Y > halfGrid.Y) { 
                       updatedRect.Y += gridSize.Height; 
                   }
               } 

               // here, we need to calculate the new size depending on how we snap to the grid ...
               //
               if (updateSize) { 
                    // update the width and the height
                    // 
                    updatedRect.Width = ((dragRect.X + dragRect.Width) / gridSize.Width) * gridSize.Width - updatedRect.X; 
                    updatedRect.Height = ((dragRect.Y + dragRect.Height) / gridSize.Height) * gridSize.Height - updatedRect.Y;
 
                    // ASURT 71552  Added so that if the updated dimnesion is smaller than grid dimension then snap that dimension to
                    // the grid dimension
                    //
                    if (updatedRect.Width < gridSize.Width) 
                        updatedRect.Width = gridSize.Width;
                    if (updatedRect.Height < gridSize.Height) 
                        updatedRect.Height = gridSize.Height; 
               }
           } 
           else {
               updatedRect = dragRect;
           }
 
           return updatedRect;
        } 
 

        ///  
        /// 
        ///     Initializes the designer with the given component.  The designer can
        ///     get the component's site and request services from it in this call.
        ///  
        public override void Initialize(IComponent component) {
            base.Initialize(component); 
 
            if (Control is ScrollableControl) {
                ((ScrollableControl)Control).Scroll += new ScrollEventHandler(this.OnScroll); 
            }

            EnableDragDrop(true);
 
            // Hook load events.  At the end of load, we need to do a scan through all
            // of our child controls to see which ones are being inherited.  We 
            // connect these up. 
            //
            IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); 
            if (host != null) {
                componentChangeSvc = (IComponentChangeService)host.GetService(typeof(IComponentChangeService));
                if (componentChangeSvc != null) {
                    componentChangeSvc.ComponentRemoving += new ComponentEventHandler(this.OnComponentRemoving); 
                    componentChangeSvc.ComponentRemoved += new ComponentEventHandler(this.OnComponentRemoved);
                } 
            } 

            // update the Status Command 
            statusCommandUI = new StatusCommandUI(component.Site);

        }
 
        /// 
        ///  
        ///  
        public override void InitializeNewComponent(IDictionary defaultValues) {
            base.InitializeNewComponent(defaultValues); 

            if (!AllowControlLasso) {
                return;
            } 

            if (defaultValues != null && defaultValues["Size"] != null && defaultValues["Location"] != null && defaultValues["Parent"] != null) { 
                //build our rect that may have covered some child controls 
                Rectangle bounds = new Rectangle((Point)defaultValues["Location"], (Size)defaultValues["Size"]);
 
                //ask the parent to give us the comps within this rect
                IComponent parent = defaultValues["Parent"] as IComponent;
                if (parent == null) {
                    Debug.Fail("Couldn't get the parent instance from 'defaultValues'"); 
                    return;
                } 
 
                IDesignerHost host = GetService(typeof(IDesignerHost)) as IDesignerHost;
                if (host == null) { 
                    Debug.Fail("Failed to IDesignerHost");
                    return;
                }
 
                ParentControlDesigner parentDesigner = host.GetDesigner(parent) as ParentControlDesigner;
                if (parentDesigner == null) { 
                    Debug.Fail("Could not get ParentControlDesigner for " + parent); 
                    return;
                } 

                object[] comps = parentDesigner.GetComponentsInRect(bounds, true, true /* component should be fully contained*/);

                if (comps == null || comps.Length == 0) { 
                    //no comps to re-parent
                    return; 
                } 

                ArrayList selectedControls = new ArrayList(comps); 

                //remove this
                if (selectedControls.Contains(Control)) {
                    selectedControls.Remove(Control); 
                }
 
                //Finally, we have identified that we need to re-parent the lasso'd controls. 
                //We will start a designer transaction, send some changing notifications
                //and swap parents... 
                //
                ReParentControls(Control, selectedControls, SR.GetString(SR.ParentControlDesignerLassoShortcutRedo, Control.Site.Name), host);
            }
        } 

        ///  
        ///  
        ///     Checks if an option has the default value
        ///  
        private bool IsOptionDefault(string optionName, object value) {
            IDesignerOptionService optSvc = (IDesignerOptionService)GetService(typeof(IDesignerOptionService));

            object defaultValue = null; 

            if (optSvc == null) { 
                if (optionName.Equals("ShowGrid")) { 
                    defaultValue = true;
                } 
                else if (optionName.Equals("SnapToGrid")) {
                    defaultValue = true;
                }
                else if (optionName.Equals("GridSize")) { 
                    defaultValue = new Size(8,8);
                } 
            } 
            else {
                defaultValue = DesignerUtils.GetOptionValue(ServiceProvider, optionName); 
            }

            if (defaultValue != null) {
                return defaultValue.Equals(value); 
            }
            else { 
                return value == null; 
            }
        } 


        /// 
        ///  
        /// 
        private void OnComponentRemoving(object sender, ComponentEventArgs e) { 
            Control comp = e.Component as Control; 
            if (comp != null && comp.Parent != null && comp.Parent == Control) {
                pendingRemoveControl = (Control)comp; 
                //We suspend Component Changing Events for bulk operations to avoid unnecessary serialization\deserialization for undo
                // see bug 488115
                if (suspendChanging == 0)
                { 
                    componentChangeSvc.OnComponentChanging(Control, TypeDescriptor.GetProperties(Control)["Controls"]);
                } 
            } 
        }
 
        /// 
        /// 
        /// 
        private void OnComponentRemoved(object sender, ComponentEventArgs e) { 
            if (e.Component == pendingRemoveControl) {
                pendingRemoveControl = null; 
                componentChangeSvc.OnComponentChanged(Control, TypeDescriptor.GetProperties(Control)["Controls"], null, null); 
            }
        } 

        internal void SuspendChangingEvents()
        {
            suspendChanging++; 
            Debug.Assert(suspendChanging > 0, "Unbalanced SuspendChangingEvents\\ResumeChangingEvents");
        } 
 
        internal void ResumeChangingEvents()
        { 

            suspendChanging--;
            Debug.Assert(suspendChanging >= 0, "Unbalanced SuspendChangingEvents\\ResumeChangingEvents");
        } 

        internal void ForceComponentChanging() 
        { 
            componentChangeSvc.OnComponentChanging(Control, TypeDescriptor.GetProperties(Control)["Controls"]);
        } 

        /// 
        /// 
        ///      Called in order to cleanup a drag and drop operation.  Here we 
        ///      cleanup any operations that were performed at the beginning of a drag.
        ///  
        protected override void OnDragComplete(DragEventArgs de) { 
            DropSourceBehavior.BehaviorDataObject data = de.Data as DropSourceBehavior.BehaviorDataObject;
            if (data != null) { 
                data.CleanupDrag();
            }
        }
 
        /// 
        ///  
        ///      Called in response to a drag drop for OLE drag and drop.  Here we 
        ///      drop a toolbox component on our parent control.
        ///  
        // Standard 'catch all - rethrow critical' exception pattern
        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")]
        protected override void OnDragDrop(DragEventArgs de) { 

            //if needed, cache extra info about the behavior dragdrop event 
            //ex: snapline and offset info 
            if (de is ToolboxSnapDragDropEventArgs) {
                this.toolboxSnapDragDropEventArgs = de as ToolboxSnapDragDropEventArgs; 
            }

            DropSourceBehavior.BehaviorDataObject data = de.Data as DropSourceBehavior.BehaviorDataObject;
            if (data != null) { 
                data.Target = Component;
                data.EndDragDrop(AllowSetChildIndexOnDrop); 
 
                OnDragComplete(de);
            } 
            // this should only occur when D&Ding between component trays on two separate forms.
            else if (mouseDragTool == null && data == null) {
                OleDragDropHandler ddh = GetOleDragHandler();
                if (ddh != null) { 
                    IOleDragClient target = ddh.Destination;
                    if (target != null && target.Component != null && target.Component.Site != null) { 
                        IContainer container = target.Component.Site.Container; 
                        if (container != null) {
                            object[] dragComps = ddh.GetDraggingObjects(de); 
                            for (int  i = 0; i < dragComps.Length; i++) {
                                IComponent comp = dragComps[i] as IComponent;
                                container.Add(comp);
                            } 
                        }
                    } 
                } 
            }
 
            if (mouseDragTool != null) {
                IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
                if (host != null) {
                    host.Activate(); 
                }
                try { 
                    //There may be a wizard displaying as a result of CreateTool. 
                    //we do not want the behavior service thinking there he is dragging while this wizard is up
                    //it causes the cursor to constantly flicker to the toolbox cursor. 
                    if (BehaviorService != null) {
                        //this will cause the BehSvc to return from 'drag mode'
                        //
                        BehaviorService.EndDragNotification(); 
                    }
                    CreateTool(mouseDragTool, new Point(de.X, de.Y)); 
                } 
                catch (Exception e) {
                    if (ClientUtils.IsCriticalException(e)) { 
                        throw;
                    }
                    else
                    { 
                        DisplayError(e);
                    } 
                } 
                mouseDragTool = null;
                return; 
            }

        }
 
        /// 
        ///  
        ///      Called in response to a drag enter for OLE drag and drop. 
        /// 
        protected override void OnDragEnter(DragEventArgs de) { 

            // Are we are new target, meaning is the drop target different than the drag source
            bool newTarget = false;
 
            DropSourceBehavior.BehaviorDataObject behDataObject = null;
            DropSourceBehavior.BehaviorDataObject data = de.Data as DropSourceBehavior.BehaviorDataObject; 
            if (data != null) { 
                behDataObject = data;
                behDataObject.Target = Component; 
                de.Effect = (Control.ModifierKeys == Keys.Control) ? DragDropEffects.Copy : DragDropEffects.Move;
                newTarget = !(data.Source.Equals(Component)); //Check if we are moving to a new target
            }
 
            // If tab order UI is being shown, then don't allow anything to be
            // dropped here. 
            // 
            IMenuCommandService ms = (IMenuCommandService)GetService(typeof(IMenuCommandService));
            if (ms != null) { 
                MenuCommand tabCommand = ms.FindCommand(StandardCommands.TabOrder);
                if (tabCommand != null && tabCommand.Checked) {
                    de.Effect = DragDropEffects.None;
                    return; 
                }
            } 
 
            // Get the objects that are being dragged
            // 
            Object[] dragComps = null;

            if (behDataObject != null && behDataObject.DragComponents != null) {
                dragComps = new Object[behDataObject.DragComponents.Count]; 
                behDataObject.DragComponents.CopyTo(dragComps, 0);
            } 
            else { 
                OleDragDropHandler ddh = GetOleDragHandler();
                dragComps = ddh.GetDraggingObjects(de); 
            }

            Control  draggedControl = null;
            object draggedDesigner = null; 

            IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); 
            if (host != null) { 
                DocumentDesigner parentDesigner = host.GetDesigner(host.RootComponent) as DocumentDesigner;
                if (parentDesigner != null) { 
                    if (!parentDesigner.CanDropComponents(de)) {
                        de.Effect = DragDropEffects.None;
                        return;
                    } 
                }
            } 
 
            if (dragComps != null) {
 
                if (data == null) {
                    // This should only be true, when moving a component from the Tray,
                    // to a new form. In this case, we are moving targets.
                    newTarget = true; 
                }
 
                for (int  i = 0; i < dragComps.Length; i++) { 
                    IComponent comp = dragComps[i] as IComponent;
                    if (host == null || comp == null) { 
                        continue;
                    }

                    if (newTarget) { 
                        // If we are dropping on a new target, then check to see if any of the components
                        // are inherited. If so, don't allow them to be moved. 
                        InheritanceAttribute attr = (InheritanceAttribute)TypeDescriptor.GetAttributes(comp)[typeof(InheritanceAttribute)]; 
                        if (attr != null && !attr.Equals(InheritanceAttribute.NotInherited) && !attr.Equals(InheritanceAttribute.InheritedReadOnly)) {
                            de.Effect = DragDropEffects.None; 
                            return;
                        }
                    }
 

                    // try go get the control for the thing that's being dragged 
                    // 
                    draggedDesigner = host.GetDesigner(comp);
 
                    if (draggedDesigner is IOleDragClient) {
                        draggedControl = ((IOleDragClient)this).GetControlForComponent(dragComps[i]);
                    }
 
                    Control ctrl = dragComps[i] as Control;
                    if (draggedControl == null && ctrl != null) { 
                        draggedControl = ctrl; 
                    }
 
                    // oh well, it's not a control so it doesn't matter
                    //
                    if (draggedControl == null) {
                        continue; 
                    }
 
                    // If we're inheriting from a private container, we can't modify the controls collection. 
                    // So drag-drop is only allowed within the container i.e. the dragged controls must already
                    // be parented to this container. 
                    //
                    if (InheritanceAttribute == InheritanceAttribute.InheritedReadOnly && draggedControl.Parent != this.Control) {
                        de.Effect = DragDropEffects.None;
                        return; 
                    }
 
                    //Can the component be dropped on this parent? I.e. you can only 
                    //drop a tab page on a tab control, not say a panel
                    if (!((IOleDragClient)this).IsDropOk(comp)) { 
                        de.Effect = DragDropEffects.None;
                        return;
                    }
                } 

                // should only occur when dragging and dropping 
                // from the component tray. 
                if (data == null) {
                    PerformDragEnter(de, host); 
                }
            }

            if (toolboxService == null) { 
                toolboxService = (IToolboxService)GetService(typeof(IToolboxService));
            } 
 
            // Only assume the items came from the ToolBox if dragComps == null
            // 
            if (toolboxService != null && dragComps == null) {
                mouseDragTool = toolboxService.DeserializeToolboxItem(de.Data, host);

                //If we have a valid toolbox item to drag and 
                //we haven't pushed our behaivor, then do so now...
                if ((mouseDragTool != null) && BehaviorService != null && BehaviorService.UseSnapLines) { 
 
                    //demand create
                    if (toolboxItemSnapLineBehavior == null) { 
                        toolboxItemSnapLineBehavior = new ToolboxItemSnapLineBehavior(Component.Site, BehaviorService, this, AllowGenericDragBox);
                    }

                    if (!toolboxItemSnapLineBehavior.IsPushed) { 
                        BehaviorService.PushBehavior(toolboxItemSnapLineBehavior);
                        toolboxItemSnapLineBehavior.IsPushed = true; 
                    } 
                }
 

                if (mouseDragTool != null) {
                    PerformDragEnter(de, host);
                } 

                // This must be called last. Tell the behavior that we are beginning a drag. 
                // Yeah, this is OnDragEnter, but to the behavior this is as if we are starting a drag. 
                // VSWhidbey 487816
                if (toolboxItemSnapLineBehavior != null) { 
                    toolboxItemSnapLineBehavior.OnBeginDrag();
                }
            }
        } 

        private void PerformDragEnter(DragEventArgs de, IDesignerHost host) { 
            if (host != null) { 
                host.Activate();
            } 

            Debug.Assert(0 != (int)(de.AllowedEffect & (DragDropEffects.Move | DragDropEffects.Copy)), "DragDropEffect.Move | .Copy isn't allowed?");
            if ((int)(de.AllowedEffect & DragDropEffects.Move) != 0) {
                de.Effect = DragDropEffects.Move; 
            }
            else { 
                de.Effect = DragDropEffects.Copy; 
            }
 
            // If we're inheriting from a private container, we can't modify the controls collection.
            if (InheritanceAttribute == InheritanceAttribute.InheritedReadOnly) {
                de.Effect = DragDropEffects.None;
                return; 
            }
 
            // Also, select this parent control to indicate it will be the drop target. 
            //
            ISelectionService sel = (ISelectionService)GetService(typeof(ISelectionService)); 
            if (sel != null) {
                sel.SetSelectedComponents(new object[] {Component}, SelectionTypes.Replace);
            }
        } 

 
        ///  
        /// 
        ///     Called when a drag-drop operation leaves the control designer view 
        ///
        /// 
        protected override void OnDragLeave(EventArgs e) {
 
            //if we're dragging around our generic snapline box - let's remove it here
            if (toolboxItemSnapLineBehavior != null && toolboxItemSnapLineBehavior.IsPushed) { 
                BehaviorService.PopBehavior(toolboxItemSnapLineBehavior); 
                toolboxItemSnapLineBehavior.IsPushed = false;
            } 

            mouseDragTool = null;
        }
 
        /// 
        ///  
        ///     Called when a drag drop object is dragged over the control designer view 
        /// 
        protected override void OnDragOver(DragEventArgs de) { 

            DropSourceBehavior.BehaviorDataObject data = de.Data as DropSourceBehavior.BehaviorDataObject;
            if (data != null) {
                data.Target = Component; 
                de.Effect = (Control.ModifierKeys == Keys.Control) ? DragDropEffects.Copy : DragDropEffects.Move;
            } 
 
            Debug.WriteLineIf(CompModSwitches.DragDrop.TraceInfo, "\tParentControlDesigner.OnDragOver: " + de.ToString());
 
            // If tab order UI is being shown, then don't allow anything to be
            // dropped here.
            //
            IMenuCommandService ms = (IMenuCommandService)GetService(typeof(IMenuCommandService)); 
            if (ms != null) {
                MenuCommand tabCommand = ms.FindCommand(StandardCommands.TabOrder); 
                Debug.Assert(tabCommand != null, "Missing tab order command"); 
                if (tabCommand != null && tabCommand.Checked) {
                    de.Effect = DragDropEffects.None; 
                    return;
                }
            }
 
            IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
            if (host != null) { 
                DocumentDesigner parentDesigner = host.GetDesigner(host.RootComponent) as DocumentDesigner; 
                if (parentDesigner != null) {
                    if (!parentDesigner.CanDropComponents(de)) { 
                        de.Effect = DragDropEffects.None;
                        return;
                    }
                } 
            }
 
            if (mouseDragTool != null) { 
                Debug.Assert(0!=(int)(de.AllowedEffect & DragDropEffects.Copy), "DragDropEffect.Move isn't allowed?");
                de.Effect = DragDropEffects.Copy; 
                return;
            }

            Debug.WriteLineIf(CompModSwitches.DragDrop.TraceInfo, "\tParentControlDesigner.OnDragOver: " + de.ToString()); 
        }
 
 
        /// 
        ///  
        ///     Called in response to the left mouse button being pressed on a
        ///     component.  The designer overrides this to provide a
        ///     "lasso" selection for components within the control.
        ///  

        private static int FrameWidth(FrameStyle style) { 
            return (style == FrameStyle.Dashed ? 1 : 2); 
        }
 
        protected override void OnMouseDragBegin(int x, int y) {
            Control control = Control;

            // Figure out the drag frame style.  We use a dotted line for selecting 
            // a component group, and a thick line for creating a new component.
            // If we are a privately inherited component, then we always use the 
            // selection frame because we can't add components. 
            //
            if (!InheritanceAttribute.Equals(InheritanceAttribute.InheritedReadOnly)) { 
                if (toolboxService == null) {
                    toolboxService = (IToolboxService)GetService(typeof(IToolboxService));
                }
 
                if (toolboxService != null) {
                    mouseDragTool = toolboxService.GetSelectedToolboxItem((IDesignerHost)GetService(typeof(IDesignerHost))); 
                } 
            }
 
            // Set the mouse capture and clipping to this control.
            //
            control.Capture = true;
 
            Rectangle bounds;
            NativeMethods.RECT winRect = new NativeMethods.RECT(); 
            NativeMethods.GetWindowRect(control.Handle, ref winRect); 
            bounds = Rectangle.FromLTRB(winRect.left, winRect.top, winRect.right, winRect.bottom);
 
            mouseDragFrame = (mouseDragTool == null) ? FrameStyle.Dashed : FrameStyle.Thick;

            // Setting this non-null signifies that we are dragging with the
            // mouse. 
            //
            mouseDragBase = new Point(x, y); 
 
            // Select the given object.
            // 
            ISelectionService selsvc = (ISelectionService)GetService(typeof(ISelectionService));

            if (selsvc != null) {
                selsvc.SetSelectedComponents(new object[] {Component}, SelectionTypes.Primary); 
            }
            // Get the event handler service.  We push a handler to handle the escape 
            // key. 
            //
            IEventHandlerService eventSvc = (IEventHandlerService)GetService(typeof(IEventHandlerService)); 
            //


            if (eventSvc != null && escapeHandler == null) { 
                escapeHandler = new EscapeHandler(this);
                eventSvc.PushHandler(escapeHandler); 
            } 

            //Need this since we are drawing the frame in the adorner window 
            adornerWindowToScreenOffset = BehaviorService.AdornerWindowToScreen();
        }

        ///  
        /// 
        ///     Called at the end of a drag operation.  This either commits or rolls back the 
        ///     drag. 
        /// 
        // Standard 'catch all - rethrow critical' exception pattern 
        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")]
        protected override void OnMouseDragEnd(bool cancel) {
 
            // Do nothing if we're not dragging anything around
            // 
            if (mouseDragBase == InvalidPoint) { 
                Debug.Assert(graphics == null);
                // make sure we force the drag end 
                base.OnMouseDragEnd(cancel);
                return;
            }
 
            // Important to null these out here, just in case we throw an exception
            // 
            Rectangle   offset    = mouseDragOffset; 
            ToolboxItem tool      = mouseDragTool;
            Point       baseVar   = mouseDragBase; 

            mouseDragOffset = Rectangle.Empty;
            mouseDragBase = InvalidPoint;
            mouseDragTool = null; 

            Control.Capture = false; 
            Cursor.Clip = Rectangle.Empty; 

            // Clear out the drag frame. 
            if (!offset.IsEmpty && graphics != null) {
                Rectangle frameRect = new Rectangle(offset.X - adornerWindowToScreenOffset.X,
                                                     offset.Y - adornerWindowToScreenOffset.Y,
                                                     offset.Width, offset.Height); 

 
                int frameWidth = FrameWidth(mouseDragFrame); 
                graphics.SetClip(frameRect);
 
                using (Region newRegion = new Region(frameRect)) {
                    newRegion.Exclude(Rectangle.Inflate(frameRect, -frameWidth, -frameWidth));
                    BehaviorService.Invalidate(newRegion);
                } 
                graphics.ResetClip();
            } 
 

            if (graphics != null) { 
                graphics.Dispose();
                graphics = null;
            }
 
            //destroy the snapline engine (if we used it)
            if (dragManager != null) { 
                dragManager.OnMouseUp(); 
                dragManager = null;
            } 

            // Get the event handler service and pop our handler.
            //
            IEventHandlerService eventSvc = (IEventHandlerService)GetService(typeof(IEventHandlerService)); 
            if (eventSvc != null && escapeHandler != null) {
                eventSvc.PopHandler(escapeHandler); 
                escapeHandler = null; 
            }
 
            // Set Status Information - but only if the offset is not empty, if it is, the user didn't move the mouse
            if (statusCommandUI != null && !offset.IsEmpty)
            {
   				NativeMethods.POINT location = new NativeMethods.POINT(baseVar.X, baseVar.Y); 
   				NativeMethods.MapWindowPoints(IntPtr.Zero, Control.Handle, location, 1);
   				if (statusCommandUI != null) 
   				{ 
   					statusCommandUI.SetStatusInformation(new Rectangle(location.x, location.y, offset.Width, offset.Height));
   				} 
            }

            // Quit now if we don't have an offset rect.  This indicates that
            // the user didn't move the mouse. 
            //
            if (offset.IsEmpty && !cancel) { 
                // BUT, if we have a selected tool, create it here 
                if (tool != null) {
                    try { 
                        CreateTool(tool, baseVar);
                        if (toolboxService != null) {
                            toolboxService.SelectedToolboxItemUsed();
                        } 
                    }
                    catch (Exception e) { 
                        if (ClientUtils.IsCriticalException(e)) { 
                            throw;
                        } 
                        else
                        {
                            DisplayError(e);
                        } 
                    }
                } 
                return; 
            }
 
            // Don't do anything else if the user wants to cancel.
            //
            if (cancel) {
                return; 
            }
 
            // If we have a valid toolbox item, create the tool 
            //
            if (tool != null) { 
                try {
                    //avoid allowing the user creating a 1x1 sized control (for ex)
                    //by enforcing a min size 2xMinDragSize...
                    Size minControlSize = new Size(DesignerUtils.MinDragSize.Width * 2, DesignerUtils.MinDragSize.Height * 2); 
                    if (offset.Width < minControlSize.Width) {
                        offset.Width = minControlSize.Width; 
                    } 
                    if (offset.Height < minControlSize.Height) {
                        offset.Height = minControlSize.Height; 
                    }

                    CreateTool(tool, offset);
                    if (toolboxService != null) { 
                        toolboxService.SelectedToolboxItemUsed();
                    } 
                } 
                catch (Exception e) {
                    if (ClientUtils.IsCriticalException(e)) { 
                        throw;
                    }
                    else
                    { 
                        DisplayError(e);
                    } 
                } 

 
            }
            else {
                // Now find the set of controls within this offset and
                // select them. 
                //
                ISelectionService selSvc = null; 
                selSvc = (ISelectionService)GetService(typeof(ISelectionService)); 
                if (selSvc != null) {
                    object[] selection = GetComponentsInRect(offset, true, false /*component does not need to be fully contained*/); 
                    if (selection.Length > 0) {
                        selSvc.SetSelectedComponents(selection);
                    }
                } 
            }
        } 
 

        ///  
        /// 
        ///     Called for each movement of the mouse.  This will check to see if a drag operation
        ///     is in progress.  If so, it will pass the updated drag dimensions on to the selection
        ///     UI service. 
        /// 
        protected override void OnMouseDragMove(int x, int y) { 
            //if we puhsed a snapline behavior during a drag operation - make sure we have popped it 
            //if we're now receiving mouse move messages.
            if (toolboxItemSnapLineBehavior != null && toolboxItemSnapLineBehavior.IsPushed) { 
                BehaviorService.PopBehavior(toolboxItemSnapLineBehavior);
                toolboxItemSnapLineBehavior.IsPushed = false;
            }
 
            // if we're doing an OLE drag, do nothing, or
            // Do nothing if we haven't initiated a drag 
            // 
            if (GetOleDragHandler().Dragging || mouseDragBase == InvalidPoint) {
                return; 
            }

            Rectangle oldFrameRect = mouseDragOffset;
 
            // Calculate the new offset.
            // 
            mouseDragOffset.X = mouseDragBase.X; 
            mouseDragOffset.Y = mouseDragBase.Y;
            mouseDragOffset.Width = x - mouseDragBase.X; 
            mouseDragOffset.Height = y - mouseDragBase.Y;

            //if we have a valid dragtool - then we'll spin up our snapline engine
            //and use it when the user drags a reversible rect -- but only if the 
            //parentcontroldesigner wants to allow Snaplines
 
            if (dragManager == null && ParticipatesWithSnapLines && mouseDragTool != null && BehaviorService.UseSnapLines) { 
                dragManager = new DragAssistanceManager(Component.Site);
            } 

            if (dragManager != null) {
                //here, we build up our new rect (offset by the adorner window)
                //and ask the snapline engine to adjust our coords 
                Rectangle r = new Rectangle(mouseDragBase.X - adornerWindowToScreenOffset.X,
                                       mouseDragBase.Y - adornerWindowToScreenOffset.Y, 
                                       x - mouseDragBase.X, y - mouseDragBase.Y); 
                Point offset = dragManager.OnMouseMove(r, GenerateNewToolSnapLines(r));
                mouseDragOffset.Width += offset.X; 
                mouseDragOffset.Height += offset.Y;
                dragManager.RenderSnapLinesInternal();
            }
 
            if (mouseDragOffset.Width < 0) {
                mouseDragOffset.X += mouseDragOffset.Width; 
                mouseDragOffset.Width = -mouseDragOffset.Width; 
            }
            if (mouseDragOffset.Height < 0) { 
                mouseDragOffset.Y += mouseDragOffset.Height;
                mouseDragOffset.Height = -mouseDragOffset.Height;
            }
 
            // If we're dragging out a new component, update the drag rectangle
            // to use snaps, if they're set. 
            // 
            if (mouseDragTool != null) {
                // To snap properly, we must snap in client coordinates.  So, convert, snap 
                // and re-convert.
                //
                mouseDragOffset = Control.RectangleToClient(mouseDragOffset);
                mouseDragOffset = GetUpdatedRect(Rectangle.Empty, mouseDragOffset, true); 
                mouseDragOffset = Control.RectangleToScreen(mouseDragOffset);
            } 
 
            if (graphics == null) {
                graphics = BehaviorService.AdornerWindowGraphics; 
            }

            // And draw the new drag frame
            if (!mouseDragOffset.IsEmpty && graphics != null) { 
                Rectangle frameRect = new Rectangle(mouseDragOffset.X - adornerWindowToScreenOffset.X,
                                                     mouseDragOffset.Y - adornerWindowToScreenOffset.Y, 
                                                     mouseDragOffset.Width, mouseDragOffset.Height); 

                //graphics.SetClip(frameRect); 

                //draw the new border
                using (Region newRegion = new Region(frameRect)) {
                    int frameWidth = FrameWidth(mouseDragFrame); 
                    newRegion.Exclude(Rectangle.Inflate(frameRect, -frameWidth, -frameWidth));
 
                    //erase the right part of the old frame 
                    if (!oldFrameRect.IsEmpty) {
                        oldFrameRect.X -= adornerWindowToScreenOffset.X; 
                        oldFrameRect.Y -= adornerWindowToScreenOffset.Y;

                        //Let's not try and be smart about invalidating just the part of the old frame
                        //that's not part of the new frame. When I did that (using the commented out 
                        //lines below), you could get serious screen artifacts when dragging fast. I think
                        //this might be because of some bad region forming (bad region, bad), or some missing 
                        //updates. 

                        // Since we invalidate and then immediately redraw, the flicker should be minimal. 
                        using (Region oldRegion = new Region(oldFrameRect)) {
                            oldRegion.Exclude(Rectangle.Inflate(oldFrameRect, -frameWidth, -frameWidth));
                            //oldRegion.Union(newRegion);
                            //oldRegion.Exclude(newRegion); 
                            BehaviorService.Invalidate(oldRegion);
                        } 
                    } 

                    DesignerUtils.DrawFrame(graphics, newRegion, mouseDragFrame, Control.BackColor); 
                }
                //graphics.ResetClip();
            }
 
            // We are looking at the primary control
            if (statusCommandUI != null) 
            { 
 				NativeMethods.POINT offset = new NativeMethods.POINT(mouseDragOffset.X, mouseDragOffset.Y);
				NativeMethods.MapWindowPoints(IntPtr.Zero, Control.Handle, offset, 1); 
				if (statusCommandUI != null)
				{
 					statusCommandUI.SetStatusInformation(new Rectangle(offset.x, offset.y, mouseDragOffset.Width, mouseDragOffset.Height));
				} 
            }
 
 
        }
 

        /// 
        /// 
        ///     Called after our component has finished painting.  Here we draw our grid surface 
        /// 
        protected override void OnPaintAdornments(PaintEventArgs pe) { 
            if (DrawGrid) { 
                Control control = (Control)Control;
 
                Rectangle displayRect = Control.DisplayRectangle;
                Rectangle clientRect = Control.ClientRectangle;

                Rectangle paintRect = new Rectangle( Math.Min(displayRect.X, clientRect.X), Math.Min(displayRect.Y, clientRect.Y), 
                                                     Math.Max(displayRect.Width, clientRect.Width), Math.Max(displayRect.Height, clientRect.Height));
 
                float xlateX = (float)paintRect.X; 
                float xlateY = (float)paintRect.Y;
                pe.Graphics.TranslateTransform(xlateX, xlateY); 
                paintRect.X = paintRect.Y = 0;
                paintRect.Width++; // gpr: FillRectangle with a TextureBrush comes up one pixel short
                paintRect.Height++;
                ControlPaint.DrawGrid(pe.Graphics, paintRect, GridSize, control.BackColor); 
                pe.Graphics.TranslateTransform(-xlateX, -xlateY);
            } 
            base.OnPaintAdornments(pe); 
        }
 
        /// 
        ///     When the control is scrolled, we want to invalidate areas previously covered by glyphs.
        ///     VSWhidbey# 183588.
        ///  
        private void OnScroll(object sender, ScrollEventArgs se) {
 
            BehaviorService.Invalidate(BehaviorService.ControlRectInAdornerWindow(Control)); 

        } 


        /// 
        ///  
        ///     Called each time the cursor needs to be set.  The ParentControlDesigner behavior here
        ///     will set the cursor to one of three things: 
        ///     1.  If the toolbox service has a tool selected, it will allow the toolbox service to 
        ///     set the cursor.
        ///     2.  The arrow will be set.  Parent controls allow dragging within their interior. 
        /// 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        protected override void OnSetCursor() {
            if (toolboxService == null) { 
                toolboxService = (IToolboxService)GetService(typeof(IToolboxService));
            } 
 
            try {
                if (toolboxService == null || !toolboxService.SetCursor() || InheritanceAttribute.Equals(InheritanceAttribute.InheritedReadOnly)) { 
                    Cursor.Current = Cursors.Default;
                }
            }
 
            catch {  // VSWhidbey 502536
                Cursor.Current = Cursors.Default; 
            } 
        }
 
        /// 
        /// 
        ///      Allows a designer to filter the set of properties
        ///      the component it is designing will expose through the 
        ///      TypeDescriptor object.  This method is called
        ///      immediately before its corresponding "Post" method. 
        ///      If you are overriding this method you should call 
        ///      the base implementation before you perform your own
        ///      filtering. 
        /// 
        protected override void PreFilterProperties(IDictionary properties) {
            base.PreFilterProperties(properties);
 
            // add the "GridSize, SnapToGrid and DrawGrid" property  from the property grid
            // iff the LayoutOption.SnapToGrid Attribute is Set... 
 

            if (!DefaultUseSnapLines) { 


                properties["DrawGrid"] = TypeDescriptor.CreateProperty(typeof(ParentControlDesigner), "DrawGrid", typeof(bool),
                                                              BrowsableAttribute.Yes, 
                                                              DesignOnlyAttribute.Yes,
                                                              new SRDescriptionAttribute("ParentControlDesignerDrawGridDescr"), 
                                                              CategoryAttribute.Design); 

                properties["SnapToGrid"] = TypeDescriptor.CreateProperty(typeof(ParentControlDesigner), "SnapToGrid", typeof(bool), 
                                                                BrowsableAttribute.Yes,
                                                                DesignOnlyAttribute.Yes,
                                                                new SRDescriptionAttribute("ParentControlDesignerSnapToGridDescr"),
                                                                CategoryAttribute.Design); 

                properties["GridSize"] = TypeDescriptor.CreateProperty(typeof(ParentControlDesigner), "GridSize", typeof(Size), 
                                                              BrowsableAttribute.Yes, 
                                                              new SRDescriptionAttribute(SR.ParentControlDesignerGridSizeDescr),
                                                              DesignOnlyAttribute.Yes, 
                                                              CategoryAttribute.Design);


            } 

            // We need this one always to make sure that Format -> Horizontal/Vertical Spacing works. 
            properties["CurrentGridSize"] = TypeDescriptor.CreateProperty(typeof(ParentControlDesigner), "CurrentGridSize", typeof(Size), 
                                                             BrowsableAttribute.No,
                                                             DesignerSerializationVisibilityAttribute.Hidden); 
        }

        /// 
        ///  
        ///     Called after we have decided that the user has drawn a control (with a toolbox item picked) onto the designer
        ///     surface and intends to have the controls beneath the new one re-parented.  Example: A user selects the 'Panel' 
        ///     Control in the toolbox then drags a rectangle around four Buttons on the Form's surface.  We'll attempt 
        ///     to re-parent those four Buttons to the newly created Panel.
        ///  
        private void ReParentControls(Control newParent, ArrayList controls, string transactionName, IDesignerHost host) {

            using (DesignerTransaction dt = host.CreateTransaction(transactionName)) {
 
                IComponentChangeService changeSvc = GetService(typeof(IComponentChangeService)) as IComponentChangeService;
 
                PropertyDescriptor controlsProp = TypeDescriptor.GetProperties(newParent)["Controls"]; 
                PropertyDescriptor locationProp = TypeDescriptor.GetProperties(newParent)["Location"];
 
                //get the location of our parent - so we can correctly offset the new lasso'd controls
                //once they are re-parented
                Point parentLoc = Point.Empty;
                if (locationProp != null) { 
                    parentLoc = (Point)locationProp.GetValue(newParent);
                } 
 
                if (changeSvc != null) {
                    changeSvc.OnComponentChanging(newParent, controlsProp); 
                }

                //enumerate the lasso'd controls relocate and re-parent...
                // 
                foreach (object comp in controls) {
                    Control control = comp as Control; 
                    Control oldParent = control.Parent; 
                    Point controlLoc = Point.Empty;
 
                    //do not want to reparent any control that is inherited readonly
                    InheritanceAttribute inheritanceAttribute = (InheritanceAttribute)TypeDescriptor.GetAttributes(control)[typeof(InheritanceAttribute)];
                    if (inheritanceAttribute != null && inheritanceAttribute == InheritanceAttribute.InheritedReadOnly) {
                        continue; 
                    }
 
                    //get the current location of the control 
                    PropertyDescriptor locProp = TypeDescriptor.GetProperties(control)["Location"];
                    if (locProp != null) { 
                        controlLoc = (Point)locProp.GetValue(control);
                    }

                    //fire comp changing on parent and control 
                    if (oldParent != null) {
                        if (changeSvc != null) { 
                            changeSvc.OnComponentChanging(oldParent, controlsProp); 
                        }
                        //remove control from the old parent 
                        oldParent.Controls.Remove(control);
                    }

                    //finally add & relocate the control with the new parent 
                    newParent.Controls.Add(control);
 
                    Point newLoc = Point.Empty; 

                    //this condition will determine which way we need to 'offset' our control location 
                    //based on whether we are moving controls into a child or bringing them out to
                    //a parent
                    if (oldParent != null) {
                        if (oldParent.Controls.Contains(newParent)) { 
                            newLoc = new Point(controlLoc.X - parentLoc.X, controlLoc.Y - parentLoc.Y);
                        } 
                        else { 
                            Point oldParentLoc = (Point)locProp.GetValue(oldParent);
                            newLoc = new Point(controlLoc.X + oldParentLoc.X, controlLoc.Y + oldParentLoc.Y); 
                        }
                    }

                    locProp.SetValue(control, newLoc); 

                    //fire our comp changed events 
                    if (changeSvc != null && oldParent != null) { 
                        changeSvc.OnComponentChanged(oldParent, controlsProp, null, null);
                    } 
                }

                if (changeSvc != null) {
                    changeSvc.OnComponentChanged(newParent, controlsProp, null, null); 
                }
 
                //commit the transaction 
                dt.Commit();
            } 

        }

 
        /// 
        ///  
        ///     Determines if the DrawGrid property should be persisted. 
        /// 
        private bool ShouldSerializeDrawGrid() { 
            //To determine if we need to persist this value, we first need to check
            //if we have a parent who is a parentcontroldesigner, then get their
            //setting...
            // 
            ParentControlDesigner parent = GetParentControlDesignerOfParent();
            if (parent != null) { 
                return !(DrawGrid == parent.DrawGrid); 
            }
            //Otherwise, we'll compare the value to the options page... 
            //
            return !IsOptionDefault("ShowGrid", this.DrawGrid);
        }
 
        /// 
        ///  
        ///     Determines if the SnapToGrid property should be persisted. 
        /// 
        private bool ShouldSerializeSnapToGrid() { 
            //To determine if we need to persist this value, we first need to check
            //if we have a parent who is a parentcontroldesigner, then get their
            //setting...
            // 
            ParentControlDesigner parent = GetParentControlDesignerOfParent();
            if (parent != null) { 
                return !(SnapToGrid == parent.SnapToGrid); 
            }
            //Otherwise, we'll compare the value to the options page... 
            //
            return !IsOptionDefault("SnapToGrid", this.SnapToGrid);
        }
 
        /// 
        ///  
        ///     Determines if the GridSize property should be persisted. 
        /// 
        private bool ShouldSerializeGridSize() { 
            //To determine if we need to persist this value, we first need to check
            //if we have a parent who is a parentcontroldesigner, then get their
            //setting...
            // 
            ParentControlDesigner parent = GetParentControlDesignerOfParent();
            if (parent != null) { 
                return !(GridSize.Equals(parent.GridSize)); 
            }
            //Otherwise, we'll compare the value to the options page... 
            //
            return !IsOptionDefault("GridSize", this.GridSize);
        }
 
        private void ResetGridSize() {
            getDefaultGridSize = true; 
            parentCanSetGridSize = true; 
            //invalidate the control
            Control control = Control; 
            if (control != null) {
                control.Invalidate(true);
            }
        } 

        private void ResetDrawGrid() { 
            getDefaultDrawGrid = true; 
            parentCanSetDrawGrid = true;
            //invalidate the control 
            Control control = Control;
            if (control != null) {
                control.Invalidate(true);
            } 
        }
 
        private void ResetSnapToGrid() { 
            getDefaultGridSnap = true;
            parentCanSetGridSnap = true; 
        }


        ///  
        /// 
        IComponent IOleDragClient.Component { 
            get{ 
                return Component;
            } 
        }

        /// 
        ///  
        /// 
        /// Retrieves the control view instance for the designer that 
        /// is hosting the drag. 
        /// 
        bool IOleDragClient.AddComponent(IComponent component, string name, bool firstAdd) { 
            IContainer container = DesignerUtils.CheckForNestedContainer(Component.Site.Container); // ...necessary to support SplitterPanel components

            bool containerMove = true;
            IContainer oldContainer = null; 
            IDesignerHost localDesignerHost = (IDesignerHost)GetService(typeof(IDesignerHost));
 
            if (!firstAdd) { 

                // just a move, so reparent 
                if (component.Site != null) {

                    oldContainer = component.Site.Container;
 
                    // check if there's already a component by this name in the
                    // get the undo service from the parent were deleteing from 
                    IDesignerHost designerHost = (IDesignerHost)component.Site.GetService(typeof(IDesignerHost)); 

                    containerMove = container != oldContainer; 

                    if (containerMove) {
                        oldContainer.Remove(component);
                    } 
                }
                if (containerMove) { 
 
                    // check if there's already a component by this name in the
                    // container 
                    if (name != null && container.Components[name] != null) {
                        name = null;
                    }
 
                    // add it back
                    if (name != null) { 
                        container.Add(component, name); 
                    }
                    else { 
                        container.Add(component);
                    }
                }
            } 

            // make sure this designer will accept this component -- we wait until 
            // now to be sure the components designer has been created. 
            //
            if (!((IOleDragClient)this).IsDropOk(component)) { 

               try {
                    IUIService uiSvc = (IUIService)GetService(typeof(IUIService));
                    string error = SR.GetString(SR.DesignerCantParentType, component.GetType().Name, Component.GetType().Name); 
                    if (uiSvc != null) {
                        uiSvc.ShowError(error); 
                    } 
                    else {
                        RTLAwareMessageBox.Show(null, error, null, MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, 0); 
                    }
                    return false;
               }
               finally { 
                   if (containerMove) {
                       // move it back. 
                       container.Remove(component); 
                       if (oldContainer != null) {
                           oldContainer.Add(component); 
                       }
                   }
                   else {
                    //there wad no container move ... but then this operation is not supported so 
                    //just remove this component
                    container.Remove(component); 
                   } 
               }
            } 

            // make sure we can handle this thing, otherwise hand it to the base components designer
            //
            Control c = GetControl(component); 

            if (c != null) { 
 
                // set it's handler to this
                Control parent = GetParentForComponent(component); 
                Form form = c as Form;

                if (form == null || !form.TopLevel) {
 
                    if (c.Parent != parent) {
                        PropertyDescriptor controlsProp = TypeDescriptor.GetProperties(parent)["Controls"]; 
                        // we want to insert rather than add it, so we add then move 
                        // to the beginning
 
                        if (c.Parent != null) {
                            Control cParent = c.Parent;
                            if (componentChangeSvc != null) {
                                componentChangeSvc.OnComponentChanging(cParent, controlsProp); 
                            }
                            cParent.Controls.Remove(c); 
                            if (componentChangeSvc != null) { 
                               componentChangeSvc.OnComponentChanged(cParent, controlsProp, cParent.Controls, cParent.Controls);
                            } 
                        }

                        if (suspendChanging == 0 && componentChangeSvc != null)
                        { 
                            componentChangeSvc.OnComponentChanging(parent, controlsProp);
                        } 
                        parent.Controls.Add(c); 
                        // [....] 78059 -- not sure why we need this call. this should move things to the beginning of the
                        // z-order, but do we need that? 
                        //
                        //parent.Controls.SetChildIndex(c, 0);
                        if (componentChangeSvc != null) {
                           componentChangeSvc.OnComponentChanged(parent, controlsProp, parent.Controls, parent.Controls); 
                        }
                    } 
                    else { 
                        // here, we redo the add to make sure the handlers get setup right
                        int childIndex = parent.Controls.GetChildIndex(c); 
                        parent.Controls.Remove(c);
                        parent.Controls.Add(c);
                        parent.Controls.SetChildIndex(c, childIndex);
                    } 
                }
                c.Invalidate(true); 
            } 

            if (localDesignerHost != null && containerMove) { 


                // [....] -- looks like we always want to do this to ensure that sited children get
                // handled properly.  if we respected the boolean before, the ui selection handlers 
                // would cache designers, handlers, etc. and cause problems.
                IComponentInitializer init = localDesignerHost.GetDesigner(component) as IComponentInitializer; 
                if (init != null) { 
                    init.InitializeExistingComponent(null);
                } 

                AddChildComponents(component, container, localDesignerHost);

 
             }
             return true; 
        } 

        ///  
        /// 
        /// 
        /// Checks if the client is read only.  That is, if components can
        /// be added or removed from the designer. 
        /// 
        bool IOleDragClient.CanModifyComponents { 
            get { 
                return(!InheritanceAttribute.Equals(InheritanceAttribute.InheritedReadOnly));
            } 
        }

        /// 
        ///  
        /// 
        /// Checks if it is valid to drop this type of a component on this client. 
        ///  
        bool IOleDragClient.IsDropOk(IComponent component) {
 
            IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));

            if (host != null) {
                IDesigner designer = host.GetDesigner(component); 
                bool disposeDesigner = false;
 
                // we need to create one then 
                if (designer == null) {
                    designer = TypeDescriptor.CreateDesigner(component, typeof(IDesigner)); 
                    ControlDesigner cd = designer as ControlDesigner;
                    if (cd != null) {
                        //Make sure the component doesn't get set to Visible
                        cd.ForceVisible = false; 
                    }
                    designer.Initialize(component); 
                    disposeDesigner = true; 
                }
 
                try {
                   ComponentDesigner cd = designer as ComponentDesigner;
                   if (cd != null) {
                       if (cd.CanBeAssociatedWith(this)) 
                       {
                            ControlDesigner controlDesigner = cd as ControlDesigner; 
                            if (controlDesigner != null) 
                            {
                                return this.CanParent(controlDesigner); 
                            }
                       }
                       else {
                            return false; 
                       }
                   } 
                } 
                finally {
                  if (disposeDesigner) { 
                     designer.Dispose();
                  }
                }
            } 
            return true;
        } 
 
        /// 
        ///  
        /// 
        /// Retrieves the control view instance for the designer that
        /// is hosting the drag.
        ///  
        Control IOleDragClient.GetDesignerControl() {
            return Control; 
        } 

        ///  
        /// 
        /// 
        /// Retrieves the control view instance for the given component.
        /// For Win32 designer, this will often be the component itself. 
        /// 
        Control IOleDragClient.GetControlForComponent(object component) { 
            return GetControl(component); 
        }
 
        /// 
        /// 
        ///      This class overrides the escape command so that we can escape
        ///      out of our private drags. 
        /// 
        private class EscapeHandler : IMenuStatusHandler { 
            private ParentControlDesigner designer; 

            ///  
            /// 
            ///      Creates a new escape handler.
            /// 
            public EscapeHandler(ParentControlDesigner designer) { 
                this.designer = designer;
 
            } 

            ///  
            /// 
            ///     CommandSet will check with this handler on each status update
            ///     to see if the handler wants to override the availability of
            ///     this command. 
            /// 
            public bool OverrideInvoke(MenuCommand cmd) { 
                if (cmd.CommandID.Equals(MenuCommands.KeyCancel)) { 
                    designer.OnMouseDragEnd(true);
                    return true; 
                }

                return false;
            } 

            ///  
            ///  
            ///     CommandSet will check with this handler on each status update
            ///     to see if the handler wants to override the availability of 
            ///     this command.
            /// 
            public bool OverrideStatus(MenuCommand cmd) {
                if (cmd.CommandID.Equals(MenuCommands.KeyCancel)) { 
                    cmd.Enabled = true;
                } 
                else { 
                    cmd.Enabled = false;
                } 

                return true;
            }
        } 

    } 
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK