Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / WinForms / Managed / System / WinForms / ContainerControl.cs / 1305376 / ContainerControl.cs
//---------------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- /* */ 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; ////// /// [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"; ///Defines a /// base class for /// controls that can parent other controls. ////// /// public ContainerControl() : base() { SetStyle(ControlStyles.AllPaintingInWmPaint, false); // this class overrides GetPreferredSizeCore, let Control automatically cache the result SetState2(STATE2_USEPREFERREDSIZECACHE, true); } ///Initializes a new instance of the ////// class. /// /// 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. /// [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(); } } } ////// /// 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 /// 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); } } ////// /// 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. /// [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(); } } } ////// /// Indicates whether controls in this container will be automatically validated when the focus changes. /// [ 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); } } } ////// /// [ Browsable(false), EditorBrowsable(EditorBrowsableState.Never), SRCategory(SR.CatPropertyChanged), SRDescription(SR.ContainerControlOnAutoValidateChangedDescr), ] public event EventHandler AutoValidateChanged { add { this.autoValidateChanged += value; } remove { this.autoValidateChanged -= value; } } ///[To be supplied.] ////// /// /// [ 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; } } ////// The binding manager for the container control. /// ////// Container controls support ImeMode only to allow child controls to inherit it from their parents. /// 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; } } ////// /// [ SRCategory(SR.CatBehavior), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), SRDescription(SR.ContainerControlActiveControlDescr) ] public Control ActiveControl { get { return activeControl; } set { SetActiveControl(value); } } ///Indicates the current active control on the container control. ///protected override CreateParams CreateParams { [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] get { CreateParams cp = base.CreateParams; cp.ExStyle |= NativeMethods.WS_EX_CONTROLPARENT; return cp; } } /// /// /// 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 /// [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 currentAutoScaleDimensions = WindowsGraphicsCacheManager.MeasurementGraphics.DeviceContext.Dpi; break; default: currentAutoScaleDimensions = AutoScaleDimensions; break; } } return currentAutoScaleDimensions; } } ////// /// [ 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 ///Indicates the form that the scrollable control is assigned to. This property is read-only. ////// /// /// 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; } ///Activates the specified control. ////// /// Used for UserControls - checks if the control /// has a focusable control inside or not /// 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; } ////// /// /// [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void AdjustFormScrollbars(bool displayScrollbars) { base.AdjustFormScrollbars(displayScrollbars); if (!GetScrollState(ScrollStateUserHasScrolled)) { ScrollActiveControlIntoView(); } } ////// Cleans up form state after a control has been removed. /// Package scope for Control /// ///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) { 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); } /// /// Used to notify the AxContainer that the form /// has been created. This should only be called if /// there is an AX container. /// private void AxContainerFormCreated() { ((AxHost.AxContainer)Properties.GetObject(PropAxContainer)).FormCreated(); } ////// Specifies whether this control can process the mnemonic or not. /// 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; } ////// /// protected override void Dispose(bool disposing) { if (disposing) { activeControl = null; } base.Dispose(disposing); focusedControl = null; unvalidatedControl = null; } ///Disposes of the resources (other than memory) used by /// the ////// . /// Recursively enables required scaling from the given control /// private void EnableRequiredScaling(Control start, bool enable) { start.RequiredScalingEnabled = enable; foreach(Control c in start.Controls) { EnableRequiredScaling(c, enable); } } ////// Assigns focus to the activeControl. If there is no activeControl then /// focus is given to the form. /// package scope for Form /// 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; } ////// This method calcuates the auto scale dimensions based on the /// control's current font. /// [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; } ////// This method is called when one of the auto scale properties changes, indicating /// that we should scale controls on the next layout. /// 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); } } ////// 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. /// internal virtual void OnAutoScaleModeChanged() { } ////// /// Raises the AutoValidateChanged event. /// 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(); } } } ////// /// Called when a child is about to resume its layout. The default implementation /// calls OnChildLayoutResuming on the parent. /// internal override void OnChildLayoutResuming(Control child, bool performLayout) { base.OnChildLayoutResuming(child, performLayout); // 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; } } } ////// /// protected override void OnCreateControl() { base.OnCreateControl(); if (Properties.GetObject(PropAxContainer) != null) { AxContainerFormCreated(); } OnBindingContextChanged(EventArgs.Empty); } ///Raises the CreateControl event. ////// /// We override this to clear the current autoscale cache. /// [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); } ////// Container controls scale during layout. /// protected override void OnLayout(LayoutEventArgs e) { PerformNeededAutoScaleOnLayout(); base.OnLayout(e); } ////// /// 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. /// internal override void OnLayoutResuming(bool performLayout) { PerformNeededAutoScaleOnLayout(); base.OnLayoutResuming(performLayout); } ////// /// 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. /// protected override void OnParentChanged(EventArgs e) { state[stateParentChanged] = !RequiredScalingEnabled; base.OnParentChanged(e); } ////// /// 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. /// public void PerformAutoScale() { PerformAutoScale(true, true); } ////// /// 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. /// 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); } } } ////// Checks to see if we need to perform an autoscale in /// response to a layout. /// private void PerformNeededAutoScaleOnLayout() { if (state[stateScalingNeededOnLayout]) { PerformAutoScale(state[stateScalingNeededOnLayout], false); } } ////// Recursively resumes all layout. /// 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); } ////// Recursively suspends all layout. /// 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]); } } ////// /// 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. /// 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); } } } ////// Process an arrowKey press by selecting the next control in the group /// that the activeControl belongs to. /// ///private bool ProcessArrowKey(bool forward) { Control group = this; if (activeControl != null) { group = activeControl.ParentInternal; } return group.SelectNextControl(activeControl, forward, false, false, true); } /// /// /// /// 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. /// [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); } ////// /// /// 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, /// !!! /// [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); } ////// [ 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; } /// /// [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() : " ") + "'"); 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; } /// /// /// [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); } } } ///Selects the next available control and makes it the active control. ////// /// 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); } } ///[To be supplied.] ////// Implements ActiveControl property setter. /// private void SetActiveControl(Control ctl) { Debug.WriteLineIf(Control.FocusTracing.TraceVerbose, "ContainerControl::SetActiveControl(" + (ctl == null ? "null" : ctl.Name) + ") - " + this.Name); Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "ModifyFocus Demanded"); IntSecurity.ModifyFocus.Demand(); SetActiveControlInternal(ctl); } ////// Unsafe version of SetActiveControl - Use with caution! /// 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; } } ////// /// Updates the default button based on current selection, and the /// acceptButton property. /// ///protected virtual void UpdateDefaultButton() { // hook for form } /// /// Updates the focusedControl variable by walking towards the /// activeControl variable, firing enter and leave events and validation /// as necessary. /// ///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); } } /// /// Make sure we have a valid choice of last unvalidated control if at all possible. /// ///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; } } } /// /// Validates the last unvalidated control and its ancestors (up through the ancestor in common /// with enterControl) if enterControl causes validation. /// ///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); } /// /// /// // // ------------------------------- // INTERNAL NOTE FOR [....] 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); } ////// 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. /// ////// /// 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; } ////// 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. /// ////// /// Validates all selectable child controls in the container, including descendants. This is /// equivalent to calling ValidateChildren(ValidationConstraints.Selectable). See [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public virtual bool ValidateChildren() { return ValidateChildren(ValidationConstraints.Selectable); } ////// for details of exactly which child controls will be validated. /// /// /// Validates all the child controls in the container. Exactly which controls are /// validated and which controls are skipped is determined by [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; } ///. /// /// WM_SETFOCUS handler /// ///private void WmSetFocus(ref Message m) { Debug.WriteLineIf(Control.FocusTracing.TraceVerbose, "ContainerControl::WmSetFocus() - " + this.Name); if (!HostedInWin32DialogManager) { if (ActiveControl != null) { WmImeSetFocus(); // [....]: Do not raise GotFocus event since the focus // is given to the visible ActiveControl if (!ActiveControl.Visible) { OnGotFocus(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); } } /// /// /// /// [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; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Substitution.cs
- GridViewRow.cs
- MessageSecurityException.cs
- SchemaCompiler.cs
- ToolStripContentPanelDesigner.cs
- DbConnectionOptions.cs
- KeyToListMap.cs
- GroupLabel.cs
- Sql8ExpressionRewriter.cs
- Types.cs
- AdornerHitTestResult.cs
- SelectingProviderEventArgs.cs
- PrintingPermissionAttribute.cs
- ObjectConverter.cs
- _ReceiveMessageOverlappedAsyncResult.cs
- SecurityRuntime.cs
- CustomErrorsSectionWrapper.cs
- Ref.cs
- DragEvent.cs
- CheckBoxFlatAdapter.cs
- NewArrayExpression.cs
- Viewport3DAutomationPeer.cs
- GeometryDrawing.cs
- SystemIPGlobalStatistics.cs
- Viewport3DAutomationPeer.cs
- ScrollProperties.cs
- _HelperAsyncResults.cs
- AssociationEndMember.cs
- MetadataFile.cs
- MetadataSerializer.cs
- Unit.cs
- LocalFileSettingsProvider.cs
- ToolstripProfessionalRenderer.cs
- ContainerSelectorBehavior.cs
- ConfigXmlSignificantWhitespace.cs
- AttachedAnnotationChangedEventArgs.cs
- Point.cs
- RectangleGeometry.cs
- NamespaceDecl.cs
- SecurityKeyType.cs
- MSHTMLHostUtil.cs
- XmlSchemaProviderAttribute.cs
- DelegatingConfigHost.cs
- XmlnsDictionary.cs
- EmptyEnumerable.cs
- ExpressionsCollectionEditor.cs
- DrawingImage.cs
- SnapLine.cs
- webeventbuffer.cs
- ListViewDeleteEventArgs.cs
- UrlRoutingHandler.cs
- WhiteSpaceTrimStringConverter.cs
- TextShapeableCharacters.cs
- MailAddressCollection.cs
- ReadOnlyHierarchicalDataSourceView.cs
- SystemIPInterfaceStatistics.cs
- XmlDownloadManager.cs
- StringFunctions.cs
- WindowInteractionStateTracker.cs
- NotificationContext.cs
- DataSourceCache.cs
- RowToFieldTransformer.cs
- BitmapEffectGeneralTransform.cs
- JsonServiceDocumentSerializer.cs
- WindowsAuthenticationModule.cs
- LocalizationParserHooks.cs
- CodeTypeParameter.cs
- UIElement3D.cs
- InternalConfigRoot.cs
- SqlTriggerAttribute.cs
- ToolStripPanel.cs
- ElementAction.cs
- CreateUserErrorEventArgs.cs
- SettingsAttributeDictionary.cs
- PeerSecurityManager.cs
- ValidationPropertyAttribute.cs
- InputMethod.cs
- ObjectDataSourceFilteringEventArgs.cs
- Message.cs
- TraceSwitch.cs
- FrugalMap.cs
- BitmapVisualManager.cs
- ItemCheckEvent.cs
- PropertyGridEditorPart.cs
- CompositionAdorner.cs
- SpeechRecognizer.cs
- RemotingClientProxy.cs
- ListViewUpdatedEventArgs.cs
- _emptywebproxy.cs
- ExpressionLexer.cs
- WindowsComboBox.cs
- SchemaMerger.cs
- XmlSchemaAttributeGroupRef.cs
- PixelFormat.cs
- HttpTransportBindingElement.cs
- MeshGeometry3D.cs
- TextEffect.cs
- WebBrowserNavigatingEventHandler.cs
- EnumConverter.cs
- SqlColumnizer.cs