File: winforms\Managed\System\WinForms\ContainerControl.cs
Project: ndp\fx\src\System.Windows.Forms.csproj (System.Windows.Forms)
//----------------------------------------------------------------------------
// <copyright file="ContainerControl.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
 
/*
 */
namespace System.Windows.Forms {
    using System.Threading;
    using System.Runtime.InteropServices;
    using System.Runtime.Remoting;
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis;
    using System;
    using System.Drawing;
    using System.ComponentModel.Design;
    using System.Windows.Forms.Layout;
    using System.Windows.Forms.Internal;
    using Microsoft.Win32;
    using System.Security;
    using System.Security.Permissions;
 
    /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl"]/*' />
    /// <devdoc>
    ///    <para>Defines a
    ///       base class for
    ///       controls that can parent other controls.</para>
    /// </devdoc>
    [ComVisible(true),
     ClassInterface(ClassInterfaceType.AutoDispatch)
    ]
    public class ContainerControl : ScrollableControl, IContainerControl {
        private Control activeControl; // current active control
        private Control focusedControl; // Current focused control. Do not directly edit this value.
        private Control unvalidatedControl; // The last control that requires validation.  Do not directly edit this value.
        private AutoValidate autoValidate = AutoValidate.Inherit; // Indicates whether automatic validation is turned on.
        private EventHandler autoValidateChanged; // Event fired whenever the AutoValidate property changes.
 
        // Auto scaling property values
        private SizeF autoScaleDimensions = SizeF.Empty;
        private SizeF currentAutoScaleDimensions = SizeF.Empty;
        private AutoScaleMode autoScaleMode = AutoScaleMode.Inherit;
        private BitVector32 state = new BitVector32();
 
        private static readonly int stateScalingNeededOnLayout = BitVector32.CreateMask(); // True if we need to perform scaling when layout resumes
        private static readonly int stateValidating            = BitVector32.CreateMask(stateScalingNeededOnLayout); // Indicates whether we're currently state[stateValidating].
        private static readonly int stateProcessingMnemonic    = BitVector32.CreateMask(stateValidating); // Indicates whether we or one of our children is currently processing a mnemonic.
        private static readonly int stateScalingChild          = BitVector32.CreateMask(stateProcessingMnemonic); // True while we are scaling a child control
        private static readonly int stateParentChanged         = BitVector32.CreateMask(stateScalingChild); // Flagged when a parent changes so we can adpat our scaling logic to match
 
        private static readonly int PropAxContainer            = PropertyStore.CreateKey();
        private const string fontMeasureString                 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.ContainerControl"]/*' />
        /// <devdoc>
        /// <para>Initializes a new instance of the <see cref='System.Windows.Forms.ContainerControl'/>
        /// class.</para>
        /// </devdoc>
        public ContainerControl() : base() {
            SetStyle(ControlStyles.AllPaintingInWmPaint, false);
            
            // this class overrides GetPreferredSizeCore, let Control automatically cache the result
            SetState2(STATE2_USEPREFERREDSIZECACHE, true);  
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.AutoScaleDimensions"]/*' />
        /// <devdoc>
        ///     AutoScaleDimensions represents the DPI or Font setting that the control has been scaled
        ///     to or designed at. Specifically, at design time this property will be set by the
        ///     designer to the value that the developer is designing at. Then, at runtime, when the
        ///     form loads if the CurrentAutoScaleDimensions are different from the AutoScaleDimensions,
        ///     PerformAutoScale will be called and AutoScaleDimensions will be set to the new value to
        ///     match the CurrentAutoScaleDimensions by PerformAutoScale.
        /// </devdoc>
        [Localizable(true)]
        [Browsable(false)]
        [SRCategory(SR.CatLayout)]
        [EditorBrowsable(EditorBrowsableState.Advanced)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public SizeF AutoScaleDimensions {
            get {
                return autoScaleDimensions;
            }
            [
                SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters") // value is the name of the param passed in.
                                                                                                            // So we don't have to localize it.
            ]
            set {
                if (value.Width < 0 || value.Height < 0) {
                    throw new ArgumentOutOfRangeException(SR.GetString(SR.ContainerControlInvalidAutoScaleDimensions), "value");
                }
                autoScaleDimensions = value;
                if (!autoScaleDimensions.IsEmpty) {
                    LayoutScalingNeeded();
                }
            }
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.AutoScaleFactor"]/*' />
        /// <devdoc>
        ///     AutoScaleFactor represents the scaling factor difference between
        ///     CurrentAutoScaleDimensions and AutoScaleDimensions. This value is
        ///     calculated on the fly. Eg: If CurrentAutoScaleDimensions is 192, 192
        ///     and AutoScaleDimensions is 96, 96 then the AutoScaleFactor is 2.0, 2.0
        /// </devdoc>
        protected SizeF AutoScaleFactor {
            get {
                SizeF current = CurrentAutoScaleDimensions;
                SizeF saved = AutoScaleDimensions;
 
                // If no one has configured auto scale dimensions yet, the scaling factor
                // is unity.
                if (saved.IsEmpty) {
                    return new SizeF(1.0F, 1.0F);
                }
 
                return new SizeF(current.Width / saved.Width, current.Height / saved.Height);
            }
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.AutoScaleMode"]/*' />
        /// <devdoc>
        ///     Determines the scaling mode of this control.  The default is no scaling.
        ///
        ///     Scaling by Font is useful if you wish to have a control
        ///     or form stretch or shrink according to the size of the fonts in the system, and should
        ///     be used when the control or form's size itself does not matter.
        ///
        ///     Scaling by DPI is useful when you wish to keep a control or form a specific size
        ///     independent of font.  for example, a control displaying a chart or other graphic
        ///     may want to use DPI scaling to increase in size to account for higher DPI monitors.
        /// </devdoc>
        [SRCategory(SR.CatLayout)]
        [SRDescription(SR.ContainerControlAutoScaleModeDescr)]
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Advanced)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public AutoScaleMode AutoScaleMode {
            get {
                return autoScaleMode;
            }
            set {
                //valid values are 0x0 to 0x3
                if (!ClientUtils.IsEnumValid(value, (int)value, (int)AutoScaleMode.None, (int)AutoScaleMode.Inherit)){
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(AutoScaleMode));
                }
 
                bool scalingNeeded = false;
 
                if (value != autoScaleMode) {
                    
                    // Invalidate any current scaling factors.  If we
                    // are changing AutoScaleMode to anything other than
                    // its default, we should clear out autoScaleDimensions as it is
                    // nonsensical.
                    if (autoScaleMode != AutoScaleMode.Inherit) {
                        autoScaleDimensions = SizeF.Empty;
                    }
 
                    currentAutoScaleDimensions = SizeF.Empty;
                    autoScaleMode = value;
                    scalingNeeded = true;
                }
 
                OnAutoScaleModeChanged();
 
                if (scalingNeeded) {
                    LayoutScalingNeeded();
                }
            }
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.AutoValidate"]/*' />
        /// <devdoc>
        ///     Indicates whether controls in this container will be automatically validated when the focus changes.
        /// </devdoc>
        [
        Browsable(false),
        EditorBrowsable(EditorBrowsableState.Never),
        AmbientValue(AutoValidate.Inherit),
        SRCategory(SR.CatBehavior),
        SRDescription(SR.ContainerControlAutoValidate),
        ]
        public virtual AutoValidate AutoValidate {
            get {
                if (autoValidate == AutoValidate.Inherit) {
                    return GetAutoValidateForControl(this);
                }
                else {
                    return autoValidate;
                }
            }
            set {
                // PERF/FXCop: dont use Enum.IsDefined.
                switch (value) { 
                    case AutoValidate.Disable:
                    case AutoValidate.EnablePreventFocusChange:
                    case AutoValidate.EnableAllowFocusChange:
                    case AutoValidate.Inherit:
                        break;
                    default:
                        throw new InvalidEnumArgumentException("AutoValidate", (int) value, typeof(AutoValidate));
                }
 
                if (autoValidate != value) {
                    autoValidate = value;
                    OnAutoValidateChanged(EventArgs.Empty);
                }
            }
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.AutoValidateChanged"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        [
        Browsable(false),
        EditorBrowsable(EditorBrowsableState.Never),
        SRCategory(SR.CatPropertyChanged),
        SRDescription(SR.ContainerControlOnAutoValidateChangedDescr),
        ]
        public event EventHandler AutoValidateChanged {
            add {
                this.autoValidateChanged += value;
            }
            remove {
                this.autoValidateChanged -= value;
            }
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.BindingContext"]/*' />
        /// <internalonly/>
        /// <devdoc>
        ///    <para>
        ///       The binding manager for the container control.
        ///    </para>
        /// </devdoc>
        [
        Browsable(false),
        SRDescription(SR.ContainerControlBindingContextDescr)
        ]
        public override BindingContext BindingContext {
            get {
                BindingContext bm = base.BindingContext;
                if (bm == null) {
                    bm = new BindingContext();
                    BindingContext = bm;
                }
                return bm;
            }
            set {
                base.BindingContext = value;
            }
        }
 
        /// <devdoc>
        ///     Container controls support ImeMode only to allow child controls to inherit it from their parents.
        /// </devdoc>
        protected override bool CanEnableIme {
            get {
                // Note: If overriding this property make sure to copy the Debug code and call this method.
 
                Debug.Indent();
                Debug.WriteLineIf( CompModSwitches.ImeMode.Level >= TraceLevel.Info, "Inside get_CanEnableIme(), value = false" + ", this = " + this );
                Debug.Unindent();
 
                return false;
            }
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.ActiveControl"]/*' />
        /// <devdoc>
        ///    <para>Indicates the current active control on the container control.</para>
        /// </devdoc>
        [
        SRCategory(SR.CatBehavior),
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        SRDescription(SR.ContainerControlActiveControlDescr)
        ]
        public Control ActiveControl {
            get {
                return activeControl;
            }
 
            set {
                SetActiveControl(value);
            }
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.CreateParams"]/*' />
        protected override CreateParams CreateParams {
            [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
            get {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= NativeMethods.WS_EX_CONTROLPARENT;
                return cp;
            }
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.CurrentAutoScaleDimensions"]/*' />
        /// <devdoc>
        ///     CurrentAutoScaleDimensions represent the actual DPI or Font settings
        ///     of the display at runtime. If the AutoScaleMode is set to ‘None’ then
        ///     the CurrentAutoScaleDimensions is equal to the ActualScaleDimensions
        /// </devdoc>
        [Browsable(false)]
        [SRCategory(SR.CatLayout)]
        [EditorBrowsable(EditorBrowsableState.Advanced)]
        public SizeF CurrentAutoScaleDimensions {
            get {
                if (currentAutoScaleDimensions.IsEmpty) {
                    switch (AutoScaleMode) {
                        case AutoScaleMode.Font:
                            currentAutoScaleDimensions = GetFontAutoScaleDimensions();
                            break;
 
                        case AutoScaleMode.Dpi:
                            // Screen Dpi
                            if (DpiHelper.EnableDpiChangedMessageHandling) {
                                currentAutoScaleDimensions = new SizeF((float)deviceDpi, (float)deviceDpi);
                            } 
                            else {
                                // this DPI value comes from the primary monitor.
                                currentAutoScaleDimensions = WindowsGraphicsCacheManager.MeasurementGraphics.DeviceContext.Dpi;
                            }
                            break;
 
                        default:
                            currentAutoScaleDimensions = AutoScaleDimensions;
                            break;
                    }
                }
 
                return currentAutoScaleDimensions;
            }
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.ParentForm"]/*' />
        /// <devdoc>
        ///    <para>Indicates the form that the scrollable control is assigned to. This property is read-only.</para>
        /// </devdoc>
        [
        SRCategory(SR.CatAppearance),
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        SRDescription(SR.ContainerControlParentFormDescr)
        ]
        public Form ParentForm {
            get {
                Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "GetParent Demanded");
                IntSecurity.GetParent.Demand();
                return ParentFormInternal;
            }
        }
 
        internal Form ParentFormInternal {
            get {
                if (ParentInternal != null) {
                    return ParentInternal.FindFormInternal();
                }
                else {
                    if (this is Form) {
                        return null;
                    }
 
                    return FindFormInternal();
                }
            }
        }
 
        // Package scope for Control
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.IContainerControl.ActivateControl"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// <para>Activates the specified control.</para>
        /// </devdoc>
        bool IContainerControl.ActivateControl(Control control) {
            Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "ModifyFocus Demanded");
            IntSecurity.ModifyFocus.Demand();
 
            return ActivateControlInternal(control, true);
        }
 
        internal bool ActivateControlInternal(Control control) {
            return ActivateControlInternal(control, true);
        }
 
        internal bool ActivateControlInternal(Control control, bool originator) {
            Debug.WriteLineIf(Control.FocusTracing.TraceVerbose, "ContainerControl::ActivateControlInternal(" + (control == null ? "null" : control.Name) + "," + originator.ToString() + ") - " + this.Name);
            // Recursive function that makes sure that the chain of active controls
            // is coherent.
            bool ret = true;
            bool updateContainerActiveControl = false;
            ContainerControl cc = null;
            Control parent = this.ParentInternal;
            if (parent != null)
            {
                cc = (parent.GetContainerControlInternal()) as ContainerControl;
                if (cc != null)
                {
                    updateContainerActiveControl = (cc.ActiveControl != this);
                }
            }
            if (control != activeControl || updateContainerActiveControl)
            {
                if (updateContainerActiveControl)
                {
                    if (!cc.ActivateControlInternal(this, false))
                    {
                        return false;
                    }
                }
                ret = AssignActiveControlInternal((control == this) ? null : control);
            }
 
            if (originator) {
                ScrollActiveControlIntoView();
            }
            return ret;
        }
 
        /// <internalonly/>
        /// <devdoc>
        ///     Used for UserControls - checks if the control
        ///     has a focusable control inside or not
        /// </devdoc>
        internal bool HasFocusableChild()
        {
            Control ctl = null;
            do {
                ctl = GetNextControl(ctl, true);
                if (ctl != null &&
                    ctl.CanSelect &&
                    ctl.TabStop)
                {
                    break;
                }
            } while (ctl != null);
            return ctl != null;
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.AdjustFormScrollbars"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// </devdoc>
        [EditorBrowsable(EditorBrowsableState.Advanced)]
        protected override void AdjustFormScrollbars(bool displayScrollbars) {
            base.AdjustFormScrollbars(displayScrollbars);
 
            if (!GetScrollState(ScrollStateUserHasScrolled)) {
                ScrollActiveControlIntoView();
            }
        }
 
        /// <devdoc>
        ///     Cleans up form state after a control has been removed.
        ///     Package scope for Control
        /// </devdoc>
        /// <internalonly/>
        internal virtual void AfterControlRemoved(Control control, Control oldParent) {
            ContainerControl cc;
            Debug.Assert(control != null);
            Debug.WriteLineIf(Control.FocusTracing.TraceVerbose, "ContainerControl::AfterControlRemoved(" + control.Name + ") - " + this.Name);
            if (control == activeControl || control.Contains(activeControl)) {
                bool selected;
                // SECREVIEW : Note that a function overriding "protected virtual void Control::Select(bool directed, bool forward)"
                //             called by SelectNextControl will be able to set the focus to any control.
                //             This is also enabled by the ModifyFocus.Assert inside Control::SelectNextIfFocused.
                IntSecurity.ModifyFocus.Assert ();
                try
                {
                    selected = SelectNextControl(control, true, true, true, true);
                }
                finally
                {
                    CodeAccessPermission.RevertAssert ();
                }
                if (selected && this.activeControl != control)
                {
                    // Bug 847648.
                    // Add the check. If it is set to true, do not call into FocusActiveControlInternal().
                    // The TOP MDI window could be gone and CreateHandle method will fail 
                    // because it try to create a parking window Parent for the MDI children 
                    if (!this.activeControl.Parent.IsTopMdiWindowClosing) 
                    {                 
                        FocusActiveControlInternal();
                    }
                }
                else
                {
                    SetActiveControlInternal(null);
                }
            }
            else if (activeControl == null && ParentInternal != null)
            {
                // The last control of an active container was removed. Focus needs to be given to the next
                // control in the Form.
                cc = ParentInternal.GetContainerControlInternal() as ContainerControl;
                if (cc != null && cc.ActiveControl == this)
                {
                    Form f = FindFormInternal();
                    if (f != null)
                    {
                        // SECREVIEW : Same comment as above.
                        IntSecurity.ModifyFocus.Assert ();
                        try
                        {
                            f.SelectNextControl(this, true, true, true, true);
                        }
                        finally
                        {
                            CodeAccessPermission.RevertAssert();
                        }
                    }
                }
            }
 
            // VSWhidbey#262686: Two controls in UserControls that don't take focus via UI can have bad behavior if ...
            // VSWhidbey#537131: 
            // When a control is removed from a container, not only do we need to clear the unvalidatedControl of that 
            // container potentially, but the unvalidatedControl of all its container parents, up the chain, needs to
            // now point to the old parent of the disappearing control.
            cc = this;
            while (cc != null) {
                Control parent = cc.ParentInternal;
                if (parent == null) {
                    break;
                }
                else {
                    cc = parent.GetContainerControlInternal() as ContainerControl;
                }
                if (cc != null &&
                    cc.unvalidatedControl != null &&
                    (cc.unvalidatedControl == control || control.Contains(cc.unvalidatedControl)))
                {
                    cc.unvalidatedControl = oldParent;
                }
            }
 
            if (control == unvalidatedControl || control.Contains(unvalidatedControl)) {
                unvalidatedControl = null;
            }
        }
 
        private bool AssignActiveControlInternal(Control value) {
#if DEBUG            
            if (value == null || (value != null && value.ParentInternal != null && !value.ParentInternal.IsContainerControl))
            {
                Debug.Assert(value == null || (value.ParentInternal != null && this == value.ParentInternal.GetContainerControlInternal()));
            }
#endif
                
            Debug.WriteLineIf(Control.FocusTracing.TraceVerbose, "ContainerControl::AssignActiveControlInternal(" + (value == null ? "null" : value.Name) + ") - " + this.Name);
            if (activeControl != value) {
                // cpb: #7318
#if FALSE
                if (activeControl != null) {
                    AxHost.Container cont = FindAxContainer();
                    if (cont != null) {
                        cont.OnOldActiveControl(activeControl, value);
                    }
                }
#endif
                try {
                    if (value != null) {
                        value.BecomingActiveControl = true;
                    }
                    activeControl = value;
                    UpdateFocusedControl();
                }
                finally {
                    if (value != null) {
                        value.BecomingActiveControl = false;
                    }
                }
                if (activeControl == value) {
                    // cpb: #7318
#if FALSE
                    AxHost.Container cont = FindAxContainer();
                    if (cont != null) {
                        cont.OnNewActiveControl(value);
                    }
#endif
                    Form form = FindFormInternal();
                    if (form != null)
                    {
                        form.UpdateDefaultButton();
                    }
                }
            }
            else {
                focusedControl = activeControl;
            }
            return(activeControl == value);
        }
 
        /// <devdoc>
        ///     Used to notify the AxContainer that the form
        ///     has been created.  This should only be called if
        ///     there is an AX container.
        /// </devdoc>
        private void AxContainerFormCreated() {
            ((AxHost.AxContainer)Properties.GetObject(PropAxContainer)).FormCreated();
        }
 
        /// <devdoc>
        ///     Specifies whether this control can process the mnemonic or not.
        /// </devdoc>
        internal override bool CanProcessMnemonic() {
#if DEBUG
            TraceCanProcessMnemonic();
#endif
            if( this.state[stateProcessingMnemonic]){
                return true;
            }
 
            return base.CanProcessMnemonic();
        }
 
        internal AxHost.AxContainer CreateAxContainer() {
            object aXContainer = Properties.GetObject(PropAxContainer);
            if (aXContainer == null) {
                aXContainer = new AxHost.AxContainer(this);
                Properties.SetObject(PropAxContainer, aXContainer);
            }
            return(AxHost.AxContainer)aXContainer;
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.Dispose"]/*' />
        /// <devdoc>
        ///    <para>Disposes of the resources (other than memory) used by
        ///       the <see cref='System.Windows.Forms.ContainerControl'/>
        ///       .</para>
        /// </devdoc>
        protected override void Dispose(bool disposing) {
            if (disposing) {
                activeControl = null;
            }
            
            base.Dispose(disposing);
 
            focusedControl = null;
            unvalidatedControl = null;
        }
 
        /// <devdoc>
        ///     Recursively enables required scaling from the given control
        /// </devdoc>
        private void EnableRequiredScaling(Control start, bool enable) {
            start.RequiredScalingEnabled = enable;
            foreach(Control c in start.Controls) {
                EnableRequiredScaling(c, enable);
            }
        }
 
        /// <devdoc>
        ///     Assigns focus to the activeControl. If there is no activeControl then
        ///     focus is given to the form.
        ///     package scope for Form
        /// </devdoc>
        internal void FocusActiveControlInternal() {
            Debug.WriteLineIf(Control.FocusTracing.TraceVerbose, "ContainerControl::FocusActiveControlInternal() - " + this.Name);
#if DEBUG
            // Things really get ugly if you try to pop up an assert dialog here
            if (activeControl != null && !this.Contains(activeControl))
                Debug.WriteLine("ActiveControl is not a child of this ContainerControl");
#endif
 
            if (activeControl != null && activeControl.Visible) {
 
                // Avoid focus loops, especially with ComboBoxes, on Win98/ME.
                //
                IntPtr focusHandle = UnsafeNativeMethods.GetFocus();
                if (focusHandle == IntPtr.Zero || Control.FromChildHandleInternal(focusHandle) != activeControl) {
                    UnsafeNativeMethods.SetFocus(new HandleRef(activeControl, activeControl.Handle));
                }
            }
            else {
                // Determine and focus closest visible parent
                ContainerControl cc = this;
                while (cc != null && !cc.Visible)
                {
                    Control parent = cc.ParentInternal;
                    if (parent != null)
                    {
                        cc = parent.GetContainerControlInternal() as ContainerControl;
                    }
                    else {
                        break;
                    }
                }
                if (cc != null && cc.Visible)
                {
                    UnsafeNativeMethods.SetFocus(new HandleRef(cc, cc.Handle));
                }
            }
        }
 
 
        internal override Size GetPreferredSizeCore(Size proposedSize) {
            // Translating 0,0 from ClientSize to actual Size tells us how much space
            // is required for the borders.
            Size borderSize = SizeFromClientSize(Size.Empty);
            Size totalPadding = borderSize + Padding.Size;
            return LayoutEngine.GetPreferredSize(this, proposedSize - totalPadding) + totalPadding;
        }
 
        internal override Rectangle GetToolNativeScreenRectangle() {
            if (this.GetTopLevel()) {
                // Get window's client rectangle (i.e. without chrome) expressed in screen coordinates
                NativeMethods.RECT clientRectangle = new NativeMethods.RECT();
                UnsafeNativeMethods.GetClientRect(new HandleRef(this, this.Handle), ref clientRectangle);
                NativeMethods.POINT topLeftPoint = new NativeMethods.POINT(0, 0);
                UnsafeNativeMethods.ClientToScreen(new HandleRef(this, this.Handle), topLeftPoint);
                return new Rectangle(topLeftPoint.x, topLeftPoint.y, clientRectangle.right, clientRectangle.bottom);
            }
            else {
                return base.GetToolNativeScreenRectangle();
            }
        }
 
        /// <devdoc>
        ///     This method calcuates the auto scale dimensions based on the
        ///     control's current font.
        /// </devdoc>
        [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")] // Refers to 'fontMeasureString'.
        [SuppressMessage("Microsoft.Usage", "CA2204:LiteralsShouldBeSpelledCorrectly")]
        private SizeF GetFontAutoScaleDimensions() 
        {
            SizeF retval = SizeF.Empty;
 
            // Windows uses CreateCompatibleDC(NULL) to get a
            // memory DC for the monitor the application is currently
            // on.
            IntPtr dc = UnsafeNativeMethods.CreateCompatibleDC(NativeMethods.NullHandleRef);
            if (dc == IntPtr.Zero) {
                throw new Win32Exception();
            }
 
            HandleRef hdc = new HandleRef(this, dc);
 
            try {
                // We clone the Windows scaling function here as closely as
                // possible.  They use textmetric for height, and textmetric
                // for width of fixed width fonts.  For variable width fonts
                // they use GetTextExtentPoint32 and pass in a long a-Z string.
                // We must do the same here if our dialogs are to scale in a
                // similar fashion.
 
                HandleRef hfont = new HandleRef(this, FontHandle);
                HandleRef hfontOld = new HandleRef(this, SafeNativeMethods.SelectObject(hdc, hfont));
 
                try {
                    NativeMethods.TEXTMETRIC tm = new NativeMethods.TEXTMETRIC();
                    SafeNativeMethods.GetTextMetrics(hdc, ref tm);
 
                    retval.Height = tm.tmHeight;
 
                    if ((tm.tmPitchAndFamily & NativeMethods.TMPF_FIXED_PITCH) != 0) {
                        IntNativeMethods.SIZE size = new IntNativeMethods.SIZE();
                        IntUnsafeNativeMethods.GetTextExtentPoint32(hdc, fontMeasureString, size);
                        // Note: intentional integer round off here for Win32 compat
                        //retval.Width = (float)(((size.cx / 26) + 1) / 2);
                        retval.Width = (int)Math.Round(((float)size.cx) / ((float)fontMeasureString.Length));
                    }
                    else {
                        retval.Width = tm.tmAveCharWidth;
                    }
                }
                finally {
                    SafeNativeMethods.SelectObject(hdc, hfontOld);
                }
            }
            finally {
                UnsafeNativeMethods.DeleteCompatibleDC(hdc);
            }
 
            return retval;
        }
 
        /// <devdoc>
        ///     This method is called when one of the auto scale properties changes, indicating
        ///     that we should scale controls on the next layout.
        /// </devdoc>
        private void LayoutScalingNeeded() {
 
            EnableRequiredScaling(this, true);
            state[stateScalingNeededOnLayout] = true;
 
            // If layout is not currently suspended, then perform a layout now,
            // as otherwise we don't know when one will happen.
            if (!IsLayoutSuspended) {
                LayoutTransaction.DoLayout(this, this, PropertyNames.Bounds);
            }
        }
 
        /// <devdoc>
        ///     to maintain backwards compat with AutoScale on form, we need to keep the
        ///     two models from conflicting.  This method is only here for Form to override
        ///     it and update its AutoScale property appropriately.
        /// </devdoc>
        internal virtual void OnAutoScaleModeChanged() {
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="Binding.OnAutoValidateChanged"]/*' />
        /// <devdoc>
        ///    Raises the AutoValidateChanged event.
        /// </devdoc>
        protected virtual void OnAutoValidateChanged(EventArgs e) {
            if (autoValidateChanged != null) {
                autoValidateChanged(this, e);
            }
        }
 
        // Refer VsWhidbey : 515910 & 269769
        internal override void OnFrameWindowActivate(bool fActivate) {
          if (fActivate) {
              IntSecurity.ModifyFocus.Assert();
              try {
                  if (ActiveControl == null) {
                      SelectNextControl(null, true, true, true, false);
                  }
                  InnerMostActiveContainerControl.FocusActiveControlInternal();
              }
              finally {
                  CodeAccessPermission.RevertAssert();
              }
          }
      }
 
        /// <include file='doc\Control.uex' path='docs/doc[@for="ContainerControl.OnChildLayoutResuming"]/*' />
        /// <devdoc>
        ///     Called when a child is about to resume its layout.  The default implementation
        ///     calls OnChildLayoutResuming on the parent.
        /// </devdoc>
        internal override void OnChildLayoutResuming(Control child, bool performLayout) {
            base.OnChildLayoutResuming(child, performLayout);
 
            // do not scale children if AutoScaleMode is set to Dpi
            if (DpiHelper.EnableSinglePassScalingOfDpiForms && (AutoScaleMode == AutoScaleMode.Dpi)) {
                return;
            }
            
            // We need to scale children before their layout engines get to them.
            // We don't have a lot of opportunity for that because the code
            // generator always generates a PerformLayout() right after a
            // ResumeLayout(false).  This seems to be the most oppportune place
            // for thiis, although it is unfortunate.
            if (!state[stateScalingChild] && !performLayout && AutoScaleMode != AutoScaleMode.None && AutoScaleMode != AutoScaleMode.Inherit && state[stateScalingNeededOnLayout]) {
                state[stateScalingChild] = true;
                try {
                    child.Scale(AutoScaleFactor, SizeF.Empty, this);
                }
                finally {
                    state[stateScalingChild] = false;
                }
            }
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.OnCreateControl"]/*' />
        /// <devdoc>
        ///    <para> Raises the CreateControl event.</para>
        /// </devdoc>
        protected override void OnCreateControl() {
            base.OnCreateControl();
 
            if (Properties.GetObject(PropAxContainer) != null) {
                AxContainerFormCreated();
            }
            OnBindingContextChanged(EventArgs.Empty);
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.OnFontChanged"]/*' />
        /// <devdoc>
        ///    We override this to clear the current autoscale cache.
        /// </devdoc>
        [EditorBrowsable(EditorBrowsableState.Advanced)]
        protected override void OnFontChanged(EventArgs e) {
            if (AutoScaleMode == AutoScaleMode.Font) {
                currentAutoScaleDimensions = SizeF.Empty;
 
                // If the font changes and we are going to autoscale
                // as a result, do it now, and wrap the entire
                // transaction in a suspend layout to prevent
                // the layout engines from conflicting with our
                // work.
                SuspendAllLayout(this);
 
                try {
                    PerformAutoScale(!RequiredScalingEnabled, true);
                }
                finally {
                    ResumeAllLayout(this, false);
                }
            }
 
            base.OnFontChanged(e);
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.FormDpiChanged"]/*' />
        /// <devdoc>
        ///   This is called by the top level form to clear the current autoscale cache.
        /// </devdoc>
        internal void FormDpiChanged(float factor) {
            Debug.Assert(this is Form);
 
            currentAutoScaleDimensions = SizeF.Empty;
 
            SuspendAllLayout(this);
            SizeF factorSize = new SizeF(factor, factor);
            try {
                ScaleChildControls(factorSize, factorSize, this, true);
            }
            finally {
                ResumeAllLayout(this, false);
            }
        }
 
        /// <devdoc>
        ///     Container controls scale during layout.
        /// </devdoc>
        protected override void OnLayout(LayoutEventArgs e) {
            PerformNeededAutoScaleOnLayout();
            base.OnLayout(e);
        }
 
        /// <include file='doc\Control.uex' path='docs/doc[@for="ContainerControl.OnLayoutResuming"]/*' />
        /// <devdoc>
        ///     Called when the last resume layout call is made.  If performLayout is true
        ///     a layout will occur as soon as this call returns.  Layout is
        ///     still suspended when this call is made.  The default implementation
        ///     calls OnChildLayoutResuming on the parent, if it exists.
        /// </devdoc>
        internal override void OnLayoutResuming(bool performLayout) {
            PerformNeededAutoScaleOnLayout();
            base.OnLayoutResuming(performLayout);
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.OnParentChanged"]/*' />
        /// <devdoc>
        ///     Called when the parent changes.  Container controls prefer to have their parents
        ///     scale themselves, but when a parent is first changed, and as a result the font
        ///     changes as well, a container control should scale itself.  We save off this state
        ///     so a later font change can trigger a scale of us.  We only set this state if
        ///     required scaling is disabled:  if it is enabled we are still initializing and
        ///     parent changes are normal.
        /// </devdoc>
        protected override void OnParentChanged(EventArgs e) {
            state[stateParentChanged] = !RequiredScalingEnabled;
            base.OnParentChanged(e);
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.PerformAutoScale"]/*' />
        /// <devdoc>
        ///     Performs scaling of this control.  Scaling works by scaling all children of this control.
        ///     Those children that are ContainerControls will have their PerformAutoScale method called
        ///     so they can scale their children.
        /// </devdoc>
        public void PerformAutoScale() {
            PerformAutoScale(true, true);
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.PerformAutoScale1"]/*' />
        /// <devdoc>
        ///     Performs scaling of this control.  Scaling works by scaling all children of this control.
        ///
        ///     If includedBounds is true those controls whose bounds have changed since
        ///     they were last scaled will be auto scaled.  If excludedBounds is true those
        ///     controls whose bounds have not changed since they were last scaled will be
        ///     auto scaled.
        ///
        ///     PerformAutoScale is automatically called during OnLayout.  The parameters to
        ///     PerformAutoScale are passed as follows:
        ///
        ///     1.  If AutoScaleDimensions are set, includedBounds is set to true.
        ///     2.  If a font change occurred, excludedBounds is set to true.
        /// </devdoc>
        private void PerformAutoScale(bool includedBounds, bool excludedBounds) {
 
            bool suspended = false;
 
            try {
                if (AutoScaleMode != AutoScaleMode.None && AutoScaleMode != AutoScaleMode.Inherit) {
                    SuspendAllLayout(this);
                    suspended = true;
 
                    // Walk each control recursively and scale.  We search the control
                    // for its own set of scaling data; if we don't find it, we use the current
                    // container control's scaling data.  Once we scale a control, we set
                    // its scaling factors to unity.  As we walk out of a container control,
                    // we set its scaling factor to unity too.
                    SizeF included = SizeF.Empty;
                    SizeF excluded = SizeF.Empty;
 
                    if (includedBounds) included = AutoScaleFactor;
                    if (excludedBounds) excluded = AutoScaleFactor;
 
                    Scale(included, excluded, this);
                    autoScaleDimensions = CurrentAutoScaleDimensions;
                }
            }
            finally {
                if (includedBounds) {
                    state[stateScalingNeededOnLayout] = false;
                    EnableRequiredScaling(this, false);
                }
                state[stateParentChanged] = false;
 
                if (suspended) {
                    ResumeAllLayout(this, false);
                }
            }
        }
 
        /// <devdoc>
        ///     Checks to see if we need to perform an autoscale in
        ///     response to a layout.
        /// </devdoc>
        private void PerformNeededAutoScaleOnLayout() {
            if (state[stateScalingNeededOnLayout]) {
                PerformAutoScale(state[stateScalingNeededOnLayout], false);
            }
        }
 
        /// <devdoc>
        ///     Recursively resumes all layout.
        /// </devdoc>
        internal void ResumeAllLayout(Control start, bool performLayout) {
 
            ControlCollection controlsCollection = start.Controls;
            // This may have changed the sizes of our children.
            // PERFNOTE: This is more efficient than using Foreach.  Foreach
            // forces the creation of an array subset enum each time we
            // enumerate
            for(int i = 0; i < controlsCollection.Count; i++) {
                ResumeAllLayout(controlsCollection[i], performLayout);
            }
 
            start.ResumeLayout(performLayout);
        }
 
        /// <devdoc>
        ///     Recursively suspends all layout.
        /// </devdoc>
        internal void SuspendAllLayout(Control start) {
            start.SuspendLayout();
            CommonProperties.xClearPreferredSizeCache(start);
 
            ControlCollection controlsCollection = start.Controls;
            // This may have changed the sizes of our children.
            // PERFNOTE: This is more efficient than using Foreach.  Foreach
            // forces the creation of an array subset enum each time we
            // enumerate
            for(int i = 0; i < controlsCollection.Count; i++) {
                SuspendAllLayout(controlsCollection[i]);
            }
        }
 
        /// <include file='doc\Control.uex' path='docs/doc[@for="ContainerControl.Scale"]/*' />
        /// <devdoc>
        ///     Overrides the default scaling mechanism to account for autoscaling.  This
        ///     override behaves as follows:  any unchanged controls are always scaled
        ///     according to the container control's AutoScaleFactor.  Any changed controls are
        ///     scaled according to the provided scaling factor.
        /// </devdoc>
        internal override void Scale(SizeF includedFactor, SizeF excludedFactor, Control requestingControl) {
 
            // If we're inhieriting our scaling from our parent, Scale is really easy:  just do the
            // base class implementation.
            if (AutoScaleMode == AutoScaleMode.Inherit) {
                base.Scale(includedFactor, excludedFactor, requestingControl);
            }
            else {
                // We scale our controls based on our own auto scaling
                // factor, not the one provided to us.  We only do this for
                // controls that are not required to be scaled (excluded controls).
                SizeF ourExcludedFactor = excludedFactor;
                SizeF childIncludedFactor = includedFactor;
 
                if (!ourExcludedFactor.IsEmpty) {
                    ourExcludedFactor = AutoScaleFactor;
                }
 
                // If we're not supposed to be scaling, don't scale the internal
                // ones either.
                if (AutoScaleMode == AutoScaleMode.None) {
                    childIncludedFactor = AutoScaleFactor;
                }
 
                // When we scale, we are establishing new baselines for the
                // positions of all controls.  Therefore, we should resume(false).
                using (new LayoutTransaction(this, this, PropertyNames.Bounds, false)) {
 
                    // Our own container control poses a problem.  We want
                    // an outer control to be responsible for scaling it,
                    // because the outer control knows the container's dimensions.
                    // We detect this by checking who is requesting that the
                    // scaling occur.
                    SizeF ourExternalContainerFactor = ourExcludedFactor;
 
                    if (!excludedFactor.IsEmpty && ParentInternal != null) {
                        ourExternalContainerFactor = SizeF.Empty;
 
                        bool scaleUs = (requestingControl != this || state[stateParentChanged]);
 
                        // Hack for design time support:  we may be parented within another form
                        // that is not part of the designer.
                        if (!scaleUs) {
                            bool dt = false;
                            bool parentDt = false;
                            ISite site = Site;
                            ISite parentSite = ParentInternal.Site;
 
                            if (site != null) dt = site.DesignMode;
                            if (parentSite != null) parentDt = parentSite.DesignMode;
 
                            if (dt && !parentDt) {
                                scaleUs = true;
                            }
                        }
 
                        if (scaleUs) {
                            ourExternalContainerFactor = excludedFactor;
                        }
                    }
 
                    ScaleControl(includedFactor, ourExternalContainerFactor, requestingControl);
                    ScaleChildControls(childIncludedFactor, ourExcludedFactor, requestingControl);
                }
            }
        }
 
        /// <devdoc>
        ///     Process an arrowKey press by selecting the next control in the group
        ///     that the activeControl belongs to.
        /// </devdoc>
        /// <internalonly/>
        private bool ProcessArrowKey(bool forward) {
            Control group = this;
            if (activeControl != null) {
                group = activeControl.ParentInternal;
            }
            return group.SelectNextControl(activeControl, forward, false, false, true);
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.ProcessDialogChar"]/*' />
        /// <internalonly/>
        /// <devdoc>
        ///    Processes a dialog character. Overrides Control.processDialogChar().
        ///    This method calls the processMnemonic() method to check if the character
        ///    is a mnemonic for one of the controls on the form. If processMnemonic()
        ///    does not consume the character, then base.processDialogChar() is
        ///    called.
        /// </devdoc>
        [EditorBrowsable(EditorBrowsableState.Advanced)]
        [UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
        protected override bool ProcessDialogChar(char charCode) {
#if DEBUG
            Debug.WriteLineIf(ControlKeyboardRouting.TraceVerbose, "ContainerControl.ProcessDialogChar [" + charCode.ToString() + "]");
#endif
            // If we're the top-level form or control, we need to do the mnemonic handling
            //
            ContainerControl parent = GetContainerControlInternal() as ContainerControl;
            if (parent != null && charCode != ' ' && ProcessMnemonic(charCode)) return true;
            return base.ProcessDialogChar(charCode);
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.ProcessDialogKey"]/*' />
        /// <internalonly/>
        /// <devdoc>
        ///    Processes a dialog key. Overrides Control.processDialogKey(). This
        ///    method implements handling of the TAB, LEFT, RIGHT, UP, and DOWN
        ///    keys in dialogs.
        ///    The method performs no processing on keys that include the ALT or
        ///    CONTROL modifiers. For the TAB key, the method selects the next control
        ///    on the form. For the arrow keys,
        ///    !!!
        /// </devdoc>
        [UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
        protected override bool ProcessDialogKey(Keys keyData) {
#if DEBUG
            Debug.WriteLineIf(ControlKeyboardRouting.TraceVerbose, "ContainerControl.ProcessDialogKey [" + keyData.ToString() + "]");
#endif
            if ((keyData & (Keys.Alt | Keys.Control)) == Keys.None) {
                Keys keyCode = (Keys)keyData & Keys.KeyCode;
                switch (keyCode) {
                    case Keys.Tab:
                        if (ProcessTabKey((keyData & Keys.Shift) == Keys.None)) return true;
                        break;
                    case Keys.Left:
                    case Keys.Right:
                    case Keys.Up:
                    case Keys.Down:
                        if (ProcessArrowKey(keyCode == Keys.Right ||
                                            keyCode == Keys.Down)) return true;
                        break;
                }
            }
            return base.ProcessDialogKey(keyData);
        }
 
 
         /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.ProcessCmdKey"]/*' />
         /// <internalonly/>
         [
             SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)
         ]
         protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
            Debug.WriteLineIf(ControlKeyboardRouting.TraceVerbose, "ContainerControl.ProcessCmdKey " + msg.ToString());
 
            if (base.ProcessCmdKey(ref msg, keyData)) {
            return true;
            }
            if (ParentInternal == null) {
                // unfortunately, we have to stick this here for the case where we're hosted without
                // a form in the chain.  This would be something like a context menu strip with shortcuts
                // hosted within Office, VS or IE.
                //
                // this is an optimized search O(number of ToolStrips in thread)
                // that happens only if the key routing makes it to the top.
                return ToolStripManager.ProcessCmdKey(ref msg, keyData);
            }
            return false;
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.ProcessMnemonic"]/*' />
        /// <internalonly/>
        [UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
        protected internal override bool ProcessMnemonic(char charCode) {
#if DEBUG
            Debug.WriteLineIf(ControlKeyboardRouting.TraceVerbose, "ContainerControl.ProcessMnemonic [" + charCode.ToString() + "]");
            Debug.Indent();
            Debug.WriteLineIf(ControlKeyboardRouting.TraceVerbose, "this == " + ToString());
#endif
            if( !CanProcessMnemonic() ){
                return false;
            }
 
            if (Controls.Count == 0) {
                Debug.Unindent();
                return false;
            }
 
            // Start with the active control.
            //
            Control start = ActiveControl;
 
#if DEBUG
            int count = 0;
#endif //DEBUG
 
            // Set the processing mnemonic flag so child controls don't check for it when checking if they
            // can process the mnemonic.
            this.state[stateProcessingMnemonic] = true;
 
            bool processed = false;
 
            try {
                // safety flag to avoid infinite loop when testing controls in a container.
                bool wrapped = false;
 
                Control ctl = start;
                Debug.WriteLineIf(ControlKeyboardRouting.TraceVerbose, "Check starting at '" + ((start != null) ? start.ToString() : "<null>") + "'");
 
                do  {
                    // Loop through the controls starting at the control next to the current Active control in the Tab order
                    // till we find someone willing to process this mnemonic.
                    // We don't start the search on the Active control to allow controls in the same container with the same 
                    // mnemonic (bad UI design but supported) to be processed sequentially (see VSWhidbey#428029).
#if DEBUG
                count++;
                if (count > 9999) {
                    Debug.Fail("Infinite loop trying to find controls which can ProcessMnemonic()!!!");
                }
#endif //DEBUG
                    ctl = GetNextControl(ctl, true);
 
                    if ( ctl != null ) {
#if DEBUG
                        Debug.WriteLineIf(ControlKeyboardRouting.TraceVerbose, "  ...checking for mnemonics on " + ctl.ToString());
                        // Control.TraceMnemonicProcessing.Enabled disables CanProcessMnemonic consistency check.
                        bool canProcess = Control.TraceMnemonicProcessing.Enabled ? true : ctl.CanProcessMnemonic(); // Processing the mnemonic can change the value of CanProcessMnemonic. See ASURT 39583.
#endif
                        // Processing the mnemonic can change the value of CanProcessMnemonic. See ASURT 39583.
                        if (ctl.ProcessMnemonic(charCode)) {
#if DEBUG
                            Debug.WriteLineIf(ControlKeyboardRouting.TraceVerbose, "  ...mnemonics found");
                            Debug.Assert((Control.TraceMnemonicProcessing.Enabled || canProcess), "ProcessMnemonic returned true, even though CanProcessMnemonic() is false.  Someone probably overrode ProcessMnemonic and forgot to test CanSelect or CanProcessMnemonic().");
                            Debug.Unindent();
#endif
                            processed = true;
                            break;
                        }
                    }
                    else { // ctl is null
                        if( wrapped ){
                            break;      // This avoids infinite loops
                        }
 
                        wrapped = true;
                    }
                } while (ctl != start);
            }
            finally {
                this.state[stateProcessingMnemonic] = false;
            }
 
            Debug.Unindent();
            return processed;
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.ProcessTabKey"]/*' />
        /// <devdoc>
        ///    <para>Selects the next available control and makes it the active control.</para>
        /// </devdoc>
        [UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
        protected virtual bool ProcessTabKey(bool forward) {
            if (SelectNextControl(activeControl, forward, true, true, false)) return true;
            return false;
        }
 
        private ScrollableControl FindScrollableParent(Control ctl) {
            Control current = ctl.ParentInternal;
            while (current != null && !(current is ScrollableControl)) {
                current = current.ParentInternal;
            }
            if (current != null) {
                return(ScrollableControl)current;
            }
            return null;
        }
 
        private void ScrollActiveControlIntoView() {
            Control last = activeControl;
            if (last != null) {
                ScrollableControl scrollParent = FindScrollableParent(last);
 
                while (scrollParent != null) {
                    scrollParent.ScrollControlIntoView(activeControl);
                    last = scrollParent;
                    scrollParent = FindScrollableParent(scrollParent);
                }
            }
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.Select"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        protected override void Select(bool directed, bool forward) {
            bool correctParentActiveControl = true;
            if (ParentInternal != null)
            {
                IContainerControl c = ParentInternal.GetContainerControlInternal();
                if (c != null)
                {
                    c.ActiveControl = this;
                    correctParentActiveControl = (c.ActiveControl == this);
                }
            }
            if (directed && correctParentActiveControl)
            {
                SelectNextControl(null, forward, true, true, false);
            }
        }
 
        /// <devdoc>
        ///     Implements ActiveControl property setter.
        /// </devdoc>
        private void SetActiveControl(Control ctl) {
            Debug.WriteLineIf(Control.FocusTracing.TraceVerbose, "ContainerControl::SetActiveControl(" + (ctl == null ? "null" : ctl.Name) + ") - " + this.Name);
 
            SetActiveControlInternal(ctl);
        }
 
        /// <devdoc>
        ///     Unsafe version of SetActiveControl - Use with caution!
        /// </devdoc>
        internal void SetActiveControlInternal(Control value) {
            Debug.WriteLineIf(Control.FocusTracing.TraceVerbose, "ContainerControl::SetActiveControlInternal(" + (value == null ? "null" : value.Name) + ") - " + this.Name);
            if (activeControl != value || (value != null && !value.Focused)) {
                if (value != null && !Contains(value)) {
                    throw new ArgumentException(SR.GetString(SR.CannotActivateControl));
                }
 
                bool ret;
                ContainerControl cc = this;
 
                if (value != null && value.ParentInternal != null)
                {
                    cc = (value.ParentInternal.GetContainerControlInternal()) as ContainerControl;
                }
                if (cc != null)
                {
                    // Call to the recursive function that corrects the chain
                    // of active controls
                    ret = cc.ActivateControlInternal(value, false);
                }
                else
                {
                    ret = AssignActiveControlInternal(value);
                }
 
                if (cc != null && ret)
                {
                    ContainerControl ccAncestor = this;
                    while (ccAncestor.ParentInternal != null &&
                           ccAncestor.ParentInternal.GetContainerControlInternal() is ContainerControl)
                    {
                        ccAncestor = ccAncestor.ParentInternal.GetContainerControlInternal() as ContainerControl;
                        Debug.Assert(ccAncestor != null);
                    }
 
                    if (ccAncestor.ContainsFocus &&
                        (value == null ||
                         !(value is UserControl) ||
                         (value is UserControl && !((UserControl)value).HasFocusableChild())))
                    {
                        cc.FocusActiveControlInternal();
                    }
                }
            }
        }
 
        internal ContainerControl InnerMostActiveContainerControl
        {
            get
            {
                ContainerControl ret = this;
                while (ret.ActiveControl is ContainerControl)
                {
                    ret = (ContainerControl) ret.ActiveControl;
                }
                return ret;
            }
        }
 
        internal ContainerControl InnerMostFocusedContainerControl
        {
            get
            {
                ContainerControl ret = this;
                while (ret.focusedControl is ContainerControl)
                {
                    ret = (ContainerControl) ret.focusedControl;
                }
                return ret;
            }
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.UpdateDefaultButton"]/*' />
        /// <devdoc>
        ///     Updates the default button based on current selection, and the
        ///     acceptButton property.
        /// </devdoc>
        /// <internalonly/>
        protected virtual void UpdateDefaultButton() {
            // hook for form
        }
 
        /// <devdoc>
        ///     Updates the focusedControl variable by walking towards the
        ///     activeControl variable, firing enter and leave events and validation
        ///     as necessary.
        /// </devdoc>
        /// <internalonly/>
        internal void UpdateFocusedControl() {
            Debug.WriteLineIf(Control.FocusTracing.TraceVerbose, "ContainerControl::UpdateFocusedControl() - " + this.Name);
 
            // Capture the current focusedControl as the unvalidatedControl if we don't have one/are not validating.
            EnsureUnvalidatedControl(focusedControl);
            Control pathControl = focusedControl;
 
            while (activeControl != pathControl) {
                if (pathControl == null || pathControl.IsDescendant(activeControl)) {
                    // heading down. find next control on path.
                    Control nextControlDown = activeControl;
                    while (true) {
                        Control parent = nextControlDown.ParentInternal;
                        if (parent == this || parent == pathControl)
                            break;
                        nextControlDown = nextControlDown.ParentInternal;
                    }
 
                    Control priorFocusedControl = focusedControl = pathControl;
                    EnterValidation(nextControlDown);
                    // If validation changed position, then jump back to the loop.
                    if (focusedControl != priorFocusedControl) {
                        pathControl = focusedControl;
                        continue;
                    }
 
                    pathControl = nextControlDown;
                    if (NativeWindow.WndProcShouldBeDebuggable) {
                        pathControl.NotifyEnter();
                    }
                    else {
                        try {
                            pathControl.NotifyEnter();
                        }
                        catch (Exception e) {
                            Application.OnThreadException(e);
                        }
                    }
                }
                else {
                    // heading up.
                    ContainerControl innerMostFCC = InnerMostFocusedContainerControl;
                    Control stopControl = null;
 
                    if (innerMostFCC.focusedControl != null)
                    {
                        pathControl = innerMostFCC.focusedControl;
                        stopControl = innerMostFCC;
 
                        if (innerMostFCC != this)
                        {
                            innerMostFCC.focusedControl = null;
                            if (!(innerMostFCC.ParentInternal != null && innerMostFCC.ParentInternal is MdiClient))
                            {
                                // Don't reset the active control of a MDIChild that loses the focus
                                innerMostFCC.activeControl = null;
                            }
                        }
                    }
                    else
                    {
                        pathControl = innerMostFCC;
                        // innerMostFCC.ParentInternal can be null when the ActiveControl is deleted.
                        if (innerMostFCC.ParentInternal != null)
                        {
                            ContainerControl cc = (innerMostFCC.ParentInternal.GetContainerControlInternal()) as ContainerControl;
                            stopControl = cc;
                            if (cc != null && cc != this)
                            {
                                cc.focusedControl = null;
                                cc.activeControl = null;
                            }
                        }
                    }
 
                    do
                    {
                        Control leaveControl = pathControl;
 
                        if (pathControl != null)
                        {
                            pathControl = pathControl.ParentInternal;
                        }
 
                        if (pathControl == this)
                        {
                            pathControl = null;
                        }
 
                        if (leaveControl != null)
                        {
                            if (NativeWindow.WndProcShouldBeDebuggable) {
                                leaveControl.NotifyLeave();
                            }
                            else {
                                try {
                                    leaveControl.NotifyLeave();
                                }
                                catch (Exception e) {
                                    Application.OnThreadException(e);
                                }
                            }
                        }
                    }
                    while (pathControl != null &&
                           pathControl != stopControl &&
                           !pathControl.IsDescendant(activeControl));
                }
            }
 
#if DEBUG            
            if (activeControl == null || (activeControl != null && activeControl.ParentInternal != null && !activeControl.ParentInternal.IsContainerControl))
            {
                Debug.Assert(activeControl == null || activeControl.ParentInternal.GetContainerControlInternal() == this);
            }
#endif
            focusedControl = activeControl;
            if (activeControl != null) {
                EnterValidation(activeControl);
            }
        }
 
        /// <devdoc>
        ///     Make sure we have a valid choice of last unvalidated control if at all possible.
        /// </devdoc>
        /// <internalonly/>
        private void EnsureUnvalidatedControl(Control candidate) {
            // Don't change the unvalidated control while in the middle of validation (re-entrancy)
            if (state[stateValidating]) {
                return;
            }
 
            // Don't change the existing unvalidated control
            if (unvalidatedControl != null) {
                return;
            }
 
            // No new choice of unvalidated control was specified - leave unvalidated control blank
            if (candidate == null) {
                return;
            }
 
            // Specified control has auto-validation disabled - leave unvalidated control blank
            if (!candidate.ShouldAutoValidate) {
                return;
            }
 
            // Go ahead and make specified control the current unvalidated control for this container
            unvalidatedControl = candidate;
 
            // In the case of nested container controls, try to pick the deepest possible unvalidated
            // control. For a container with no unvalidated control, use the active control instead.
            // Stop as soon as we encounter any control that has auto-validation turned off.
            while (unvalidatedControl is ContainerControl) {
                ContainerControl container = unvalidatedControl as ContainerControl;
 
                if (container.unvalidatedControl != null && container.unvalidatedControl.ShouldAutoValidate) {
                    unvalidatedControl = container.unvalidatedControl;
                }
                else if (container.activeControl != null && container.activeControl.ShouldAutoValidate) {
                    unvalidatedControl = container.activeControl;
                }
                else {
                    break;
                }
            }
        }
 
        /// <devdoc>
        ///     Validates the last unvalidated control and its ancestors (up through the ancestor in common
        ///     with enterControl) if enterControl causes validation.
        /// </devdoc>
        /// <internalonly/>
        private void EnterValidation(Control enterControl) {
            // No unvalidated control to validate - stop now
            if (unvalidatedControl == null) {
                return;
            }
 
            // Entered control does not trigger validation - stop now
            if (!enterControl.CausesValidation) {
                return;
            }
 
            // Get the effective AutoValidate mode for this control (based on its container control)
            AutoValidate autoValidateMode = Control.GetAutoValidateForControl(unvalidatedControl);
 
            // Auto-validate has been turned off in container of unvalidated control - stop now
            if (autoValidateMode == AutoValidate.Disable) {
                return;
            }
 
            // Find common ancestor of entered control and unvalidated control
            Control commonAncestor = enterControl;
            while (commonAncestor != null && !commonAncestor.IsDescendant(unvalidatedControl)) {
                commonAncestor = commonAncestor.ParentInternal;
            }
 
            // Should we force focus to stay on same control if there is a validation error?
            bool preventFocusChangeOnError = (autoValidateMode == AutoValidate.EnablePreventFocusChange);
 
            // Validate control and its ancestors, up to (but not including) the common ancestor
            ValidateThroughAncestor(commonAncestor, preventFocusChangeOnError);
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.Validate"]/*' />
        /// <devdoc>
        ///     <para>
        ///     Validates the last unvalidated control and its ancestors up through, but not including the current control.
        ///
        ///     This version always performs validation, regardless of the AutoValidate setting of the control's parent.
        ///     </para>
        /// </devdoc>
        //
        // -------------------------------
        // INTERNAL NOTE FOR Microsoft DEVS: This version is intended for user code that wants to force validation, even
        // while auto-validation is turned off. When adding any explicit Validate() calls to our code, consider using
        // Validate(true) rather than Validate(), so that you will be sensitive to the current auto-validation setting.
        // -------------------------------
        //
        public bool Validate() {
            return Validate(false);
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.Validate2"]/*' />
        /// <devdoc>
        ///     <para>
        ///     Validates the last unvalidated control and its ancestors up through, but not including the current control.
        ///
        ///     This version will skip validation if checkAutoValidate is true and the effective AutoValidate setting, as
        ///     determined by the control's parent, is AutoValidate.Disable.
        ///     </para>
        /// </devdoc>
        public bool Validate(bool checkAutoValidate) {
            bool validatedControlAllowsFocusChange;
            return ValidateInternal(checkAutoValidate, out validatedControlAllowsFocusChange);
        }
 
        internal bool ValidateInternal(bool checkAutoValidate, out bool validatedControlAllowsFocusChange) {
            validatedControlAllowsFocusChange = false;
 
            if (this.AutoValidate == AutoValidate.EnablePreventFocusChange ||
                (activeControl != null && activeControl.CausesValidation)) {
                if (unvalidatedControl == null) {
                    if (focusedControl is ContainerControl && focusedControl.CausesValidation) {
                        ContainerControl c = (ContainerControl)focusedControl;
                        if( !c.ValidateInternal(checkAutoValidate, out validatedControlAllowsFocusChange) ){
                            return false;
                        }
                    }
                    else {
                        unvalidatedControl = focusedControl;
                    }
                }
 
                // Should we force focus to stay on same control if there is a validation error?
                bool preventFocusChangeOnError = true;
 
                Control controlToValidate = unvalidatedControl != null ? unvalidatedControl : focusedControl;
 
                if (controlToValidate != null)
                {
                    // Get the effective AutoValidate mode for unvalidated control (based on its container control)
                    AutoValidate autoValidateMode = Control.GetAutoValidateForControl(controlToValidate);
 
                    // Auto-validate has been turned off in container of unvalidated control - stop now
                    if (checkAutoValidate && autoValidateMode == AutoValidate.Disable)
                    {
                        return true;
                    }
                    preventFocusChangeOnError = (autoValidateMode == AutoValidate.EnablePreventFocusChange);
                    validatedControlAllowsFocusChange = (autoValidateMode == AutoValidate.EnableAllowFocusChange);
                }
 
                return ValidateThroughAncestor(null, preventFocusChangeOnError);
            }
            return true;
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.ValidateChildren"]/*' />
        /// <devdoc>
        ///     Validates all selectable child controls in the container, including descendants. This is
        ///     equivalent to calling ValidateChildren(ValidationConstraints.Selectable). See <see cref='ValidationConstraints.Selectable'/>
        ///     for details of exactly which child controls will be validated.
        /// </devdoc>
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public virtual bool ValidateChildren() {
            return ValidateChildren(ValidationConstraints.Selectable);
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.ValidateChildren1"]/*' />
        /// <devdoc>
        ///     Validates all the child controls in the container. Exactly which controls are
        ///     validated and which controls are skipped is determined by <paramref name="flags"/>.
        /// </devdoc>
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public virtual bool ValidateChildren(ValidationConstraints validationConstraints) {
            // validationConstraints must be a combination of 
            // None = 0x00, Selectable = 0x01, Enabled = 0x02, Visible = 0x04, TabStop = 0x08, ImmediateChildren = 0x10
            // Not using ClientUtils.IsValidEnum here because this is a flags enum and everything is valid between 0x00 and 0x1F.
            if ((int)validationConstraints < 0x00 || (int)validationConstraints > 0x1F)
            {
                throw new InvalidEnumArgumentException("validationConstraints", (int)validationConstraints, typeof(ValidationConstraints)); 
            }
            return !PerformContainerValidation(validationConstraints);
        }
        
        private bool ValidateThroughAncestor(Control ancestorControl, bool preventFocusChangeOnError) {
            if (ancestorControl == null)
                ancestorControl = this;
            if (state[stateValidating])
                return false;
            if (unvalidatedControl == null)
                unvalidatedControl = focusedControl;
            //return true for a Container Control with no controls to validate....
            //
            if (unvalidatedControl == null)
                return true;
            if (!ancestorControl.IsDescendant(unvalidatedControl))
                return false;
 
            this.state[stateValidating] = true;
            bool cancel = false;
            
            Control currentActiveControl = activeControl;
            Control currentValidatingControl = unvalidatedControl;
            if (currentActiveControl != null) {
                currentActiveControl.ValidationCancelled = false;
                if (currentActiveControl is ContainerControl) {
                    ContainerControl currentActiveContainerControl = currentActiveControl as ContainerControl;
 
                    currentActiveContainerControl.ResetValidationFlag();
                }
            }
            try {
                while (currentValidatingControl != null && currentValidatingControl != ancestorControl) {
                    try {
                        cancel = currentValidatingControl.PerformControlValidation(false);
                    }
                    catch {
                        cancel = true;
                        throw;
                    }
 
                    if (cancel) {
                        break;
                    }
 
                    currentValidatingControl = currentValidatingControl.ParentInternal;
                }
 
                if (cancel && preventFocusChangeOnError) {
                    if (unvalidatedControl == null && currentValidatingControl != null &&
                        ancestorControl.IsDescendant(currentValidatingControl))
                    {
                        unvalidatedControl = currentValidatingControl;
                    }
                    // This bit 'marks' the control that was going to get the focus, so that it will ignore any pending
                    // mouse or key events. Otherwise it would still perform its default 'click' action or whatever.
                    if (currentActiveControl == activeControl) {
                        if (currentActiveControl != null) {
                            CancelEventArgs ev = new CancelEventArgs();
                            ev.Cancel = true;
                            currentActiveControl.NotifyValidationResult(currentValidatingControl, ev);
                            if (currentActiveControl is ContainerControl) {
                                ContainerControl currentActiveContainerControl = currentActiveControl as ContainerControl;
                                if (currentActiveContainerControl.focusedControl != null) {
                                    currentActiveContainerControl.focusedControl.ValidationCancelled = true;
                                }
                                currentActiveContainerControl.ResetActiveAndFocusedControlsRecursive();
                            }
                        }
                    }
                    // This bit forces the focus to move back to the invalid control
                    SetActiveControlInternal(unvalidatedControl);
                }
            }
            finally {
                unvalidatedControl = null;
                state[stateValidating] = false;
            }
            
            return !cancel;
        }
 
        private void ResetValidationFlag()  {
            // PERFNOTE: This is more efficient than using Foreach.  Foreach
            // forces the creation of an array subset enum each time we
            // enumerate
            Control.ControlCollection children = this.Controls;
            int count = children.Count;
            for(int i = 0; i < count; i++) {
                children[i].ValidationCancelled = false;
            }
        }
 
        internal void ResetActiveAndFocusedControlsRecursive()
        {
            if (activeControl is ContainerControl)
            {
                ((ContainerControl) activeControl).ResetActiveAndFocusedControlsRecursive();
            }
            activeControl = null;
            focusedControl = null;
        }
 
        [EditorBrowsable(EditorBrowsableState.Never)]
        internal virtual bool ShouldSerializeAutoValidate() {
            return autoValidate != AutoValidate.Inherit;
        }
 
        /// <devdoc>
        ///     WM_SETFOCUS handler
        /// </devdoc>
        /// <internalonly/>
        private void WmSetFocus(ref Message m) {
            Debug.WriteLineIf(Control.FocusTracing.TraceVerbose, "ContainerControl::WmSetFocus() - " + this.Name);
            if (!HostedInWin32DialogManager) {
                if (ActiveControl != null) {
                    WmImeSetFocus();
                    // Microsoft: Do not raise GotFocus event since the focus
                    //         is given to the visible ActiveControl
                    if (!ActiveControl.Visible) {
                        this.InvokeGotFocus(this, EventArgs.Empty);
                    }
                    FocusActiveControlInternal();
                }
                else {
                    if (ParentInternal != null) {
                        IContainerControl c = ParentInternal.GetContainerControlInternal();
                        if (c != null) {
                            bool succeeded = false;
 
                            ContainerControl knowncontainer = c as ContainerControl;
                            if (knowncontainer != null) {
                                succeeded = knowncontainer.ActivateControlInternal(this);
                            }
                            else {
 
                                // SECREVIEW : Taking focus and activating a control in response
                                //           : to a user gesture (WM_SETFOCUS) is OK.
                                //
                                IntSecurity.ModifyFocus.Assert();
                                try {
                                    succeeded = c.ActivateControl(this);
                                }
                                finally {
                                    CodeAccessPermission.RevertAssert();
                                }
                            }
                            if (!succeeded) {
                                return;
                            }
                        }
                    }
                    base.WndProc(ref m);
                }
            }
            else {
                base.WndProc(ref m);
            }
        }
 
        /// <include file='doc\ContainerControl.uex' path='docs/doc[@for="ContainerControl.WndProc"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// </devdoc>
        [EditorBrowsable(EditorBrowsableState.Advanced)]
        [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
        protected override void WndProc(ref Message m) {
            switch (m.Msg) {
                case NativeMethods.WM_SETFOCUS:
                    WmSetFocus(ref m);
                    break;
                default:
                    base.WndProc(ref m);
                    break;
            }
        }
    }
}