ButtonBase.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / WinForms / Managed / System / WinForms / ButtonBase.cs / 1305376 / ButtonBase.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 
namespace System.Windows.Forms {
    using System.Runtime.Serialization.Formatters; 
    using System.Runtime.InteropServices; 
    using System.Diagnostics;
    using System.Drawing.Imaging; 
    using System;
    using System.Security.Permissions;
    using System.Drawing.Drawing2D;
    using System.Drawing; 
    using System.Drawing.Design;
    using System.Windows.Forms.ButtonInternal; 
    using System.Windows.Forms.Layout; 
    using System.ComponentModel;
    using Microsoft.Win32; 
    using System.Globalization;
    using System.Runtime.Versioning;

    ///  
    /// 
    ///     
    ///       Implements the basic functionality required by a button control. 
    ///    
    ///  
    [
    ComVisible(true),
    ClassInterface(ClassInterfaceType.AutoDispatch),
    Designer("System.Windows.Forms.Design.ButtonBaseDesigner, " + AssemblyRef.SystemDesign) 
    ]
    public abstract class ButtonBase : Control { 
 
        private FlatStyle flatStyle                  = System.Windows.Forms.FlatStyle.Standard;
        private ContentAlignment imageAlign          = ContentAlignment.MiddleCenter; 
        private ContentAlignment textAlign           = ContentAlignment.MiddleCenter;
        private TextImageRelation textImageRelation  = TextImageRelation.Overlay;
        private ImageList.Indexer imageIndex         = new ImageList.Indexer();
        private FlatButtonAppearance flatAppearance; 
        private ImageList imageList;
        private Image image; 
 
        private const int FlagMouseOver             = 0x0001;
        private const int FlagMouseDown             = 0x0002; 
        private const int FlagMousePressed          = 0x0004;
        private const int FlagInButtonUp            = 0x0008;
        private const int FlagCurrentlyAnimating    = 0x0010;
        private const int FlagAutoEllipsis          = 0x0020; 
        private const int FlagIsDefault             = 0x0040;
        private const int FlagUseMnemonic           = 0x0080; 
        private const int FlagShowToolTip           = 0x0100; 
        private int state                           = 0;
 
        private ToolTip textToolTip;

        //this allows the user to disable visual styles for the button so that it inherits its background color
        private bool enableVisualStyleBackground = true; 

        private bool isEnableVisualStyleBackgroundSet = false; 
 
        /// 
        ///  
        ///    
        ///       Initializes a new instance of the  class.
        ///
        ///     
        /// 
        protected ButtonBase() { 
            // If Button doesn't want double-clicks, we should introduce a StandardDoubleClick style. 
            // Checkboxes probably want double-click's (#26120), and RadioButtons certainly do
            // (useful e.g. on a Wizard). 
            SetStyle( ControlStyles.SupportsTransparentBackColor |
                      ControlStyles.Opaque |
                      ControlStyles.ResizeRedraw |
                      ControlStyles.OptimizedDoubleBuffer | 
                      ControlStyles.CacheText | // We gain about 2% in painting by avoiding extra GetWindowText calls
                      ControlStyles.StandardClick, 
                      true); 
            // this class overrides GetPreferredSizeCore, let Control automatically cache the result
            SetState2(STATE2_USEPREFERREDSIZECACHE, true); 

            SetStyle(ControlStyles.UserMouse |
                     ControlStyles.UserPaint, OwnerDraw);
            SetFlag(FlagUseMnemonic, true); 
            SetFlag(FlagShowToolTip, false);
        } 
 
        /// 
        ///     This property controls the activation handling of bleedover for the text that 
        ///    extends beyond the width of the button. 
        /// 
        [
        SRCategory(SR.CatBehavior), 
        DefaultValue(false),
        Browsable(true), 
        EditorBrowsable(EditorBrowsableState.Always), 
        SRDescription(SR.ButtonAutoEllipsisDescr)
        ] 
        public bool AutoEllipsis {
            get {
                return GetFlag(FlagAutoEllipsis);
            } 

            set { 
                if (AutoEllipsis != value) { 
                    SetFlag(FlagAutoEllipsis, value);
                    if (value) { 
                        if (textToolTip == null) {
                            textToolTip  = new ToolTip();
                        }
                    } 
                    Invalidate();
                } 
            } 
        }
 
        /// 
        ///     Indicates whether the control is automatically resized to fit its contents
        /// 
        [Browsable(true), EditorBrowsable(EditorBrowsableState.Always), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public override bool AutoSize { 
            get { 
                return base.AutoSize;
            } 
            set {
                base.AutoSize = value;
                //don't show ellipsis if the control is autosized
                if (value) { 
                    AutoEllipsis = false;
                } 
            } 
        }
 
        /// 
        [SRCategory(SR.CatPropertyChanged), SRDescription(SR.ControlOnAutoSizeChangedDescr)]
        [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
        new public event EventHandler AutoSizeChanged 
        {
            add 
            { 
                base.AutoSizeChanged += value;
            } 
            remove
            {
                base.AutoSizeChanged -= value;
            } 
        }
 
 
        /// 
        ///  
        ///     The background color of this control. This is an ambient property and
        ///     will always return a non-null value.
        /// 
        [ 
        SRCategory(SR.CatAppearance),
        SRDescription(SR.ControlBackColorDescr) 
        ] 
        public override Color BackColor {
            get { 
                return base.BackColor;
            }
            set {
                if (DesignMode) { 
                    if (value != Color.Empty) {
                        PropertyDescriptor pd = TypeDescriptor.GetProperties(this)["UseVisualStyleBackColor"]; 
                        Debug.Assert(pd != null); 
                        if (pd != null) {
                            pd.SetValue(this, false); 
                        }
                    }
                }
                else { 
                    UseVisualStyleBackColor = false;
                } 
 
                base.BackColor = value;
            } 
        }

        /// 
        ///  
        ///     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. 
        ///  
        protected override Size DefaultSize {
            get { 
                return new Size(75, 23);
            }
        }
 
        /// 
        protected override CreateParams CreateParams { 
            [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] 
            get {
                CreateParams cp = base.CreateParams; 
                if (!OwnerDraw) {
                    cp.ExStyle &= ~NativeMethods.WS_EX_RIGHT;   // WS_EX_RIGHT overrides the BS_XXXX alignment styles

                    cp.Style |= NativeMethods.BS_MULTILINE; 

                    if (IsDefault) { 
                        cp.Style |= NativeMethods.BS_DEFPUSHBUTTON; 
                    }
 
                    ContentAlignment align = RtlTranslateContent(TextAlign);

                    if ((int)(align & WindowsFormsUtils.AnyLeftAlign) != 0) {
                        cp.Style |= NativeMethods.BS_LEFT; 
                    }
                    else if ((int)(align & WindowsFormsUtils.AnyRightAlign) != 0) { 
                        cp.Style |= NativeMethods.BS_RIGHT; 
                    }
                    else { 
                        cp.Style |= NativeMethods.BS_CENTER;

                    }
                    if ((int)(align & WindowsFormsUtils.AnyTopAlign) != 0) { 
                        cp.Style |= NativeMethods.BS_TOP;
                    } 
                    else if ((int)(align & WindowsFormsUtils.AnyBottomAlign) != 0) { 
                        cp.Style |= NativeMethods.BS_BOTTOM;
                    } 
                    else {
                        cp.Style |= NativeMethods.BS_VCENTER;
                    }
                } 
                return cp;
            } 
        } 

        ///  
        protected override ImeMode DefaultImeMode {
            get {
                return ImeMode.Disable;
            } 
        }
 
        ///  
        /// 
        ///    [To be supplied.] 
        /// 
        protected internal bool IsDefault {
            get {
                return GetFlag(FlagIsDefault); 
            }
            set { 
                if (GetFlag(FlagIsDefault) != value) { 
                    SetFlag(FlagIsDefault, value);
                    if (IsHandleCreated) { 
                        if (OwnerDraw) {
                            Invalidate();
                        }
                        else { 
                            UpdateStyles();
                        } 
                    } 
                }
            } 
        }

        /// 
        ///  
        ///    
        ///       Gets or 
        ///       sets 
        ///       the flat style appearance of the button control.
        ///     
        /// 
        [
        SRCategory(SR.CatAppearance),
        DefaultValue(FlatStyle.Standard), 
        Localizable(true),
        SRDescription(SR.ButtonFlatStyleDescr) 
        ] 
        public FlatStyle FlatStyle {
            get { 
                return flatStyle;
            }
            set {
                if (!ClientUtils.IsEnumValid(value, (int)value, (int)FlatStyle.Flat, (int)FlatStyle.System)){ 
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(FlatStyle));
                } 
                flatStyle = value; 
                LayoutTransaction.DoLayoutIf(AutoSize,ParentInternal, this, PropertyNames.FlatStyle);
                Invalidate(); 
                UpdateOwnerDraw();
            }
        }
 
        /// 
        ///  
        ///  
        [
        Browsable(true), 
        SRCategory(SR.CatAppearance),
        SRDescription(SR.ButtonFlatAppearance),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        ] 
        public FlatButtonAppearance FlatAppearance {
            get { 
                if (flatAppearance == null) { 
                    flatAppearance = new FlatButtonAppearance(this);
                } 

                return flatAppearance;
            }
        } 

        ///  
        ///  
        ///    
        ///       Gets or sets the image 
        ///       that is displayed on a button control.
        ///    
        /// 
        [ 
        SRDescription(SR.ButtonImageDescr),
        Localizable(true), 
        SRCategory(SR.CatAppearance) 
        ]
        public Image Image { 
            [ResourceExposure(ResourceScope.Machine)]
            [ResourceConsumption(ResourceScope.Machine)]
            get {
                if (image == null && imageList != null) { 
                    int actualIndex = imageIndex.ActualIndex;
 
                    // Pre-whidbey we used to use ImageIndex rather than ImageIndexer.ActualIndex. 
                    // ImageIndex clamps to the length of the image list.  We need to replicate
                    // this logic here for backwards compatibility.  (VSWhidbey #95780) 
                    // Per [....] we do not bake this into ImageIndexer because different controls
                    // treat this scenario differently.
                    if(actualIndex >= imageList.Images.Count) {
                        actualIndex = imageList.Images.Count - 1; 
                    }
 
                    if (actualIndex >= 0) { 
                        return imageList.Images[actualIndex];
                    } 
                    Debug.Assert(image == null, "We expect to be returning null.");
                }
                return image;
            } 
            set {
                if (Image != value) { 
                    StopAnimate(); 

                    image = value; 
                    if (image != null) {
                        ImageIndex = -1;
                        ImageList = null;
                    } 

                    LayoutTransaction.DoLayoutIf(AutoSize, ParentInternal, this, PropertyNames.Image); 
                    Animate(); 
                    Invalidate();
                } 
            }
        }

        ///  
        /// 
        ///     
        ///       Gets or sets the alignment of the image on the button control. 
        ///    
        ///  
        [
        DefaultValue(ContentAlignment.MiddleCenter),
        Localizable(true),
        SRDescription(SR.ButtonImageAlignDescr), 
        SRCategory(SR.CatAppearance)
        ] 
        public ContentAlignment ImageAlign { 
            get {
                return imageAlign; 
            }
            set {
                if (!WindowsFormsUtils.EnumValidator.IsValidContentAlignment(value)) {
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(ContentAlignment)); 
                }
                if(value != imageAlign) { 
                    imageAlign = value; 
                    LayoutTransaction.DoLayoutIf(AutoSize, ParentInternal, this, PropertyNames.ImageAlign);
                    Invalidate(); 
                }
            }
        }
 
        /// 
        ///  
        ///     
        ///       Gets or sets the image list index value of the image
        ///       displayed on the button control. 
        ///    
        /// 
        [
        TypeConverterAttribute(typeof(ImageIndexConverter)), 
        Editor("System.Windows.Forms.Design.ImageIndexEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
        Localizable(true), 
        DefaultValue(-1), 
        RefreshProperties(RefreshProperties.Repaint),
        SRDescription(SR.ButtonImageIndexDescr), 
        SRCategory(SR.CatAppearance)
        ]
        public int ImageIndex {
            get { 
                if (imageIndex.Index != -1 && imageList != null && imageIndex.Index >= imageList.Images.Count) {
                    return imageList.Images.Count - 1; 
                } 
                return imageIndex.Index;
            } 
            set {
                if (value < -1) {
                    throw new ArgumentOutOfRangeException("ImageIndex", SR.GetString(SR.InvalidLowBoundArgumentEx, "ImageIndex", (value).ToString(CultureInfo.CurrentCulture), (-1).ToString(CultureInfo.CurrentCulture)));
                } 
                if (imageIndex.Index != value) {
                    if (value != -1) { 
                        // Image.set calls ImageIndex = -1 
                        image = null;
                    } 

                    // If they were previously using keys - this should clear out the image key field.
                    imageIndex.Index = value;
                    Invalidate(); 
                }
            } 
        } 

         ///  
        /// 
        ///    
        ///       Gets or sets the image list index key of the image
        ///       displayed on the button control.  Note - setting this unsets the ImageIndex 
        ///    
        ///  
        [ 
        TypeConverterAttribute(typeof(ImageKeyConverter)),
        Editor("System.Windows.Forms.Design.ImageIndexEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)), 
        Localizable(true),
        DefaultValue(""),
        RefreshProperties(RefreshProperties.Repaint),
        SRDescription(SR.ButtonImageIndexDescr), 
        SRCategory(SR.CatAppearance)
        ] 
        public string ImageKey { 
            get {
                return imageIndex.Key; 
            }
            set {
                if (imageIndex.Key != value) {
                    if (value != null) { 
                        // Image.set calls ImageIndex = -1
                        image = null; 
                    } 

                    // If they were previously using indexes - this should clear out the image index field. 
                    imageIndex.Key = value;
                    Invalidate();
                }
            } 
        }
 
 
        /// 
        ///  
        ///    
        ///       Gets or sets the  that contains the  displayed on a button control.
        ///    
        ///  
        [
        DefaultValue(null), 
        SRDescription(SR.ButtonImageListDescr), 
        RefreshProperties(RefreshProperties.Repaint),
        SRCategory(SR.CatAppearance) 
        ]
        public ImageList ImageList {
            get {
                return imageList; 
            }
            set { 
                if (imageList != value) { 
                    EventHandler recreateHandler = new EventHandler(ImageListRecreateHandle);
                    EventHandler disposedHandler = new EventHandler(DetachImageList); 

                    // Detach old event handlers
                    //
                    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) {
                        image = null; // Image.set calls ImageList = null
                    } 

                    imageList = value; 
                    imageIndex.ImageList = value; 

                    // Wire up new event handlers 
                    //
                    if (value != null) {
                        value.RecreateHandle += recreateHandler;
                        value.Disposed += disposedHandler; 
                    }
 
 
                    Invalidate();
                } 
            }
        }

        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        new public ImeMode ImeMode { 
            get { 
                return base.ImeMode;
            } 
            set {
                base.ImeMode = value;
            }
        } 

        ///  
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler ImeModeChanged { 
            add {
                base.ImeModeChanged += value;
            }
            remove { 
                base.ImeModeChanged -= value;
            } 
        } 

        ///  
        ///     Specifies whether the control is willing to process mnemonics when hosted in an container ActiveX (Ax Sourcing).
        /// 
        internal override bool IsMnemonicsListenerAxSourced
        { 
            get{
                return true; 
            } 
        }
 
        /// 
        ///     
        ///         The area of the button encompassing any changes between the button's
        ///     resting appearance and its appearance when the mouse is over it. 
        ///     
        ///      
        ///         Consider overriding this property if you override any painting methods, 
        ///     or your button may not paint correctly or may have flicker. Returning
        ///     ClientRectangle is safe for correct painting but may still cause flicker. 
        ///     
        /// 
        internal virtual Rectangle OverChangeRectangle {
            get { 
                if (FlatStyle == FlatStyle.Standard) {
                    // this Rectangle will cause no Invalidation 
                    // can't use Rectangle.Empty because it will cause Invalidate(ClientRectangle) 
                    return new Rectangle(-1, -1, 1, 1);
                } 
                else {
                    return ClientRectangle;
                }
            } 
        }
 
        internal bool OwnerDraw { 
            get {
                return FlatStyle != FlatStyle.System; 
            }
        }

        ///  
        ///     
        ///         The area of the button encompassing any changes between the button's 
        ///     appearance when the mouse is over it but not pressed and when it is pressed. 
        ///     
        ///      
        ///         Consider overriding this property if you override any painting methods,
        ///     or your button may not paint correctly or may have flicker. Returning
        ///     ClientRectangle is safe for correct painting but may still cause flicker.
        ///      
        /// 
        internal virtual Rectangle DownChangeRectangle { 
            get { 
                return ClientRectangle;
            } 
        }

        internal bool MouseIsPressed {
            get { 
                return GetFlag(FlagMousePressed);
            } 
        } 

        // a "smart" version of mouseDown for Appearance.Button CheckBoxes & RadioButtons 
        // for these, instead of being based on the actual mouse state, it's based on the appropriate button state
        internal bool MouseIsDown {
            get {
                return GetFlag(FlagMouseDown); 
            }
        } 
 
        // a "smart" version of mouseOver for Appearance.Button CheckBoxes & RadioButtons
        // for these, instead of being based on the actual mouse state, it's based on the appropriate button state 
        internal bool MouseIsOver {
            get {
                return GetFlag(FlagMouseOver);
            } 
        }
 
 
        /// 
        ///     Indicates whether the tooltip should be shown 
        /// 
        internal bool ShowToolTip {
            get {
                return GetFlag(FlagShowToolTip); 
            }
            set { 
                SetFlag(FlagShowToolTip, value); 
            }
        } 

        [
        Editor("System.ComponentModel.Design.MultilineStringEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
        SettingsBindable(true) 
        ]
        public override string Text { 
            get { 
                return base.Text;
            } 
            set {
                base.Text = value;
            }
        } 

        ///  
        ///  
        ///    
        ///       Gets or sets the alignment of the text on the button control. 
        ///    
        /// 
        [
        DefaultValue(ContentAlignment.MiddleCenter), 
        Localizable(true),
        SRDescription(SR.ButtonTextAlignDescr), 
        SRCategory(SR.CatAppearance) 
        ]
        public virtual ContentAlignment TextAlign { 
            get {
                return textAlign;
            }
            set { 
                if (!WindowsFormsUtils.EnumValidator.IsValidContentAlignment(value)) {
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(ContentAlignment)); 
                } 
                if(value != textAlign) {
                    textAlign = value; 
                    LayoutTransaction.DoLayoutIf(AutoSize, ParentInternal, this, PropertyNames.TextAlign);
                    if (OwnerDraw) {
                        Invalidate();
                    } 
                    else {
                        UpdateStyles(); 
                    } 
                }
            } 
        }

        /// 
        [DefaultValue(TextImageRelation.Overlay), 
        Localizable(true),
        SRDescription(SR.ButtonTextImageRelationDescr), 
        SRCategory(SR.CatAppearance)] 
        public TextImageRelation TextImageRelation {
            get { 
                return textImageRelation;
            }
            set {
                if (!WindowsFormsUtils.EnumValidator.IsValidTextImageRelation(value)) { 
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(TextImageRelation));
                } 
                if(value != TextImageRelation) { 
                    textImageRelation = value;
                    LayoutTransaction.DoLayoutIf(AutoSize, ParentInternal, this, PropertyNames.TextImageRelation); 
                    Invalidate();
                }
            }
        } 

        ///  
        ///    Gets or sets a value indicating whether an ampersand (&) included in the text of 
        ///       the control.
        ///  
        [
        SRDescription(SR.ButtonUseMnemonicDescr),
        DefaultValue(true),
        SRCategory(SR.CatAppearance) 
        ]
        public bool UseMnemonic { 
            get { 
                return GetFlag(FlagUseMnemonic);
            } 

            set {
                SetFlag(FlagUseMnemonic, value);
                LayoutTransaction.DoLayoutIf(AutoSize, ParentInternal, this, PropertyNames.Text); 
                Invalidate();
            } 
        } 

        private void Animate() { 
            Animate(!DesignMode && Visible && Enabled && ParentInternal != null);
        }

        private void StopAnimate() { 
            Animate(false);
        } 
 
        private void Animate(bool animate) {
            if (animate != GetFlag(FlagCurrentlyAnimating)) { 
                if (animate) {
                    if (this.image != null) {
                        ImageAnimator.Animate(this.image, new EventHandler(this.OnFrameChanged));
                        SetFlag(FlagCurrentlyAnimating, animate); 
                    }
                } 
                else { 
                    if (this.image != null) {
                        ImageAnimator.StopAnimate(this.image, new EventHandler(this.OnFrameChanged)); 
                        SetFlag(FlagCurrentlyAnimating, animate);
                    }
                }
            } 
        }
 
        ///  
        protected override AccessibleObject CreateAccessibilityInstance() {
            return new ButtonBaseAccessibleObject(this); 
        }

        private void DetachImageList(object sender, EventArgs e) {
            ImageList = null; 
        }
 
        ///  
        /// 
        ///  
        /// 
        protected override void Dispose(bool disposing) {
            if (disposing) {
                StopAnimate(); 
                if (imageList != null) {
                    imageList.Disposed -= new EventHandler(this.DetachImageList); 
                } 
                //Dipose the tooltip if one present..
                if (textToolTip != null) { 
                    textToolTip.Dispose();
                    textToolTip = null;
                }
            } 
            base.Dispose(disposing);
        } 
 
        private bool GetFlag(int flag) {
            return ((state & flag) == flag); 
        }

        private void ImageListRecreateHandle(object sender, EventArgs e) {
            if (IsHandleCreated) { 
                Invalidate();
            } 
        } 

        ///  
        /// 
        /// 
        ///    
        ///       Raises the  event. 
        ///    
        ///  
        protected override void OnGotFocus(EventArgs e) { 
            base.OnGotFocus(e);
            Invalidate(); 
        }

        /// 
        ///  
        /// 
        ///     
        ///       Raises the  event. 
        ///    
        ///  
        protected override void OnLostFocus(EventArgs e) {
            base.OnLostFocus(e);

            // Hitting tab while holding down the space key. See ASURT 38669. 
            SetFlag(FlagMouseDown, false);
            CaptureInternal = false; 
 
            Invalidate();
        } 

        /// 
        /// 
        ///  
        ///    
        ///       Raises the  event. 
        ///     
        /// 
        protected override void OnMouseEnter(EventArgs eventargs) { 
            Debug.Assert(Enabled, "ButtonBase.OnMouseEnter should not be called if the button is disabled");
            SetFlag(FlagMouseOver, true);
            Invalidate();
            if (!DesignMode && AutoEllipsis && ShowToolTip && textToolTip != null) { 
                // SECREVIEW: VSWhidbey 531915 - ToolTip should show in internet zone
                IntSecurity.AllWindows.Assert(); 
                try { 
                    textToolTip.Show(WindowsFormsUtils.TextWithoutMnemonics(Text), this);
                } 
                finally {
                    System.Security.CodeAccessPermission.RevertAssert();
                }
            } 
            // call base last, so if it invokes any listeners that disable the button, we
            // don't have to recheck 
            base.OnMouseEnter(eventargs); 
        }
 
        /// 
        /// 
        /// 
        ///     
        ///       Raises the  event.
        ///     
        ///  
        protected override void OnMouseLeave(EventArgs eventargs) {
            SetFlag(FlagMouseOver, false); 
            if (textToolTip != null) {
                // SECREVIEW: VSWhidbey 531915 - ToolTip should show in internet zone
                IntSecurity.AllWindows.Assert();
                try { 
                    textToolTip.Hide(this);
                } 
                finally { 
                    System.Security.CodeAccessPermission.RevertAssert();
                } 
            }
            Invalidate();
            // call base last, so if it invokes any listeners that disable the button, we
            // don't have to recheck 
            base.OnMouseLeave(eventargs);
        } 
 
        /// 
        ///  
        /// 
        ///    
        ///       Raises the  event.
        ///     
        /// 
        protected override void OnMouseMove(MouseEventArgs mevent) { 
            Debug.Assert(Enabled, "ButtonBase.OnMouseMove should not be called if the button is disabled"); 
            if (mevent.Button != MouseButtons.None && GetFlag(FlagMousePressed)) {
                Rectangle r = ClientRectangle; 
                if (!r.Contains(mevent.X, mevent.Y)) {
                    if (GetFlag(FlagMouseDown)) {
                        SetFlag(FlagMouseDown, false);
                        Invalidate(DownChangeRectangle); 
                    }
                } 
                else { 
                    if (!GetFlag(FlagMouseDown)) {
                        SetFlag(FlagMouseDown, true); 
                        Invalidate(DownChangeRectangle);
                    }
                }
            } 
            // call base last, so if it invokes any listeners that disable the button, we
            // don't have to recheck 
            base.OnMouseMove(mevent); 
        }
 
        /// 
        /// 
        /// 
        ///     
        ///       Raises the  event.
        ///     
        ///  
        protected override void OnMouseDown(MouseEventArgs mevent) {
            Debug.Assert(Enabled, "ButtonBase.OnMouseDown should not be called if the button is disabled"); 
            if (mevent.Button == MouseButtons.Left) {
                SetFlag(FlagMouseDown, true);
                SetFlag(FlagMousePressed, true);
                Invalidate(DownChangeRectangle); 
            }
            // call base last, so if it invokes any listeners that disable the button, we 
            // don't have to recheck 
            base.OnMouseDown(mevent);
        } 

        /// 
        /// 
        ///  
        ///    
        ///       Raises the  event. 
        /// 
        ///    
        ///  
        protected override void OnMouseUp(MouseEventArgs mevent) {
            base.OnMouseUp(mevent);
        }
 
        /// 
        ///  
        ///  
        ///    
        ///       Used for quick re-painting of the button after the pressed state. 
        ///    
        /// 
        protected void ResetFlagsandPaint() {
            SetFlag(FlagMousePressed, false); 
            SetFlag(FlagMouseDown, false);
            Invalidate(DownChangeRectangle); 
            Update(); 
        }
 
        /// 
        ///     Central paint dispatcher to one of the three styles of painting.
        /// 
        private void PaintControl(PaintEventArgs pevent) { 
            Debug.Assert(GetStyle(ControlStyles.UserPaint), "Shouldn't be in PaintControl when control is not UserPaint style");
            Adapter.Paint(pevent); 
        } 

        public override Size GetPreferredSize( Size proposedSize ) { 
            // TableLayoutPanel passes width = 1 to get the minimum autosize width, since Buttons word-break text
            // that width would be the size of the widest caracter in the text.  We need to make the proposed size
            // unbounded.
            // This is the same as what Label does. 
            if( proposedSize.Width == 1 ) {
                proposedSize.Width = 0; 
            } 
            if( proposedSize.Height == 1 ) {
                proposedSize.Height = 0; 
            }
            return base.GetPreferredSize( proposedSize );
        }
 
        internal override Size GetPreferredSizeCore(Size proposedConstraints) {
            Size prefSize = Adapter.GetPreferredSizeCore(proposedConstraints); 
            return LayoutUtils.UnionSizes(prefSize + Padding.Size, MinimumSize); 
        }
 
        private ButtonBaseAdapter  _adapter = null;
        private FlatStyle          _cachedAdapterType;

        internal ButtonBaseAdapter Adapter { 
            get {
                if(_adapter == null || FlatStyle != _cachedAdapterType) { 
                    switch (FlatStyle) { 
                        case FlatStyle.Standard:
                            _adapter = CreateStandardAdapter(); 
                            break;
                        case FlatStyle.Popup:
                            _adapter = CreatePopupAdapter();
                            break; 
                        case FlatStyle.Flat:
                            _adapter = CreateFlatAdapter();; 
                            break; 
                        default:
                            Debug.Fail("Unsupported FlatStyle: '" + FlatStyle + '"'); 
                            break;
                    }
                    _cachedAdapterType = FlatStyle;
                } 
                return _adapter;
            } 
        } 

        internal virtual ButtonBaseAdapter CreateFlatAdapter() { 
            Debug.Fail("Derived classes need to provide a meaningful implementation.");
            return null;
        }
 
        internal virtual ButtonBaseAdapter CreatePopupAdapter() {
            Debug.Fail("Derived classes need to provide a meaningful implementation."); 
            return null; 
        }
 
        internal virtual ButtonBaseAdapter CreateStandardAdapter() {
            Debug.Fail("Derived classes need to provide a meaningful implementation.");
            return null;
        } 

        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)] 
        internal virtual StringFormat CreateStringFormat() {
            if( Adapter == null ) { 
                Debug.Fail("Adapter not expected to be null at this point");
                return new StringFormat();
            }
            return Adapter.CreateStringFormat(); 
        }
 
        internal virtual TextFormatFlags CreateTextFormatFlags() { 
            if( Adapter == null ) {
                Debug.Fail( "Adapter not expected to be null at this point" ); 
                return TextFormatFlags.Default;
            }
            return Adapter.CreateTextFormatFlags();
        } 

        private void OnFrameChanged(object o, EventArgs e) { 
            if (Disposing || IsDisposed) { 
                return;
            } 
            if (IsHandleCreated && InvokeRequired) {
                BeginInvoke(new EventHandler(this.OnFrameChanged), new object[]{o,e});
                return;
            } 

            Invalidate(); 
        } 

        ///  
        /// 
        ///    [To be supplied.]
        /// 
        protected override void OnEnabledChanged(EventArgs e) { 
            base.OnEnabledChanged(e);
            Animate(); 
            if (!Enabled) { 
                // disabled button is always "up"
                SetFlag(FlagMouseDown, false); 
                SetFlag(FlagMouseOver, false);
                Invalidate();
            }
        } 

        ///  
        ///  
        ///    [To be supplied.]
        ///  
        protected override void OnTextChanged(EventArgs e) {
            using(LayoutTransaction.CreateTransactionIf(AutoSize, ParentInternal, this, PropertyNames.Text)) {
                base.OnTextChanged(e);
                Invalidate(); 
            }
        } 
 
        /// 
        ///  
        /// 
        ///    
        ///       Raises the  event.
        /// 
        ///    
        ///  
        protected override void OnKeyDown(KeyEventArgs kevent) { 
            Debug.Assert(Enabled, "ButtonBase.OnKeyDown should not be called if the button is disabled");
            if (kevent.KeyData == Keys.Space) { 
                if (!GetFlag(FlagMouseDown)) {
                    SetFlag(FlagMouseDown, true);
                    // It looks like none of the "SPACE" key downs generate the BM_SETSTATE.
                    // This causes to not draw the focus rectangle inside the button and also 
                    // not paint the button as "un-depressed".
                    // 
                    if(!OwnerDraw) { 
                        SendMessage(NativeMethods.BM_SETSTATE, 1, 0);
                    } 
                    Invalidate(DownChangeRectangle);
                }
                kevent.Handled = true;
            } 
            // call base last, so if it invokes any listeners that disable the button, we
            // don't have to recheck 
            base.OnKeyDown(kevent); 
        }
 
        /// 
        /// 
        /// 
        ///     
        ///       Raises the  event.
        /// 
        ///     
        /// 
        protected override void OnKeyUp(KeyEventArgs kevent) { 
            if (GetFlag(FlagMouseDown) && !ValidationCancelled) {
                if (OwnerDraw) {
                    ResetFlagsandPaint();
                } 
                else {
                    SetFlag(FlagMousePressed, false); 
                    SetFlag(FlagMouseDown, false); 
                    SendMessage(NativeMethods.BM_SETSTATE, 0, 0);
                } 
                // VSWhidbey 498398: Breaking change: specifically filter out Keys.Enter and Keys.Space as the only
                // two keystrokes to execute OnClick.
                if (kevent.KeyCode == Keys.Enter || kevent.KeyCode == Keys.Space) {
                    OnClick(EventArgs.Empty); 
                }
                kevent.Handled = true; 
            } 
            // call base last, so if it invokes any listeners that disable the button, we
            // don't have to recheck 
            base.OnKeyUp(kevent);

        }
 
        /// 
        ///  
        ///  
        ///    
        ///       Raises the  event. 
        ///
        ///    
        /// 
        protected override void OnPaint(PaintEventArgs pevent) { 
            if( AutoEllipsis ){
                Size preferredSize = PreferredSize; 
                ShowToolTip = (this.ClientRectangle.Width < preferredSize.Width || this.ClientRectangle.Height < preferredSize.Height); 
            }
            else { 
                ShowToolTip = false;
            }

            if (GetStyle(ControlStyles.UserPaint)) { 
                Animate();
                ImageAnimator.UpdateFrames(); 
 
                PaintControl(pevent);
            } 
            base.OnPaint(pevent);
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        protected override void OnParentChanged(EventArgs e) {
            base.OnParentChanged(e); 
            Animate();
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        protected override void OnVisibleChanged(EventArgs e) {
            base.OnVisibleChanged(e); 
            Animate();
        }

        private void ResetImage() { 
            Image = null;
        } 
 
        private void SetFlag(int flag, bool value) {
            bool oldValue = ((state & flag) != 0); 

            if (value) {
                state |= flag;
            } 
            else {
                state &= ~flag; 
            } 

            if (OwnerDraw && (flag & FlagMouseDown) != 0 && value != oldValue) { 
                AccessibilityNotifyClients(AccessibleEvents.StateChange, -1);
            }
        }
 
        private bool ShouldSerializeImage() {
            return image != null; 
        } 

        private void UpdateOwnerDraw() { 
            if (OwnerDraw != GetStyle(ControlStyles.UserPaint)) {
                SetStyle(ControlStyles.UserMouse | ControlStyles.UserPaint, OwnerDraw);
                RecreateHandle();
            } 
        }
 
        ///  
        ///     Determines whether to use compatible text rendering engine (GDI+) or not (GDI).
        ///  
        [
        DefaultValue(false),
        SRCategory(SR.CatBehavior),
        SRDescription(SR.UseCompatibleTextRenderingDescr) 
        ]
        public bool UseCompatibleTextRendering { 
            get{ 
                return base.UseCompatibleTextRenderingInt;
            } 
            set{
                base.UseCompatibleTextRenderingInt = value;
            }
        } 

        ///  
        ///     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. 
        /// 
        internal override bool SupportsUseCompatibleTextRendering {
            get {
                return true; 
            }
        } 
 
        /// 
        ///  
        [
        SRCategory(SR.CatAppearance),
        SRDescription(SR.ButtonUseVisualStyleBackColorDescr)
        ] 
        public bool UseVisualStyleBackColor {
            get { 
                if (isEnableVisualStyleBackgroundSet || ((RawBackColor.IsEmpty) && (BackColor == SystemColors.Control))) 
                {
                	return enableVisualStyleBackground; 
                }
                else
                {
                	return false; 
                }
 
            } 
            set {
                isEnableVisualStyleBackgroundSet = true; 
                enableVisualStyleBackground = value;
                this.Invalidate();
            }
        } 

        private void ResetUseVisualStyleBackColor() { 
            isEnableVisualStyleBackgroundSet = false; 
            enableVisualStyleBackground = true;
            this.Invalidate(); 
        }

        private bool ShouldSerializeUseVisualStyleBackColor() {
            return isEnableVisualStyleBackgroundSet; 
        }
 
 
        /// 
        ///  
        ///    [To be supplied.]
        /// 

        [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] 
        protected override void WndProc(ref Message m) {
 
            switch (m.Msg) { 
                // NDPWhidbey 28043 -- we don't respect this because the code below eats BM_SETSTATE.
                // so we just invoke the click. 
                //
                case NativeMethods.BM_CLICK:
                    if (this is IButtonControl) {
                        ((IButtonControl)this).PerformClick(); 
                    }
                    else { 
                        OnClick(EventArgs.Empty); 
                    }
                    return; 
            }

            if (OwnerDraw) {
                switch (m.Msg) { 
                    case NativeMethods.BM_SETSTATE:
                        // Ignore BM_SETSTATE -- Windows gets confused and paints 
                        // things, even though we are ownerdraw. See ASURT 38669. 
                        break;
 
                    case NativeMethods.WM_KILLFOCUS:
                    case NativeMethods.WM_CANCELMODE:
                    case NativeMethods.WM_CAPTURECHANGED:
                        if (!GetFlag(FlagInButtonUp) && GetFlag(FlagMousePressed)) { 
                            SetFlag(FlagMousePressed, false);
 
                            if (GetFlag(FlagMouseDown)) { 
                                SetFlag(FlagMouseDown, false);
                                Invalidate(DownChangeRectangle); 
                            }
                        }
                        base.WndProc(ref m);
                        break; 

                    case NativeMethods.WM_LBUTTONUP: 
                    case NativeMethods.WM_MBUTTONUP: 
                    case NativeMethods.WM_RBUTTONUP:
                        try { 
                            SetFlag(FlagInButtonUp, true);
                            base.WndProc(ref m);
                        }
                        finally { 
                            SetFlag(FlagInButtonUp, false);
                        } 
                        break; 

                    default: 
                        base.WndProc(ref m);
                        break;
                }
            } 
            else {
                switch (m.Msg) { 
                    case NativeMethods.WM_REFLECT + NativeMethods.WM_COMMAND: 
                        if (NativeMethods.Util.HIWORD(m.WParam) == NativeMethods.BN_CLICKED && !ValidationCancelled) {
                            OnClick(EventArgs.Empty); 
                        }
                        break;
                    default:
                        base.WndProc(ref m); 
                        break;
                } 
            } 
        }
 
        /// 
        /// 
        [System.Runtime.InteropServices.ComVisible(true)]
        public class ButtonBaseAccessibleObject : ControlAccessibleObject { 

            ///  
            public ButtonBaseAccessibleObject(Control owner) : base(owner) { 
            }
 
            /// 
            [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
            public override void DoDefaultAction() {
                ((ButtonBase)Owner).OnClick(EventArgs.Empty); 
            }
 
            ///  
            public override AccessibleStates State {
                get { 
                    AccessibleStates state = base.State;

                    ButtonBase owner = (ButtonBase) Owner;
                    if (owner.OwnerDraw && owner.MouseIsDown) { 
                        state |= AccessibleStates.Pressed;
                    } 
 
                    return state;
                } 
            }

        }
    } 
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

Link Menu

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