File: winforms\Managed\System\WinForms\Label.cs
Project: ndp\fx\src\System.Windows.Forms.csproj (System.Windows.Forms)
//------------------------------------------------------------------------------
// <copyright file="Label.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
 
namespace System.Windows.Forms {
 
    using System;
    using System.Security.Permissions;
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Diagnostics;
    using System.Drawing;
    using System.Windows.Forms.Internal;
    using System.Drawing.Design;
    using System.Drawing.Imaging;
    using System.Runtime.InteropServices;
    using System.Runtime.Remoting;
    using System.Runtime.Serialization.Formatters;
    using System.Windows.Forms.Layout;
    using Microsoft.Win32;
    using System.Collections;
    using System.Globalization;
    using System.Diagnostics.CodeAnalysis;
    using System.Runtime.Versioning;
    using Automation;
 
 
    /// <include file='doc\Label.uex' path='docs/doc[@for="Label"]/*' />
    /// <devdoc>
    ///    <para>
    ///       Represents a standard Windows label. </para>
    /// </devdoc>
    [
    ComVisible(true),
    ClassInterface(ClassInterfaceType.AutoDispatch),
    DefaultProperty("Text"),
    DefaultBindingProperty("Text"),
    Designer("System.Windows.Forms.Design.LabelDesigner, " + AssemblyRef.SystemDesign),
    ToolboxItem("System.Windows.Forms.Design.AutoSizeToolboxItem," + AssemblyRef.SystemDesign),
    SRDescription(SR.DescriptionLabel)
    ]
    // If not for FormatControl, we could inherit from ButtonBase and get foreground images for free.
    public class Label : Control, IAutomationLiveRegion {
 
        private static readonly object EVENT_TEXTALIGNCHANGED = new object();
 
        private static readonly BitVector32.Section StateUseMnemonic = BitVector32.CreateSection(1);
        private static readonly BitVector32.Section StateAutoSize    = BitVector32.CreateSection(1, StateUseMnemonic);
        private static readonly BitVector32.Section StateAnimating   = BitVector32.CreateSection(1, StateAutoSize);
        private static readonly BitVector32.Section StateFlatStyle   = BitVector32.CreateSection((int)FlatStyle.System, StateAnimating);
        private static readonly BitVector32.Section StateBorderStyle = BitVector32.CreateSection((int)BorderStyle.Fixed3D, StateFlatStyle);
        private static readonly BitVector32.Section StateAutoEllipsis = BitVector32.CreateSection(1, StateBorderStyle);
 
        private static readonly int PropImageList  = PropertyStore.CreateKey();
        private static readonly int PropImage      = PropertyStore.CreateKey();
 
        private static readonly int PropTextAlign  = PropertyStore.CreateKey();
        private static readonly int PropImageAlign = PropertyStore.CreateKey();
        private static readonly int PropImageIndex = PropertyStore.CreateKey();
 
        ///////////////////////////////////////////////////////////////////////
        // Label per instance members
        //
        // Note: Do not add anything to this list unless absolutely neccessary.
        //
        // Begin Members {
 
        // List of properties that are generally set, so we keep them directly on
        // Label.
        //
 
        BitVector32 labelState = new BitVector32();
        int         requestedHeight;
        int         requestedWidth;
        LayoutUtils.MeasureTextCache textMeasurementCache; 
 
        //Tooltip is shown only if the Text in the Label is cut.
        internal bool showToolTip = false;
        ToolTip     textToolTip;
        // This bool suggests that the User has added a toolTip to this label
        // In such a case we should not show the AutoEllipsis tooltip.
        bool        controlToolTip = false;
        AutomationLiveSetting liveSetting;
 
        // } End Members
        ///////////////////////////////////////////////////////////////////////
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.Label"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Initializes a new instance of the <see cref='System.Windows.Forms.Label'/> class.
        ///    </para>
        /// </devdoc>
        public Label()
        : base() {
            // this class overrides GetPreferredSizeCore, let Control automatically cache the result
            SetState2(STATE2_USEPREFERREDSIZECACHE, true);  
           
            SetStyle(ControlStyles.UserPaint |
                     ControlStyles.SupportsTransparentBackColor |
                     ControlStyles.OptimizedDoubleBuffer, IsOwnerDraw());
 
            SetStyle(ControlStyles.FixedHeight |
                     ControlStyles.Selectable, false);
 
            SetStyle(ControlStyles.ResizeRedraw, true);
 
            CommonProperties.SetSelfAutoSizeInDefaultLayout(this,true);
 
            labelState[StateFlatStyle]   = (int)FlatStyle.Standard;
            labelState[StateUseMnemonic] = 1;
            labelState[StateBorderStyle] = (int)BorderStyle.None;
 
            TabStop = false;
            requestedHeight = Height;
            requestedWidth = Width;
        }
 
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.AutoSize"]/*' />
        /// <devdoc>
        ///    <para> Indicates whether the control is automatically resized
        ///       to fit its contents. </para>
        /// </devdoc>
        [
        SRCategory(SR.CatLayout),
        DefaultValue(false),
        RefreshProperties(RefreshProperties.All),
        Localizable(true),
        SRDescription(SR.LabelAutoSizeDescr),
        Browsable(true),
        EditorBrowsable(EditorBrowsableState.Always),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)
        ]
        public override bool AutoSize {
            get {
                return base.AutoSize;
            }
            set {
                if (AutoSize != value) {
                    base.AutoSize = value;
                    AdjustSize();
                }
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.AutoSizeChanged"]/*' />
        [SRCategory(SR.CatPropertyChanged), SRDescription(SR.ControlOnAutoSizeChangedDescr)]
        [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
        new public event EventHandler AutoSizeChanged
        {
            add
            {
                base.AutoSizeChanged += value;
            }
            remove
            {
                base.AutoSizeChanged -= value;
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.AutoEllipsis"]/*' />
        /// <devdoc>
        ///    <para> This property controls the activation handling of bleedover for the text that
        ///    extends beyond the width of the label. </para>
        /// </devdoc>
        [
        SRCategory(SR.CatBehavior),
        DefaultValue(false),
        Browsable(true),
        EditorBrowsable(EditorBrowsableState.Always),
        SRDescription(SR.LabelAutoEllipsisDescr)
        ]
        public bool AutoEllipsis {
            get {
                return labelState[StateAutoEllipsis] != 0;
            }
 
            set {
                if (AutoEllipsis != value) {
                    labelState[StateAutoEllipsis] = value ? 1 : 0;
                    MeasureTextCache.InvalidateCache();
 
                    OnAutoEllipsisChanged(/*EventArgs.Empty*/);
                    
                    if (value) {
                        if (textToolTip == null) {
                            textToolTip  = new ToolTip();
                        }
                    }
          
            
                    if (ParentInternal != null) {
                        LayoutTransaction.DoLayoutIf(AutoSize,ParentInternal, this, PropertyNames.AutoEllipsis);
                    }
                    Invalidate();
                }
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.BackgroundImage"]/*' />
        /// <internalonly/>
        /// <devdoc>
        ///    <para>
        ///       Gets or sets the image rendered on the background of the control.
        ///    </para>
        /// </devdoc>
        [
        SRCategory(SR.CatAppearance),
        Browsable(false), EditorBrowsable(EditorBrowsableState.Never),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        SRDescription(SR.LabelBackgroundImageDescr)
        ]
        public override Image BackgroundImage {
            get {
                return base.BackgroundImage;
            }
            set {
                base.BackgroundImage = value;
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.BackgroundImageChanged"]/*' />
        /// <internalonly/>
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        new public event EventHandler BackgroundImageChanged {
            add {
                base.BackgroundImageChanged += value;
            }
            remove {
                base.BackgroundImageChanged -= value;
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.BackgroundImageLayout"]/*' />
        /// <internalonly/>
        /// <devdoc>
        ///    <para>
        ///       Gets or sets the image layout for the background of the control.
        ///    </para>
        /// </devdoc>
        [
        Browsable(false), EditorBrowsable(EditorBrowsableState.Never)
        ]
        public override ImageLayout BackgroundImageLayout {
            get {
                return base.BackgroundImageLayout;
            }
            set {
                base.BackgroundImageLayout = value;
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.BackgroundImageLayoutChanged"]/*' />
        /// <internalonly/>
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        new public event EventHandler BackgroundImageLayoutChanged {
            add {
                base.BackgroundImageLayoutChanged += value;
            }
            remove {
                base.BackgroundImageLayoutChanged -= value;
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.BorderStyle"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Gets or sets the border style for the control.
        ///    </para>
        /// </devdoc>
        [
        SRCategory(SR.CatAppearance),
        DefaultValue(BorderStyle.None),
        DispId(NativeMethods.ActiveX.DISPID_BORDERSTYLE),
        SRDescription(SR.LabelBorderDescr)
        ]
        public virtual BorderStyle BorderStyle {
            get {
                return (BorderStyle)labelState[StateBorderStyle];
            }
            set {
                //valid values are 0x0 to 0x2
                if (!ClientUtils.IsEnumValid(value, (int)value, (int)BorderStyle.None, (int)BorderStyle.Fixed3D)){
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(BorderStyle));
                }
 
                if (BorderStyle != value) {
                    labelState[StateBorderStyle] = (int)value;
                    if (ParentInternal != null) {
                        LayoutTransaction.DoLayoutIf(AutoSize, ParentInternal, this, PropertyNames.BorderStyle);
                    }
                    if (AutoSize) {
                        AdjustSize();
                    }
                    RecreateHandle();
                }
            }
        }
 
        /// <summary>
        ///     Determines whether the current state of the control allows for rendering text using TextRenderer (GDI).
        ///     See LinkLabel implementation for details.
        /// </summary>
        internal virtual bool CanUseTextRenderer {
            get{
                return true;
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.CreateParams"]/*' />
        /// <internalonly/>
        /// <devdoc>
        ///    Overrides Control.  A Label is a Win32 STATIC control, which we setup here.
        /// </devdoc>
        protected override CreateParams CreateParams {
            [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
            get {
                CreateParams cp = base.CreateParams;
                cp.ClassName = "STATIC";
 
                if (OwnerDraw) {
                    // An unfortunate side effect of this style is Windows sends us WM_DRAWITEM
                    // messages instead of WM_PAINT, but since Windows insists on repainting
                    // *without* a WM_PAINT after SetWindowText, I don't see much choice.
                    cp.Style |= NativeMethods.SS_OWNERDRAW;
 
                    // Since we're owner draw, I don't see any point in setting the
                    // SS_CENTER/SS_RIGHT styles.
                    //
                    cp.ExStyle &= ~NativeMethods.WS_EX_RIGHT;   // WS_EX_RIGHT overrides the SS_XXXX alignment styles
                }
 
 
                if (!OwnerDraw) {
                    switch(TextAlign) {
                        case ContentAlignment.TopLeft:
                        case ContentAlignment.MiddleLeft:
                        case ContentAlignment.BottomLeft:
                            cp.Style |= NativeMethods.SS_LEFT;
                            break;
 
                        case ContentAlignment.TopRight:
                        case ContentAlignment.MiddleRight:
                        case ContentAlignment.BottomRight:
                            cp.Style |= NativeMethods.SS_RIGHT;
                            break;
 
                        case ContentAlignment.TopCenter:
                        case ContentAlignment.MiddleCenter:
                        case ContentAlignment.BottomCenter:
                            cp.Style |= NativeMethods.SS_CENTER;
                            break;
                    }
                }
                else
                    cp.Style |= NativeMethods.SS_LEFT;
 
                switch (BorderStyle) {
                    case BorderStyle.FixedSingle:
                        cp.Style |= NativeMethods.WS_BORDER;
                        break;
                    case BorderStyle.Fixed3D:
                        cp.Style |= NativeMethods.SS_SUNKEN;
                        break;
                }
 
                if (!UseMnemonic)
                    cp.Style |= NativeMethods.SS_NOPREFIX;
 
                return cp;
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.DefaultImeMode"]/*' />
        protected override ImeMode DefaultImeMode {
            get {
                return ImeMode.Disable;
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.DefaultMargin"]/*' />
        protected override Padding DefaultMargin {
            get {
                return new Padding(3, 0, 3, 0);
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.DefaultSize"]/*' />
        /// <devdoc>
        ///     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.
        /// </devdoc>
        protected override Size DefaultSize {
            get {
                return new Size(100, AutoSize ? PreferredHeight : 23);
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.FlatStyle"]/*' />
        [
            SRCategory(SR.CatAppearance),
            DefaultValue(FlatStyle.Standard),
            SRDescription(SR.ButtonFlatStyleDescr)
        ]
        public FlatStyle FlatStyle {
            get {
                return (FlatStyle)labelState[StateFlatStyle];
            }
            set {
                //valid values are 0x0 to 0x3
                if (!ClientUtils.IsEnumValid(value, (int)value, (int)FlatStyle.Flat, (int)FlatStyle.System))
                {
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(FlatStyle));
                }
 
                if (labelState[StateFlatStyle] != (int)value) {
                    bool needRecreate = (labelState[StateFlatStyle] == (int)FlatStyle.System) || (value == FlatStyle.System);
 
                    labelState[StateFlatStyle] = (int)value;
 
                    SetStyle(ControlStyles.UserPaint
                             | ControlStyles.SupportsTransparentBackColor
                             | ControlStyles.OptimizedDoubleBuffer, OwnerDraw);
 
                    if (needRecreate) {
                        // this will clear the preferred size cache - it's OK if the parent is null - it would be a NOP.
                        LayoutTransaction.DoLayoutIf(AutoSize, ParentInternal, this, PropertyNames.BorderStyle);
                        if (AutoSize) {
                            AdjustSize();
                        }
                        RecreateHandle();                       
                    }
                    else {
                        Refresh();
                    }
                }
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.Image"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Gets or sets the image that is displayed on a <see cref='System.Windows.Forms.Label'/>.
        ///    </para>
        /// </devdoc>
        [
        Localizable(true),
        SRDescription(SR.ButtonImageDescr),
        SRCategory(SR.CatAppearance)
        ]
        public Image Image {
            [ResourceExposure(ResourceScope.Machine)]
            [ResourceConsumption(ResourceScope.Machine)]
            get {
                Image image = (Image)Properties.GetObject(PropImage);
 
                if (image == null && ImageList != null && ImageIndexer.ActualIndex >= 0) {
                    return ImageList.Images[ImageIndexer.ActualIndex];
                }
                else {
                    return image;
                }
            }
            set {
                if (Image != value) {
                    StopAnimate();
 
                    Properties.SetObject(PropImage, value);
                    if (value != null) {
                        ImageIndex = -1;
                        ImageList = null;
                    }
 
                    // Hook up the frame changed event
                    //
                    Animate();
                    Invalidate();
                }
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.ImageIndex"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Gets or sets the index value of the images displayed on the
        ///    <see cref='System.Windows.Forms.Label'/>.
        ///    </para>
        /// </devdoc>
        [
        TypeConverterAttribute(typeof(ImageIndexConverter)),
        Editor("System.Windows.Forms.Design.ImageIndexEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
        DefaultValue(-1),
        Localizable(true),
        RefreshProperties(RefreshProperties.Repaint),
        SRDescription(SR.ButtonImageIndexDescr),
        SRCategory(SR.CatAppearance)
        ]
        public int ImageIndex {
            get {
 
               if (ImageIndexer != null) {
                    int index = ImageIndexer.Index;
 
                    if (ImageList != null && (index >= ImageList.Images.Count)) {
                        return ImageList.Images.Count - 1;
                    }
                    return index;
 
                }
                return -1;
            }
            set {
                if (value < -1) {
                    throw new ArgumentOutOfRangeException("ImageIndex", SR.GetString(SR.InvalidLowBoundArgumentEx, "ImageIndex", (value).ToString(CultureInfo.CurrentCulture), (-1).ToString(CultureInfo.CurrentCulture)));
                }
                if (ImageIndex != value) {
                    if (value != -1) {
                        // Image.set calls ImageIndex = -1
                        Properties.SetObject(PropImage, null);
                    }
 
                    ImageIndexer.Index = value;
                    Invalidate();
                }
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.ImageKey"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Gets or sets the key accessor for the image list.  This specifies the image
	    ///	  from the image list to display on
        ///    <see cref='System.Windows.Forms.Label'/>.
        ///    </para>
        /// </devdoc>
        [
        TypeConverterAttribute(typeof(ImageKeyConverter)),
        Editor("System.Windows.Forms.Design.ImageIndexEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
        DefaultValue(""),
        Localizable(true),
        RefreshProperties(RefreshProperties.Repaint),
        SRDescription(SR.ButtonImageIndexDescr),
        SRCategory(SR.CatAppearance)
        ]
        public string ImageKey {
            get {
 
               if (ImageIndexer != null) {
                   return ImageIndexer.Key;
               }
               return null;
            }
            set {
                if (ImageKey != value) {
 
                    // Image.set calls ImageIndex = -1
                    Properties.SetObject(PropImage, null);
 
                    ImageIndexer.Key = value;
                    Invalidate();
                }
            }
        }
 
        internal LabelImageIndexer ImageIndexer{
            get {
                 bool found;
                 LabelImageIndexer imageIndexer = Properties.GetObject(PropImageIndex, out found) as LabelImageIndexer;
 
                 // Demand create the ImageIndexer property
                 if ((imageIndexer == null) || (!found)) {
                    imageIndexer = new LabelImageIndexer(this);
                    ImageIndexer = imageIndexer;
                 }
 
                 return imageIndexer;
            }
            set {
                Properties.SetObject(PropImageIndex, value);
            }
 
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.ImageList"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Gets or sets the images displayed in a <see cref='System.Windows.Forms.Label'/>.
        ///    </para>
        /// </devdoc>
        [
        DefaultValue(null),
        SRDescription(SR.ButtonImageListDescr),
        RefreshProperties(RefreshProperties.Repaint),
        SRCategory(SR.CatAppearance)
        ]
        public ImageList ImageList {
            get {
                return (ImageList)Properties.GetObject(PropImageList);
            }
            set {
                if (ImageList != value) {
 
                    EventHandler recreateHandler = new EventHandler(ImageListRecreateHandle);
                    EventHandler disposedHandler = new EventHandler(DetachImageList);
 
                    // Remove the previous imagelist handle recreate handler
                    //
                    ImageList imageList = ImageList;
                    if (imageList != null) {
                        imageList.RecreateHandle -= recreateHandler;
                        imageList.Disposed -= disposedHandler;
                    }
 
                    // Make sure we don't have an Image as well as an ImageList
                    //
                    if (value != null) {
                        Properties.SetObject(PropImage, null); // Image.set calls ImageList = null
                    }
 
                    Properties.SetObject(PropImageList, value);
 
                    // Add the new imagelist handle recreate handler
                    //
                    if (value != null) {
                        value.RecreateHandle += recreateHandler;
                        value.Disposed += disposedHandler;
                    }
 
                    Invalidate();
                }
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.ImageAlign"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Gets or sets the alignment of the image on the <see cref='System.Windows.Forms.Label'/>.
        ///    </para>
        /// </devdoc>
        [
        DefaultValue(ContentAlignment.MiddleCenter),
        Localizable(true),
        SRDescription(SR.ButtonImageAlignDescr),
        SRCategory(SR.CatAppearance)
        ]
        public ContentAlignment ImageAlign {
            get {
                bool found;
                int imageAlign = Properties.GetInteger(PropImageAlign, out found);
                if (found) {
                    return (ContentAlignment)imageAlign;
                }
                return ContentAlignment.MiddleCenter;
            }
            set {
                if (!WindowsFormsUtils.EnumValidator.IsValidContentAlignment(value)) {
                  throw new InvalidEnumArgumentException("value", (int)value, typeof(ContentAlignment));
                }
                if(value != ImageAlign) {
                    Properties.SetInteger(PropImageAlign, (int)value);
                    LayoutTransaction.DoLayoutIf(AutoSize, ParentInternal, this, PropertyNames.ImageAlign);
                    Invalidate();
                }
            }
        }
        /* FxCop rule 'AvoidBuildingNonCallableCode' - Left here in case it is needed in the future.
        private Rectangle ImageBounds {
            get {
                Image image = (Image)Properties.GetObject(PropImage);
                return CalcImageRenderBounds(image, ClientRectangle, RtlTranslateAlignment(ImageAlign));
            }
        }
        */
 
        /// <summary>
        /// Indicates the "politeness" level that a client should use
        /// to notify the user of changes to the live region.
        /// </summary>
        [
        SRCategory(SR.CatAccessibility),
        DefaultValue(AutomationLiveSetting.Off),
        SRDescription(SR.LiveRegionAutomationLiveSettingDescr),
        Browsable(true),
        EditorBrowsable(EditorBrowsableState.Always)
        ]
        public AutomationLiveSetting LiveSetting {
            get {
                return liveSetting;
            }
            set {
                if (!ClientUtils.IsEnumValid(value, (int)value, (int)AutomationLiveSetting.Off, (int)AutomationLiveSetting.Assertive)) {
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(AutomationLiveSetting));
                }
                liveSetting = value;
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.ImeMode"]/*' />
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        new public ImeMode ImeMode {
            get {
                return base.ImeMode;
            }
            set {
                base.ImeMode = value;
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.ImeModeChanged"]/*' />
        /// <internalonly/>
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler ImeModeChanged {
            add {
                base.ImeModeChanged += value;
            }
            remove {
                base.ImeModeChanged -= value;
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.KeyUp"]/*' />
        /// <internalonly/><hideinheritance/>
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new event KeyEventHandler KeyUp {
            add {
             base.KeyUp += value;
            }
            remove {
             base.KeyUp -= value;
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.KeyDown"]/*' />
        /// <internalonly/><hideinheritance/>
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new event KeyEventHandler KeyDown {
            add {
                 base.KeyDown += value;
            }
            remove {
                base.KeyDown -= value;
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.KeyPress"]/*' />
        /// <internalonly/><hideinheritance/>
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new event KeyPressEventHandler KeyPress {
            add {
             base.KeyPress += value;
            }
            remove {
             base.KeyPress -= value;
            }
        }
 
        internal LayoutUtils.MeasureTextCache MeasureTextCache {
            get {
                if (textMeasurementCache == null) {
                    textMeasurementCache = new LayoutUtils.MeasureTextCache();
                }
                return textMeasurementCache;
            }
        }
 
        internal virtual bool OwnerDraw {
            get {
                return IsOwnerDraw();
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.PreferredHeight"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Gets the height of the control (in pixels), assuming a
        ///       single line of text is displayed.
        ///    </para>
        /// </devdoc>
        [
        SRCategory(SR.CatLayout),
        Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        SRDescription(SR.LabelPreferredHeightDescr)
        ]
        public virtual int PreferredHeight {
            get { return PreferredSize.Height; }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.PreferredWidth"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Gets the width of the control (in pixels), assuming a single line
        ///       of text is displayed.
        ///    </para>
        /// </devdoc>
        [
        SRCategory(SR.CatLayout),
        Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        SRDescription(SR.LabelPreferredWidthDescr)
        ]
        public virtual int PreferredWidth {
            get { return PreferredSize.Width; }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.RenderTransparent"]/*' />
        /// <devdoc>
        ///    <para> Indicates whether
        ///       the container control background is rendered on the <see cref='System.Windows.Forms.Label'/>.</para>
        /// </devdoc>
        [Obsolete("This property has been deprecated. Use BackColor instead.  http://go.microsoft.com/fwlink/?linkid=14202")]
        virtual new protected bool RenderTransparent
        {
            get {
                return((Control) this).RenderTransparent;
            }
            set {
            }
        }
 
 
        private bool SelfSizing {
            get {
                return CommonProperties.ShouldSelfSize(this);
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.TabStop"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Gets or sets a value indicating whether the user can tab to the
        ///    <see cref='System.Windows.Forms.Label'/>.
        ///    </para>
        /// </devdoc>
        [DefaultValue(false), Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        new public bool TabStop {
            get {
                return base.TabStop;
            }
            set {
                base.TabStop = value;
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.TabStopChanged"]/*' />
        /// <internalonly/>
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        new public event EventHandler TabStopChanged {
            add {
                base.TabStopChanged += value;
            }
            remove {
                base.TabStopChanged -= value;
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.TextAlign"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Gets or sets the
        ///       horizontal alignment of the text in the control.
        ///    </para>
        /// </devdoc>
        [
        SRDescription(SR.LabelTextAlignDescr),
        Localizable(true),
        DefaultValue(ContentAlignment.TopLeft),
        SRCategory(SR.CatAppearance)
        ]
        public virtual ContentAlignment TextAlign {
            get {
                bool found;
                int textAlign = Properties.GetInteger(PropTextAlign, out found);
                if (found) {
                    return (ContentAlignment)textAlign;
                }
 
                return ContentAlignment.TopLeft;
            }
            set {
 
                if (!WindowsFormsUtils.EnumValidator.IsValidContentAlignment(value)) {
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(ContentAlignment));
                }
 
                if (TextAlign != value) {
                    Properties.SetInteger(PropTextAlign, (int)value);
                    Invalidate();
                    //Change the TextAlignment for SystemDrawn Labels ....
                    if (!OwnerDraw) {
                        RecreateHandle();
                    }
                    OnTextAlignChanged(EventArgs.Empty);
 
                }
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.Text"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Gets or sets the text in the Label. Since we can have multiline support
        ///       this property just overides the base to pluck in the Multiline editor.
        ///    </para>
        /// </devdoc>
        [
        Editor("System.ComponentModel.Design.MultilineStringEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
        SettingsBindable(true)
        ]
        public override string Text {
            get {
                return base.Text;
            }
            set {
                base.Text = value;
            }
        }
 
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.TextAlignChanged"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        [SRCategory(SR.CatPropertyChanged), SRDescription(SR.LabelOnTextAlignChangedDescr)]
        public event EventHandler TextAlignChanged {
            add {
                Events.AddHandler(EVENT_TEXTALIGNCHANGED, value);
            }
 
            remove {
                Events.RemoveHandler(EVENT_TEXTALIGNCHANGED, value);
            }
        }
 
        /// <devdoc>
        ///     Determines whether to use compatible text rendering engine (GDI+) or not (GDI).
        /// </devdoc>
        [
        DefaultValue(false),
        SRCategory(SR.CatBehavior),
        SRDescription(SR.UseCompatibleTextRenderingDescr)
        ]
        public bool UseCompatibleTextRendering {
            get{
                if( CanUseTextRenderer ){
                    return base.UseCompatibleTextRenderingInt;
                }
 
                // Use compat text rendering (GDI+).
                return true;
            }
            set{
                if( base.UseCompatibleTextRenderingInt != value ) {
                    base.UseCompatibleTextRenderingInt = value;
                    AdjustSize();
                }
            }
        }
 
        /// <devdoc>
        ///     Determines whether the control supports rendering text using GDI+ and GDI.
        ///     This is provided for container controls to iterate through its children to set UseCompatibleTextRendering to the same
        ///     value if the child control supports it.
        /// </devdoc>
        internal override bool SupportsUseCompatibleTextRendering {
            get {
                return true;
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.UseMnemonic"]/*' />
        /// <devdoc>
        ///    <para>Gets or sets a value indicating whether an ampersand (&amp;) included in the text of
        ///       the control.</para>
        /// </devdoc>
        [
        SRDescription(SR.LabelUseMnemonicDescr),
        DefaultValue(true),
        SRCategory(SR.CatAppearance)
        ]
        public bool UseMnemonic {
            get {
                return labelState[StateUseMnemonic] != 0;
            }
 
            set {
 
                if (UseMnemonic != value) {
                   labelState[StateUseMnemonic] = value ? 1 : 0;
                   MeasureTextCache.InvalidateCache();
                               
 
                   // The size of the label need to be adjusted when the Mnemonic
                   // is set irrespective of auto-sizing
                   using (LayoutTransaction.CreateTransactionIf(AutoSize, ParentInternal, this, PropertyNames.Text)) {
                      AdjustSize();
                      Invalidate();
                   }
 
                   //set windowStyle directly instead of recreating handle to increase efficiency
                   if (IsHandleCreated) {
                      int style = this.WindowStyle;
                      if (!UseMnemonic) {
 
                         style |= NativeMethods.SS_NOPREFIX;
                      }
                      else {
                         style &= ~NativeMethods.SS_NOPREFIX;
                      }
                      this.WindowStyle = style;
                   }
                }
            }
        }
 
 
        /// <devdoc>
        ///     Updates the control in response to events that could affect either
        ///     the size of the control, or the size of the text within it.
        /// </devdoc>
        /// <internalonly/>
        internal void AdjustSize() {
            if (!SelfSizing) {
                return;
            }
 
            // the rest is here for RTM compat.
 
            // If width and/or height are constrained by anchoring, don't adjust control size
            // to fit around text, since this will cause us to lose the original anchored size.
            if (!AutoSize &&
                ((this.Anchor & (AnchorStyles.Left | AnchorStyles.Right)) == (AnchorStyles.Left | AnchorStyles.Right) ||
                 (this.Anchor & (AnchorStyles.Top | AnchorStyles.Bottom)) == (AnchorStyles.Top | AnchorStyles.Bottom))) {
                return;
            }
 
            // Resize control to fit around current text
            //
            int saveHeight = requestedHeight;
            int saveWidth = requestedWidth;
            try {
                Size preferredSize = (AutoSize) ? PreferredSize : new Size(saveWidth, saveHeight);
                Size = preferredSize;
            }
            finally {
                requestedHeight = saveHeight;
                requestedWidth = saveWidth;
            }
        }
 
        internal void Animate() {
            Animate(!DesignMode && Visible && Enabled && ParentInternal != null);
        }
 
        internal void StopAnimate() {
            Animate(false);
        }
 
        private void Animate(bool animate) {
            bool currentlyAnimating = labelState[StateAnimating] != 0;
            if (animate != currentlyAnimating) {
                Image image = (Image)Properties.GetObject(PropImage);
                if (animate) {
                    if (image != null) {
                        ImageAnimator.Animate(image, new EventHandler(this.OnFrameChanged));
                        labelState[StateAnimating] = animate ? 1 : 0;
                    }
                }
                else {
                    if (image != null) {
                        ImageAnimator.StopAnimate(image, new EventHandler(this.OnFrameChanged));
                        labelState[StateAnimating] = animate ? 1 : 0;
                    }
                }
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.CalcImageRenderBounds"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        protected Rectangle CalcImageRenderBounds(Image image, Rectangle r, ContentAlignment align) {
            Size pointImageSize = image.Size;
 
            int xLoc = r.X + 2;
            int yLoc = r.Y + 2;
 
            if ((align & WindowsFormsUtils.AnyRightAlign) !=0) {
                xLoc = (r.X+r.Width - 4)-pointImageSize.Width;
            }
            else if ((align & WindowsFormsUtils.AnyCenterAlign) != 0) {
                xLoc = r.X + (r.Width - pointImageSize.Width)/2;
            }
 
 
            if ((align & WindowsFormsUtils.AnyBottomAlign) != 0) {
                yLoc = (r.Y+r.Height - 4)-pointImageSize.Height;
            }
            else if ((align & WindowsFormsUtils.AnyTopAlign) != 0) {
                yLoc = r.Y + 2;
            }
            else {
                yLoc = r.Y + (r.Height - pointImageSize.Height)/2;
            }
 
            return new Rectangle(xLoc, yLoc, pointImageSize.Width, pointImageSize.Height);
        }
 
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.CreateAccessibilityInstance"]/*' />
        protected override AccessibleObject CreateAccessibilityInstance() {
            return new LabelAccessibleObject(this);
        }
 
        /// <devdoc>
        ///     Get StringFormat object for rendering text using GDI+ (Graphics).
        /// </devdoc>
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        internal virtual StringFormat CreateStringFormat() {
            return ControlPaint.CreateStringFormat( this, this.TextAlign, this.AutoEllipsis, this.UseMnemonic );
        }
 
        private TextFormatFlags CreateTextFormatFlags() {
            return CreateTextFormatFlags(this.Size - GetBordersAndPadding());
        }
        /// <devdoc>
        ///     Get TextFormatFlags flags for rendering text using GDI (TextRenderer).
        /// </devdoc>
        internal virtual TextFormatFlags CreateTextFormatFlags(Size constrainingSize){
 
            // PREFERRED SIZE CACHING: 
            // Please read if you're adding a new TextFormatFlag.
            // whenever something can change the TextFormatFlags used
            // MeasureTextCache.InvalidateCache() should be called so we can approprately clear.
            
            TextFormatFlags flags = ControlPaint.CreateTextFormatFlags( this, this.TextAlign, this.AutoEllipsis, this.UseMnemonic );
 
            // Remove WordBreak if the size is large enough to display all the text.
            if (!MeasureTextCache.TextRequiresWordBreak(Text, Font, constrainingSize, flags)) {
                // The effect of the TextBoxControl flag is that in-word line breaking will occur if needed, this happens when AutoSize 
                // is false and a one-word line still doesn't fit the binding box (width).  The other effect is that partially visible 
                // lines are clipped; this is how GDI+ works by default.
                flags &= ~(TextFormatFlags.WordBreak | TextFormatFlags.TextBoxControl); 
            }
 
            return flags;
        }
 
        private void DetachImageList(object sender, EventArgs e) {
            ImageList = null;
        }
    
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.Dispose"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        protected override void Dispose(bool disposing) {
            if (disposing) {
                StopAnimate();
                // VSWhidbey 318551: holding on to images and image list is a memory leak.
                if (ImageList != null) {
                    ImageList.Disposed       -= new EventHandler(this.DetachImageList);
                    ImageList.RecreateHandle -= new EventHandler(ImageListRecreateHandle);
                    Properties.SetObject(PropImageList, null);
                }
                if (Image != null) {
                    Properties.SetObject(PropImage, null);
                }
 
                //Dipose the tooltip if one present..
                if (textToolTip != null) {
                    textToolTip.Dispose();
                    textToolTip = null;
                }
                controlToolTip = false;
            }
            base.Dispose(disposing);
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.DrawImage"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Draws an <see cref='System.Drawing.Image'/> within the specified bounds.
        ///    </para>
        /// </devdoc>
        protected void DrawImage(System.Drawing.Graphics g, Image image, Rectangle r, ContentAlignment align) {
            Rectangle loc = CalcImageRenderBounds(image, r, align);
 
            if (!Enabled) {
                ControlPaint.DrawImageDisabled(g, image, loc.X, loc.Y, BackColor);
            }
            else {
                g.DrawImage(image, loc.X, loc.Y, image.Width, image.Height);
            }
        }
 
        /// <internalonly/>
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.GetLines"]/*' />
        /// <devdoc>
        ///    <para>
        ///       This Function returns the number of lines in the label Text.
        ///    </para>
        /// </devdoc>
        /* FxCop rule 'AvoidBuildingNonCallableCode' - Left here in case it is needed in the future.
        private ArrayList GetLines() {
            string text = Text;
            ArrayList list = new ArrayList();
 
            int lineStart = 0;
            while (lineStart < text.Length) {
                int lineEnd = lineStart;
                for (; lineEnd < text.Length; lineEnd++) {
                    char c = text[lineEnd];
                    if (c == '\r' || c == '\n')
                        break;
                }
 
                string line = text.Substring(lineStart, lineEnd - lineStart);
                list.Add(line);
 
                // Treat "\r", "\r\n", and "\n" as new lines
                if (lineEnd < text.Length && text[lineEnd] == '\r')
                    lineEnd++;
                if (lineEnd < text.Length && text[lineEnd] == '\n')
                    lineEnd++;
 
                lineStart = lineEnd;
            }
            return list;
        }
        */
        private Size GetBordersAndPadding() {
           Size bordersAndPadding = Padding.Size;
           
           // COMPAT VSW 248415: Everett added random numbers to the height of the label               
           if (UseCompatibleTextRendering) {               
              //Always return the Fontheight + some buffer else the Text gets clipped for Autosize = true..
              //(bug 118909)
              if (BorderStyle != BorderStyle.None) {
                  bordersAndPadding.Height += 6; // taken from Everett.PreferredHeight
                  bordersAndPadding.Width += 2; // taken from Everett.PreferredWidth
              }
              else {
                  bordersAndPadding.Height += 3; // taken from Everett.PreferredHeight
              }
           }
           else {
              // in Whidbey we'll actually ask the control the border size.
              
              bordersAndPadding +=  SizeFromClientSize(Size.Empty);
              if (BorderStyle == BorderStyle.Fixed3D) {
                  bordersAndPadding += new Size(2, 2);
              } 
           }
           return bordersAndPadding;
 
       }
 
 
        public override Size GetPreferredSize(Size proposedSize) {
            //make sure the behavior is consistent with GetPreferredSizeCore
            if (proposedSize.Width == 1) {
                proposedSize.Width = 0;
            }
            if (proposedSize.Height == 1) {
                proposedSize.Height = 0;
            }
            return base.GetPreferredSize(proposedSize);
        }
 
        internal virtual bool UseGDIMeasuring() {
            return (FlatStyle == FlatStyle.System || !UseCompatibleTextRendering);
        }
       
        [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters")] // See ComboBox.cs GetComboHeight
        internal override Size GetPreferredSizeCore(Size proposedConstraints) {
            Size bordersAndPadding = GetBordersAndPadding();
            // Subtract border area from constraints
            proposedConstraints -= bordersAndPadding;
 
            // keep positive
            proposedConstraints = LayoutUtils.UnionSizes(proposedConstraints,Size.Empty);
 
            Size requiredSize;
 
            //
            // TEXT Measurement 
            //
            
            if (string.IsNullOrEmpty(Text)) {    
                // COMPAT VSW 248415: empty labels return the font height + borders
                using (WindowsFont font = WindowsFont.FromFont(this.Font)) {
                    // this is the character that Windows uses to determine the extent
                    requiredSize = WindowsGraphicsCacheManager.MeasurementGraphics.GetTextExtent("0", font);
                    requiredSize.Width = 0;
                }
            }
            else if (UseGDIMeasuring()) {
                TextFormatFlags format = FlatStyle == FlatStyle.System ? TextFormatFlags.Default : CreateTextFormatFlags(proposedConstraints);
                requiredSize = MeasureTextCache.GetTextSize(Text, Font, proposedConstraints, format);
            } 
            else {
                // GDI+ rendering.
                using (Graphics measurementGraphics = WindowsFormsUtils.CreateMeasurementGraphics()) {
                    using (StringFormat stringFormat = CreateStringFormat()) {
                        SizeF bounds = (proposedConstraints.Width == 1) ?
                            new SizeF(0, proposedConstraints.Height) :
                            new SizeF(proposedConstraints.Width, proposedConstraints.Height);
 
                        requiredSize = Size.Ceiling(measurementGraphics.MeasureString(Text, Font, bounds, stringFormat));
                    }
                }
                
            }
           
            requiredSize += bordersAndPadding;
 
            return requiredSize;
        }
 
        /// <devdoc>
        ///     This method is to be called by LabelDesigner, using private reflection, to get the location of the text snaplines.
        /// </devdoc>
        [
            // This method is called by LabelDesigner, using private reflection.
            System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")
        ]
        private int GetLeadingTextPaddingFromTextFormatFlags(){
            if( !IsHandleCreated ){
                return 0;
            }
 
            //If we are using GDI+ the code below will not work, except
            //if the style is FlatStyle.System since GDI will be used in that case.
            if (UseCompatibleTextRendering && FlatStyle != FlatStyle.System) {
                return 0;
            }
            
            using( WindowsGraphics wg = WindowsGraphics.FromHwnd(this.Handle) ){
                TextFormatFlags flags = CreateTextFormatFlags();
 
                if( (flags & TextFormatFlags.NoPadding ) == TextFormatFlags.NoPadding ){
                    wg.TextPadding = TextPaddingOptions.NoPadding;
                }
                else if( (flags & TextFormatFlags.LeftAndRightPadding ) == TextFormatFlags.LeftAndRightPadding ){
                    wg.TextPadding = TextPaddingOptions.LeftAndRightPadding;
                }
 
                using (WindowsFont wf = WindowsGraphicsCacheManager.GetWindowsFont(this.Font)) {
                    IntNativeMethods.DRAWTEXTPARAMS dtParams = wg.GetTextMargins(wf);
 
                    // This is actually leading margin.
                    return dtParams.iLeftMargin; 
                }
            }
        }
 
        private void ImageListRecreateHandle(object sender, EventArgs e) {
            if (IsHandleCreated) {
                Invalidate();
            }
        }
 
        /// <devdoc>
        ///     Specifies whether the control is willing to process mnemonics when hosted in an container ActiveX (Ax Sourcing).
        /// </devdoc>
        internal override bool IsMnemonicsListenerAxSourced
        {
            get{
                return true;
            }
        }
 
        /// <devdoc>
        ///    This method is required because the Label constructor needs to know if the control is OwnerDraw but it should
        ///    not call the virtual property for the following reason (from FxCop rule 'ConstructorsShouldNotCallBaseClassVirtualMethods'):
        ///    Virtual methods defined on the class should not be called from constructors. If a derived class has overridden
        ///    the method, the derived class version will be called (before the derived class constructor is called).
        /// </devdoc>
        internal bool IsOwnerDraw(){
            return FlatStyle != FlatStyle.System;
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.OnMouseEnter"]/*' />
        /// <internalonly/>
        /// <devdoc>
        ///    <para>
        ///       Raises the <see cref='System.Windows.Forms.Control.OnMouseEnter'/> event.
        ///    </para>
        /// </devdoc>
        protected override void OnMouseEnter(EventArgs e) {
            if (!controlToolTip && !DesignMode && AutoEllipsis && showToolTip && textToolTip != null) {
 
                // SECREVIEW: VSWhidbey 531915 - ToolTip should show in internet zone
                IntSecurity.AllWindows.Assert();
                try {
                    controlToolTip = true;
                    textToolTip.Show(WindowsFormsUtils.TextWithoutMnemonics(Text), this);
                }
                finally {
                    System.Security.CodeAccessPermission.RevertAssert();
                    controlToolTip = false;
                }
                    
            }
            base.OnMouseEnter(e);
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Button.OnMouseLeave"]/*' />
        /// <internalonly/>
        /// <devdoc>
        ///    <para>
        ///       Raises the <see cref='System.Windows.Forms.Control.OnMouseLeave'/> event.
        ///    </para>
        /// </devdoc>
        [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
        [SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
        protected override void OnMouseLeave(EventArgs e) {
            if (!controlToolTip && textToolTip != null && textToolTip.GetHandleCreated()) {
                    textToolTip.RemoveAll();
                    // SECREVIEW: VSWhidbey 531915 - ToolTip should show in internet zone
                    IntSecurity.AllWindows.Assert();
                    try {
                        textToolTip.Hide(this);
                    }
                    finally {
                        System.Security.CodeAccessPermission.RevertAssert();
                    }
            }
 
            base.OnMouseLeave(e);
        }
 
        private void OnFrameChanged(object o, EventArgs e) {
            if (Disposing || IsDisposed) {
                return;
            }
            if (IsHandleCreated && InvokeRequired)
            {
                BeginInvoke(new EventHandler(this.OnFrameChanged), o, e);
                return;
            }
 
            Invalidate();
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.OnFontChanged"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        protected override void OnFontChanged(EventArgs e) {
            MeasureTextCache.InvalidateCache();
            base.OnFontChanged(e);
            AdjustSize();
            Invalidate();
        }
 
        
        [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
        [SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
        protected override void OnHandleDestroyed(EventArgs e) {
            base.OnHandleDestroyed(e);
            if (textToolTip != null && textToolTip.GetHandleCreated())
            {
                textToolTip.DestroyHandle();
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.OnTextChanged"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        protected override void OnTextChanged(EventArgs e) {
  
            using(LayoutTransaction.CreateTransactionIf(AutoSize, ParentInternal, this, PropertyNames.Text)) {
                MeasureTextCache.InvalidateCache();
                base.OnTextChanged(e);
                AdjustSize();
                Invalidate();
            }
 
            if (AccessibilityImprovements.Level3 && LiveSetting != AutomationLiveSetting.Off) {
                AccessibilityObject.RaiseLiveRegionChanged();
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.OnTextAlignChanged"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        protected virtual void OnTextAlignChanged(EventArgs e) {
            EventHandler eh = Events[EVENT_TEXTALIGNCHANGED] as EventHandler;
            if (eh != null) {
                 eh(this, e);
            }
        }
 
        protected override void OnPaddingChanged(EventArgs e) {
            base.OnPaddingChanged(e);
            AdjustSize();
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.OnPaint"]/*' />
        /// <devdoc>
        /// </devdoc>
        /// <internalonly/>
        protected override void OnPaint(PaintEventArgs e) {
            Animate();
            ImageAnimator.UpdateFrames(this.Image);
 
            Rectangle face = LayoutUtils.DeflateRect(ClientRectangle, Padding);
            Image i = this.Image;
            if (i != null) {
                DrawImage(e.Graphics, i, face, RtlTranslateAlignment(ImageAlign));
            }
 
            Color color;
            IntPtr hdc = e.Graphics.GetHdc();
            try {
                using (WindowsGraphics wg = WindowsGraphics.FromHdc( hdc )) {
                    color = wg.GetNearestColor((Enabled) ? ForeColor : DisabledColor);
                }
            }
            finally {
                e.Graphics.ReleaseHdc();
            }
 
            // Do actual drawing
 
            if (AutoEllipsis) {
                Rectangle clientRect = this.ClientRectangle;
                Size preferredSize = GetPreferredSize(new Size(clientRect.Width, clientRect.Height));
                showToolTip = (clientRect.Width < preferredSize.Width || clientRect.Height < preferredSize.Height);
            }
            else {
                showToolTip = false;
            }
 
            if (UseCompatibleTextRendering) {
                using (StringFormat stringFormat = CreateStringFormat()) {
                    if (Enabled) {
                        using (Brush brush = new SolidBrush(color)) {
                            e.Graphics.DrawString(Text, Font, brush, face, stringFormat);
                        }
                    }
                    else {
                        ControlPaint.DrawStringDisabled(e.Graphics, Text, Font, color, face, stringFormat);
                    }
                }
            }
            else{
                TextFormatFlags flags = CreateTextFormatFlags();
 
                if (Enabled) {
                    TextRenderer.DrawText(e.Graphics, Text, Font, face, color, flags);
                }
                else {
                    //Theme specs -- if the backcolor is darker than Control, we use
                    // ControlPaint.Dark(backcolor).  Otherwise we use ControlDark.
                    // see VS#357226
                    Color disabledTextForeColor = TextRenderer.DisabledTextColor(this.BackColor);
                    TextRenderer.DrawText(e.Graphics, Text, Font, face, disabledTextForeColor, flags);
                }
            }
 
            base.OnPaint(e); // raise paint event
        }
 
        /// <devdoc>
        ///     Overriden by LinkLabel.
        /// </devdoc>
        internal virtual void OnAutoEllipsisChanged(/*EventArgs e*/) {
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.OnEnabledChanged"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        protected override void OnEnabledChanged(EventArgs e) {
            base.OnEnabledChanged(e);
            Animate();
        }
 
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.OnParentChanged"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        protected override void OnParentChanged(EventArgs e) {
            base.OnParentChanged(e);
            if (SelfSizing) {
                // VSWhidbey 368232: in the case of SelfSizing
                // we dont know what size to be until we're parented
                AdjustSize();
            }
            Animate();
        }
 
        protected override void OnRightToLeftChanged(EventArgs e) {
            MeasureTextCache.InvalidateCache();
            base.OnRightToLeftChanged(e);
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.OnVisibleChanged"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        protected override void OnVisibleChanged(EventArgs e) {
            base.OnVisibleChanged(e);
            Animate();
        }
 
        internal override void PrintToMetaFileRecursive(HandleRef hDC, IntPtr lParam, Rectangle bounds) {
            base.PrintToMetaFileRecursive(hDC, lParam, bounds);
 
            using (WindowsFormsUtils.DCMapping mapping = new WindowsFormsUtils.DCMapping(hDC, bounds)) {
                using(Graphics g = Graphics.FromHdcInternal(hDC.Handle)) {
                    ControlPaint.PrintBorder(g, new Rectangle(Point.Empty, Size), BorderStyle, Border3DStyle.SunkenOuter);
                }
            }
        }
 
 
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.ProcessMnemonic"]/*' />
        /// <internalonly/>
        /// <devdoc>
        ///    <para>
        ///       Overrides Control. This is called when the user has pressed an Alt-CHAR
        ///       key combination and determines if that combination is an interesting
        ///       mnemonic for this control.
        ///    </para>
        /// </devdoc>        
        [UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
        protected internal override bool ProcessMnemonic(char charCode) {
            if (UseMnemonic && IsMnemonic(charCode, Text) && CanProcessMnemonic()) {
                Control parent = ParentInternal;
                if (parent != null) {
                    // SECREVIEW: This assert is required because the call to SelectNextControl will generate a call to SetActiveControl which have a demand,
                    //            it is safe since no input from user code is processed while setting the active control originated this way.
                    //
                    IntSecurity.ModifyFocus.Assert();
                    try {
                        if (parent.SelectNextControl(this, true, false, true, false)) {
                            if (!parent.ContainsFocus) {
                                parent.Focus();
                            }
                        }
                    }
                    finally {
                        System.Security.CodeAccessPermission.RevertAssert();
                    }
                }
                return true;
            }
            return false;
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.SetBoundsCore"]/*' />
        /// <devdoc>
        ///    Overrides Control.setBoundsCore to enforce autoSize.
        /// </devdoc>
        /// <internalonly/>
        protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) {
            if ((specified & BoundsSpecified.Height) != BoundsSpecified.None)
                requestedHeight = height;
            if ((specified & BoundsSpecified.Width) != BoundsSpecified.None)
                requestedWidth = width;
 
            if (AutoSize && SelfSizing) {
                Size preferredSize = PreferredSize;
                width = preferredSize.Width;
                height = preferredSize.Height;
            }
 
            base.SetBoundsCore(x, y, width, height, specified);
 
            Debug.Assert(!AutoSize || (AutoSize && !SelfSizing) || Size == PreferredSize,
                "It is SetBoundsCore's responsibility to ensure Size = PreferredSize when AutoSize is true.");
        }
 
        private void ResetImage() {
            Image = null;
        }
 
        private bool ShouldSerializeImage() {
            return Properties.GetObject(PropImage) != null;
        }
 
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.SetToolTip"]/*' />
        /// <devdoc>
        ///     Called by ToolTip to poke in that Tooltip into this ComCtl so that the Native ChildToolTip is not exposed.
        /// </devdoc>
        /// <internalonly/>
        internal void SetToolTip(ToolTip toolTip) {
            if (toolTip != null && !controlToolTip) {
                controlToolTip = true;
            }
        }
 
        internal override bool SupportsUiaProviders {
            get {
                return AccessibilityImprovements.Level3 && !DesignMode;
            }
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.ToString"]/*' />
        /// <devdoc>
        ///    Returns a string representation for this control.
        /// </devdoc>
        /// <internalonly/>
        public override string ToString() {
            string s = base.ToString();
            return s + ", Text: " + Text;
        }
 
        /// <include file='doc\Label.uex' path='docs/doc[@for="Label.WndProc"]/*' />
        /// <internalonly/>
        /// <devdoc>
        ///    <para>
        ///       Overrides Control. This processes certain messages that the Win32 STATIC
        ///       class would normally override.
        ///    </para>
        /// </devdoc>
        [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
        protected override void WndProc(ref Message m) {
            switch (m.Msg) {
                case NativeMethods.WM_NCHITTEST:
                    // label returns HT_TRANSPARENT for everything, so all messages get
                    // routed to the parent.  Change this so we can tell what's going on.
                    //
                    Rectangle rectInScreen = this.RectangleToScreen(new Rectangle(0, 0, Width, Height));
                    Point pt = new Point(unchecked((int)(long)m.LParam));
                    m.Result = (IntPtr)((rectInScreen.Contains(pt) ? NativeMethods.HTCLIENT : NativeMethods.HTNOWHERE));
                    break;
 
                default:
                    base.WndProc(ref m);
                    break;
            }
        }
 
        protected override void RescaleConstantsForDpi(int deviceDpiOld, int deviceDpiNew) {
            base.RescaleConstantsForDpi(deviceDpiOld, deviceDpiNew);
            if (!DpiHelper.EnableDpiChangedHighDpiImprovements) {
                return;
            }
 
            // When Font is derived from parent, Dpi changed event required to clear the cache 
            // to recalculate the label size. 
            MeasureTextCache.InvalidateCache();
        }
 
        [System.Runtime.InteropServices.ComVisible(true)]
        internal class LabelAccessibleObject : ControlAccessibleObject {
 
            public LabelAccessibleObject(Label owner) : base(owner) {
            }
 
            /// <devdoc>
            ///    <para>[To be supplied.]</para>
            /// </devdoc>
            public override AccessibleRole Role {
                get {
                    AccessibleRole role = Owner.AccessibleRole;
                    if (role != AccessibleRole.Default) {
                        return role;
                    }
                    return AccessibleRole.StaticText;
                }
            }
 
            internal override bool IsIAccessibleExSupported() {
                if (AccessibilityImprovements.Level3) {
                    return true;
                }
 
                return base.IsIAccessibleExSupported();
            }
 
            internal override object GetPropertyValue(int propertyID) {
                if (propertyID == NativeMethods.UIA_ControlTypePropertyId) {
                    return NativeMethods.UIA_TextControlTypeId;
                }
 
                return base.GetPropertyValue(propertyID);
            }
        }
    }
 
 
 
    /// <include file='doc\Label.uex' path='docs/doc[@for="Label.LabelImageIndexer"]/*' />
    /// <internalonly/>
    /// <devdoc>
    ///    <para>
    ///            Override ImageList.Indexer to support Label's ImageList semantics.
    ///    </para>
    /// </devdoc>
    internal class LabelImageIndexer : ImageList.Indexer {
           private Label owner;
           private bool useIntegerIndex = true;
 
           public LabelImageIndexer(Label owner) {
              this.owner = owner;
           }
 
           public override ImageList ImageList {
                get { return (owner == null) ? null : owner.ImageList; }
 
                set { Debug.Assert(false, "Setting the image list in this class is not supported");}
           }
 
 
           public override string Key {
                get { return base.Key; }
                set {
                      base.Key = value;
                      useIntegerIndex = false;
                }
           }
 
           public override int Index {
                get { return base.Index; }
                set {
                      base.Index = value;
                      useIntegerIndex = true;
                }
 
           }
 
 
           public override int ActualIndex  {
                get {
                    if (useIntegerIndex) {
                        // The behavior of label is to return the last item in the Images collection
                        // if the index is currently set higher than the count.
                        return (Index < ImageList.Images.Count) ? Index : ImageList.Images.Count - 1;
                    }
                    else if (ImageList != null) {
                        return ImageList.Images.IndexOfKey(Key);
                    }
 
                    return -1;
                }
            }
 
 
        }
 
}