| File: System\Windows\Forms\Panels\Panel.cs | Web Access |
| Project: src\winforms\src\System.Windows.Forms\System.Windows.Forms.csproj (System.Windows.Forms) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms.Layout; namespace System.Windows.Forms; /// <summary> /// Represents a <see cref="Panel"/> control. /// </summary> [DefaultProperty(nameof(BorderStyle))] [DefaultEvent(nameof(Paint))] [Docking(DockingBehavior.Ask)] [Designer($"System.Windows.Forms.Design.PanelDesigner, {Assemblies.SystemDesign}")] [SRDescription(nameof(SR.DescriptionPanel))] public partial class Panel : ScrollableControl { private BorderStyle _borderStyle = BorderStyle.None; /// <summary> /// Initializes a new instance of the <see cref="Panel"/> class. /// </summary> public Panel() : base() { // this class overrides GetPreferredSizeCore, let Control automatically cache the result SetExtendedState(ExtendedStates.UserPreferredSizeCache, true); TabStop = false; SetStyle(ControlStyles.Selectable | ControlStyles.AllPaintingInWmPaint, false); SetStyle(ControlStyles.SupportsTransparentBackColor, true); } /// <summary> /// Override to re-expose AutoSize. /// </summary> [Browsable(true)] [EditorBrowsable(EditorBrowsableState.Always)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] public override bool AutoSize { get => base.AutoSize; set => base.AutoSize = value; } [SRCategory(nameof(SR.CatPropertyChanged))] [SRDescription(nameof(SR.ControlOnAutoSizeChangedDescr))] [Browsable(true)] [EditorBrowsable(EditorBrowsableState.Always)] public new event EventHandler? AutoSizeChanged { add => base.AutoSizeChanged += value; remove => base.AutoSizeChanged -= value; } /// <summary> /// Allows the control to optionally shrink when AutoSize is true. /// </summary> [SRDescription(nameof(SR.ControlAutoSizeModeDescr))] [SRCategory(nameof(SR.CatLayout))] [Browsable(true)] [DefaultValue(AutoSizeMode.GrowOnly)] [Localizable(true)] public virtual AutoSizeMode AutoSizeMode { get => GetAutoSizeMode(); set { SourceGenerated.EnumValidator.Validate(value); if (GetAutoSizeMode() != value) { SetAutoSizeMode(value); if (ParentInternal is not null) { // DefaultLayout does not keep anchor information until it needs to. When // AutoSize became a common property, we could no longer blindly call into // DefaultLayout, so now we do a special InitLayout just for DefaultLayout. if (ParentInternal.LayoutEngine == DefaultLayout.Instance) { ParentInternal.LayoutEngine.InitLayout(this, BoundsSpecified.Size); } LayoutTransaction.DoLayout(ParentInternal, this, PropertyNames.AutoSize); } } } } /// <summary> /// Indicates the border style for the control. /// </summary> [SRCategory(nameof(SR.CatAppearance))] [DefaultValue(BorderStyle.None)] [DispId(PInvokeCore.DISPID_BORDERSTYLE)] [SRDescription(nameof(SR.PanelBorderStyleDescr))] public BorderStyle BorderStyle { get => _borderStyle; set { if (_borderStyle != value) { SourceGenerated.EnumValidator.Validate(value); _borderStyle = value; UpdateStyles(); } } } /// <summary> /// Returns the parameters needed to create the handle. Inheriting classes can override /// this to provide extra functionality. They should not, however, forget to call /// base.getCreateParams() first to get the struct filled up with the basic info. /// </summary> protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; cp.Style &= ~(int)WINDOW_STYLE.WS_BORDER; cp.ExStyle |= (int)WINDOW_EX_STYLE.WS_EX_CONTROLPARENT; cp.ExStyle &= ~(int)WINDOW_EX_STYLE.WS_EX_CLIENTEDGE; switch (_borderStyle) { case BorderStyle.Fixed3D: cp.ExStyle |= (int)WINDOW_EX_STYLE.WS_EX_CLIENTEDGE; break; case BorderStyle.FixedSingle: cp.Style |= (int)WINDOW_STYLE.WS_BORDER; break; } return cp; } } /// <summary> /// Deriving classes can override this to configure a default size for their control. /// This is more efficient than setting the size in the control's constructor. /// </summary> protected override Size DefaultSize => new(200, 100); 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; } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] public new event KeyEventHandler? KeyUp { add => base.KeyUp += value; remove => base.KeyUp -= value; } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] public new event KeyEventHandler? KeyDown { add => base.KeyDown += value; remove => base.KeyDown -= value; } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] public new event KeyPressEventHandler? KeyPress { add => base.KeyPress += value; remove => base.KeyPress -= value; } internal override bool SupportsUiaProviders => true; [DefaultValue(false)] public new bool TabStop { get => base.TabStop; set => base.TabStop = value; } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] [Bindable(false)] [AllowNull] public override string Text { get => base.Text; set => base.Text = value; } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler? TextChanged { add => base.TextChanged += value; remove => base.TextChanged -= value; } /// <summary> /// Fires the event indicating that the panel has been resized. /// Inheriting controls should use this in favour of actually listening to /// the event, but should not forget to call base.onResize() to /// ensure that the event is still fired for external listeners. /// </summary> protected override void OnResize(EventArgs eventargs) { if (DesignMode && _borderStyle == BorderStyle.None) { Invalidate(); } base.OnResize(eventargs); } private protected override void PrintToMetaFileRecursive(HDC hDC, IntPtr lParam, Rectangle bounds) { base.PrintToMetaFileRecursive(hDC, lParam, bounds); using DCMapping mapping = new(hDC, bounds); using Graphics g = hDC.CreateGraphics(); ControlPaint.PrintBorder(g, new Rectangle(Point.Empty, Size), BorderStyle, Border3DStyle.Sunken); } /// <summary> /// Returns a string representation for this control. /// </summary> public override string ToString() { return $"{base.ToString()}, BorderStyle: {typeof(BorderStyle)}.{_borderStyle}"; } /// <summary> /// Creates a new AccessibleObject for this <see cref="Panel"/> instance. /// The AccessibleObject instance returned by this method supports ControlType UIA property. /// </summary> /// <returns> /// <see cref="AccessibleObject"/> for this <see cref="Panel"/> instance. /// </returns> protected override AccessibleObject CreateAccessibilityInstance() => new PanelAccessibleObject(this); }