TextBoxBase.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 / TextBoxBase.cs / 1305376 / TextBoxBase.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

/* 
 */ 
namespace System.Windows.Forms {
    using System.Text; 
    using System.Runtime.Serialization.Formatters;
    using System.Runtime.InteropServices;
    using System.Runtime.Remoting;
    using System.Diagnostics; 
    using System.Diagnostics.CodeAnalysis;
    using System; 
    using System.Collections; 
    using System.Collections.Specialized;
    using System.Security.Permissions; 
    using System.Windows.Forms.Design;
    using System.Windows.Forms.Layout;
    using System.ComponentModel.Design;
    using System.ComponentModel; 
    using System.Drawing;
    using System.Windows.Forms.Internal; 
    using System.Drawing.Design; 
    using Microsoft.Win32;
    using System.Reflection; 
    using System.Globalization;

    /// 
    ///  
    ///    
    ///       Implements the basic functionality required by text 
    ///       controls. 
    ///    
    ///  
    [
    ComVisible(true),
    ClassInterface(ClassInterfaceType.AutoDispatch),
    DefaultEvent("TextChanged"), 
    DefaultBindingProperty("Text"),
    Designer("System.Windows.Forms.Design.TextBoxBaseDesigner, " + AssemblyRef.SystemDesign) 
    ] 
    public abstract class TextBoxBase : Control {
 
        // The boolean properties for this control are contained in the textBoxFlags bit
        // vector.  We can store up to 32 boolean values in this one vector.  Here we
        // create the bitmasks for each bit in the vector.
        // 
        private static readonly int autoSize         = BitVector32.CreateMask();
        private static readonly int hideSelection    = BitVector32.CreateMask(autoSize); 
        private static readonly int multiline        = BitVector32.CreateMask(hideSelection); 
        private static readonly int modified         = BitVector32.CreateMask(multiline);
        private static readonly int readOnly         = BitVector32.CreateMask(modified); 
        private static readonly int acceptsTab       = BitVector32.CreateMask(readOnly);
        private static readonly int wordWrap         = BitVector32.CreateMask(acceptsTab);
        private static readonly int creatingHandle   = BitVector32.CreateMask(wordWrap);
        private static readonly int codeUpdateText   = BitVector32.CreateMask(creatingHandle); 
        private static readonly int shortcutsEnabled   = BitVector32.CreateMask(codeUpdateText);
        private static readonly int scrollToCaretOnHandleCreated = BitVector32.CreateMask(shortcutsEnabled); 
        private static readonly int setSelectionOnHandleCreated = BitVector32.CreateMask(scrollToCaretOnHandleCreated); 

        private static readonly object EVENT_ACCEPTSTABCHANGED      = new object(); 
        private static readonly object EVENT_BORDERSTYLECHANGED     = new object();
        private static readonly object EVENT_HIDESELECTIONCHANGED   = new object();
        private static readonly object EVENT_MODIFIEDCHANGED        = new object();
        private static readonly object EVENT_MULTILINECHANGED       = new object(); 
        private static readonly object EVENT_READONLYCHANGED        = new object();
 
        ///  
        /// 
        ///     The current border for this edit control. 
        /// 
        private BorderStyle borderStyle = System.Windows.Forms.BorderStyle.Fixed3D;

        ///  
        /// 
        ///     Controls the maximum length of text in the edit control. 
        ///  
        private int maxLength = 32767; // Win9X default, used for consistency
 
        /// 
        /// 
        ///     Used by the autoSizing code to help figure out the desired height of
        ///     the edit box. 
        /// 
        private int requestedHeight; 
        bool integralHeightAdjust = false; 

        //these indices are used to cache the values of the selection, by doing this 
        //if the handle isn't created yet, we don't force a creation.
        private int selectionStart = 0;
        private int selectionLength = 0;
 
        /// 
        ///     Controls firing of click event (Left click). 
        ///     This is used by TextBox, RichTextBox and MaskedTextBox, code was moved down from TextBox/RichTextBox 
        ///     but cannot make it as default behavior to avoid introducing breaking changes.
        ///  
        private  bool doubleClickFired = false;

        private static int[] shortcutsToDisable;
 
        // We store all boolean properties in here.
        // 
        private BitVector32 textBoxFlags = new BitVector32(); 

        ///  
        /// 
        ///     Creates a new TextBox control.  Uses the parent's current font and color
        ///     set.
        ///  
        internal TextBoxBase() : base() {
 
            // this class overrides GetPreferredSizeCore, let Control automatically cache the result 
            SetState2(STATE2_USEPREFERREDSIZECACHE, true);
 
            textBoxFlags[autoSize | hideSelection | wordWrap | shortcutsEnabled] = true;
            SetStyle(ControlStyles.FixedHeight, textBoxFlags[autoSize]);
            SetStyle(ControlStyles.StandardClick
                    | ControlStyles.StandardDoubleClick 
                    | ControlStyles.UseTextForAccessibility
                    | ControlStyles.UserPaint, false); 
 

            // cache requestedHeight. Note: Control calls DefaultSize (overridable) in the constructor 
            // to set the control's cached height that is returned when calling Height, so we just
            // need to get the cached height here.
            requestedHeight = Height;
        } 

        ///  
        ///  
        ///    
        ///       Gets or sets 
        ///       a value indicating whether pressing the TAB key
        ///       in a multiline text box control types
        ///       a TAB character in the control instead of moving the focus to the next control
        ///       in the tab order. 
        ///    
        ///  
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(false), 
        SRDescription(SR.TextBoxAcceptsTabDescr)
        ]
        public bool AcceptsTab {
            get { 
                return textBoxFlags[acceptsTab];
            } 
            set { 
                if (textBoxFlags[acceptsTab] != value) {
                    textBoxFlags[acceptsTab] = value; 
                    OnAcceptsTabChanged(EventArgs.Empty);
                }
            }
        } 

        ///  
        ///  
        ///    [To be supplied.]
        ///  
        [SRCategory(SR.CatPropertyChanged), SRDescription(SR.TextBoxBaseOnAcceptsTabChangedDescr)]
        public event EventHandler AcceptsTabChanged {
            add {
                Events.AddHandler(EVENT_ACCEPTSTABCHANGED, value); 
            }
            remove { 
                Events.RemoveHandler(EVENT_ACCEPTSTABCHANGED, value); 
            }
        } 


        /// 
        ///  
        ///    
        ///       Gets or sets a value indicating whether the following shortcuts should be enabled or not: 
        ///       Ctrl-Z, Ctrl-C, Ctrl-X, Ctrl-V, Ctrl-A, Ctrl-L, Ctrl-R, Ctrl-E, Ctrl-I, Ctrl-Y, 
        ///       Ctrl-BackSpace, Ctrl-Del, Shift-Del, Shift-Ins.
        ///     
        /// 
        [
        SRCategory(SR.CatBehavior),
        DefaultValue(true), 
        SRDescription(SR.TextBoxShortcutsEnabledDescr)
        ] 
        public virtual bool ShortcutsEnabled { 
            get {
                return textBoxFlags[shortcutsEnabled]; 
            }
            set {
                if (shortcutsToDisable == null) {
                    shortcutsToDisable = new int[] {(int)Shortcut.CtrlZ, (int)Shortcut.CtrlC, (int)Shortcut.CtrlX, 
                    (int)Shortcut.CtrlV, (int)Shortcut.CtrlA, (int)Shortcut.CtrlL, (int)Shortcut.CtrlR,
                    (int)Shortcut.CtrlE, (int)Shortcut.CtrlY, (int)Keys.Control + (int)Keys.Back, 
                    (int)Shortcut.CtrlDel, (int)Shortcut.ShiftDel, (int)Shortcut.ShiftIns, (int)Shortcut.CtrlJ}; 
                }
                textBoxFlags[shortcutsEnabled] = value; 
            }
        }

        ///  
        /// 
        ///     Implements the  property. 
        ///  
        [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { 
            // First call parent's ProcessCmdKey, since we don't to eat up
            // the shortcut key we are not supported in TextBox.
            bool returnedValue = base.ProcessCmdKey(ref msg, keyData);
 
            if (this.ShortcutsEnabled == false) {
                foreach (int shortcutValue in shortcutsToDisable) { 
                    if ((int)keyData == shortcutValue || 
                        (int)keyData == (shortcutValue | (int)Keys.Shift)) {
                        return true; 
                    }
                }
            }
            // 
            // There are a few keys that change the alignment of the text, but that
            // are not ignored by the native control when the ReadOnly property is set. 
            // We need to workaround that. 
            if (textBoxFlags[readOnly]) {
                int k = (int)keyData; 
                if (k == (int)Shortcut.CtrlL        // align left
                    || k == (int)Shortcut.CtrlR     // align right
                    || k == (int)Shortcut.CtrlE     // align centre
                    || k == (int)Shortcut.CtrlJ) {  // align justified 
                    return true;
                } 
            } 

            return returnedValue; 
        }

        /// 
        ///  
        ///    
        ///       Gets or sets a value indicating whether the size 
        ///       of the control automatically adjusts when the font assigned to the control 
        ///       is changed.
        /// 
        ///       Note: this works differently than other Controls' AutoSize, so we're hiding
        ///       it to avoid confusion.
        ///    
        ///  
        [
        SRCategory(SR.CatBehavior), 
        DefaultValue(true), 
        Localizable(true),
        SRDescription(SR.TextBoxAutoSizeDescr), 
        RefreshProperties(RefreshProperties.Repaint),
        Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]

        public override bool AutoSize { 
            get {
                return textBoxFlags[autoSize]; 
            } 
            set {
                // Note that we intentionally do not call base.  TextBoxes size themselves by 
                // overriding SetBoundsCore (old RTM code).  We let CommonProperties.GetAutoSize
                // continue to return false to keep our LayoutEngines from messing with TextBoxes.
                // This is done for backwards compatibility since the new AutoSize behavior differs.
                if (textBoxFlags[autoSize] != value) { 
                    textBoxFlags[autoSize] = value;
 
                    // AutoSize's effects are ignored for a multi-line textbox 
                    //
                    if (!Multiline) { 
                        SetStyle(ControlStyles.FixedHeight, value);
                        AdjustHeight(false);
                    }
 
                    OnAutoSizeChanged(EventArgs.Empty);
                } 
            } 
        }
 
        /// 
        /// 
        ///    
        ///       Gets or sets 
        ///       the background color of the control.
        ///     
        ///  
        [
        SRCategory(SR.CatAppearance), 
        DispId(NativeMethods.ActiveX.DISPID_BACKCOLOR),
        SRDescription(SR.ControlBackColorDescr)
        ]
        public override Color BackColor { 
            get {
                if (ShouldSerializeBackColor()) { 
                    return base.BackColor; 
                }
                else if (this.ReadOnly) { 
                    return SystemColors.Control;
                } else {
                    return SystemColors.Window;
                } 
            }
            set { 
                base.BackColor = value; 
            }
        } 


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

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

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

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

        /// 
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        new public event EventHandler BackgroundImageLayoutChanged {
            add { 
                base.BackgroundImageLayoutChanged += value; 
            }
            remove { 
                base.BackgroundImageLayoutChanged -= value;
            }
        }
 
        /// 
        ///  
        ///     
        ///       Gets or sets the border type
        ///       of the text box control. 
        ///    
        /// 
        [
        SRCategory(SR.CatAppearance), 
        DefaultValue(BorderStyle.Fixed3D),
        DispId(NativeMethods.ActiveX.DISPID_BORDERSTYLE), 
        SRDescription(SR.TextBoxBorderDescr) 
        ]
        public BorderStyle BorderStyle { 
            get {
                return borderStyle;
            }
 
            set {
                if (borderStyle != value) { 
                    //verify that 'value' is a valid enum type... 

                    //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));
                    }
 
                    borderStyle = value;
                    UpdateStyles(); 
                    RecreateHandle(); 

                    // PreferredSize depends on BorderStyle : thru CreateParams.ExStyle in User32!AdjustRectEx. 
                    // So when the BorderStyle changes let the parent of this control know about it.
                    using(LayoutTransaction.CreateTransactionIf(AutoSize, ParentInternal, this, PropertyNames.BorderStyle)) {
                        OnBorderStyleChanged(EventArgs.Empty);
                    } 
                }
            } 
        } 

        ///  
        /// 
        ///    [To be supplied.]
        /// 
        [SRCategory(SR.CatPropertyChanged), SRDescription(SR.TextBoxBaseOnBorderStyleChangedDescr)] 
        public event EventHandler BorderStyleChanged {
            add { 
                Events.AddHandler(EVENT_BORDERSTYLECHANGED, value); 
            }
            remove { 
                Events.RemoveHandler(EVENT_BORDERSTYLECHANGED, value);
            }
        }
 
        internal virtual bool CanRaiseTextChangedEvent {
            get { 
                return true; 
            }
        } 

        /// 
        ///     Specifies whether the ImeMode can be enabled - See also ImeModeBase.
        ///  
        protected override bool CanEnableIme {
            get { 
                Debug.WriteLineIf( CompModSwitches.ImeMode.Level >= TraceLevel.Info, "Inside get_CanEnableIme(), this = " + this ); 
                Debug.Indent();
 
                bool canEnable = !( this.ReadOnly || this.PasswordProtect ) && base.CanEnableIme;

                Debug.WriteLineIf( CompModSwitches.ImeMode.Level >= TraceLevel.Info, "Value = " + canEnable );
                Debug.Unindent(); 

                return canEnable; 
            } 
        }
 
        /// 
        /// 
        ///    
        ///       Gets a value 
        ///       indicating whether the user can undo the previous operation in a text box control.
        ///     
        ///  
        [
        SRCategory(SR.CatBehavior), 
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        SRDescription(SR.TextBoxCanUndoDescr)
        ] 
        public bool CanUndo {
            get { 
                if (IsHandleCreated) { 
                    bool b;
                    b = unchecked( (int) (long)SendMessage(NativeMethods.EM_CANUNDO, 0, 0)) != 0; 

                    return b;
                }
                return false; 
            }
        } 
 
        /// 
        ///  
        /// 
        ///    
        ///       Returns the parameters needed to create the handle. Inheriting classes
        ///       can override this to provide extra functionality. They should not, 
        ///       however, forget to call base.getCreateParams() first to get the struct
        ///       filled up with the basic info. 
        ///     
        /// 
        protected override CreateParams CreateParams { 
            [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
            get {
                CreateParams cp = base.CreateParams;
                cp.ClassName = "EDIT"; 
                cp.Style |= NativeMethods.ES_AUTOHSCROLL | NativeMethods.ES_AUTOVSCROLL;
                if (!textBoxFlags[hideSelection]) cp.Style |= NativeMethods.ES_NOHIDESEL; 
                if (textBoxFlags[readOnly]) cp.Style |= NativeMethods.ES_READONLY; 
                cp.ExStyle &= (~NativeMethods.WS_EX_CLIENTEDGE);
                cp.Style &= (~NativeMethods.WS_BORDER); 

                switch (borderStyle) {
                    case BorderStyle.Fixed3D:
                        cp.ExStyle |= NativeMethods.WS_EX_CLIENTEDGE; 
                        break;
                    case BorderStyle.FixedSingle: 
                        cp.Style |= NativeMethods.WS_BORDER; 
                        break;
                } 
                if (textBoxFlags[multiline]) {
                    cp.Style |= NativeMethods.ES_MULTILINE;
                    if (textBoxFlags[wordWrap]) cp.Style &= ~NativeMethods.ES_AUTOHSCROLL;
                } 

                return cp; 
            } 
        }
 
        /// 
        /// 
        ///     This property is overridden and hidden from statement completion
        ///     on controls that are based on Win32 Native Controls. 
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)] 
        protected override bool DoubleBuffered { 
            get {
                return base.DoubleBuffered; 
            }
            set {
                base.DoubleBuffered = value;
            } 
        }
 
        ///  
        /// 
        ///    [To be supplied.] 
        /// 
        [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
        public new event EventHandler Click {
            add { 
                base.Click += value;
            } 
            remove { 
                base.Click -= value;
            } 
        }

        /// 
        ///  
        ///    [To be supplied.]
        ///  
        [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)] 
        public new event MouseEventHandler MouseClick {
            add { 
                base.MouseClick += value;
            }
            remove {
                base.MouseClick -= value; 
            }
        } 
 
        /// 
        protected override Cursor DefaultCursor { 
            get {
                return Cursors.IBeam;
            }
        } 

        ///  
        ///  
        ///     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(100, PreferredHeight); 
            }
        } 
 
        /// 
        ///  
        ///    
        ///       Gets or sets the foreground color of the control.
        ///    
        ///  
        [
        SRCategory(SR.CatAppearance), 
        DispId(NativeMethods.ActiveX.DISPID_FORECOLOR), 
        SRDescription(SR.ControlForeColorDescr)
        ] 
        public override Color ForeColor {
            get {
                if (ShouldSerializeForeColor()) {
                    return base.ForeColor; 
                }
                else { 
                    return SystemColors.WindowText; 
                }
            } 
            set {
                base.ForeColor = value;
            }
        } 

        ///  
        ///  
        ///    
        ///       Gets or sets a value indicating whether the selected 
        ///       text in the text box control remains highlighted when the control loses focus.
        ///    
        /// 
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(true), 
        SRDescription(SR.TextBoxHideSelectionDescr) 
        ]
        public bool HideSelection { 
            get {
                return textBoxFlags[hideSelection];
            }
 
            set {
                if (textBoxFlags[hideSelection] != value) { 
                    textBoxFlags[hideSelection] = value; 
                    RecreateHandle();
                    OnHideSelectionChanged(EventArgs.Empty); 
                }
            }
        }
 
        /// 
        ///  
        ///    [To be supplied.] 
        /// 
        [SRCategory(SR.CatPropertyChanged), SRDescription(SR.TextBoxBaseOnHideSelectionChangedDescr)] 
        public event EventHandler HideSelectionChanged {
            add {
                Events.AddHandler(EVENT_HIDESELECTIONCHANGED, value);
            } 
            remove {
                Events.RemoveHandler(EVENT_HIDESELECTIONCHANGED, value); 
            } 
        }
 
        /// 
        ///     Internal version of ImeMode property.  The ImeMode of TextBoxBase controls depend on its IME restricted
        ///     mode which is determined by the CanEnableIme property which checks whether the control is in Password or
        ///     ReadOnly mode. 
        /// 
        protected override ImeMode ImeModeBase { 
            get { 
                if( DesignMode ) {
                    return base.ImeModeBase; 
                }

                Debug.WriteLineIf( CompModSwitches.ImeMode.Level >= TraceLevel.Info, "Inside get_ImeModeInternal(), this = " + this );
                Debug.Indent(); 

                ImeMode imeMode = CanEnableIme ? base.ImeModeBase : ImeMode.Disable; 
 
                Debug.WriteLineIf( CompModSwitches.ImeMode.Level >= TraceLevel.Info, "Value = " + imeMode );
                Debug.Unindent(); 

                return imeMode;
            }
            set { 
                base.ImeModeBase = value;
            } 
        } 

        ///  
        /// 
        ///    
        ///       Gets or
        ///       sets the lines of text in an text box control. 
        ///    
        ///  
        [ 
        SRCategory(SR.CatAppearance),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        MergableProperty(false),
        Localizable(true),
        SRDescription(SR.TextBoxLinesDescr),
        Editor("System.Windows.Forms.Design.StringArrayEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)) 
        ]
        public string[] Lines { 
            get { 
                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;
                }
 
                // Corner case -- last character in Text is a new line; need to add blank line to list
                if (text.Length > 0 && (text[text.Length - 1] == '\r' || text[text.Length - 1] == '\n')) 
                    list.Add(""); 

                return(string[]) list.ToArray(typeof(string)); 
            }
            [
                SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters") // We append a new line to the Text property.
                                                                                                            // Don't localize the new line character. 
            ]
            set { 
                //unparse this string list... 
                if (value != null && value.Length > 0) {
 
                    // Work Item #40689:
                    // Using a StringBuilder instead of a String
                    // speeds things up approx 150 times
                    StringBuilder text = new StringBuilder(value[0]); 
                    for (int i=1; i < value.Length; ++i) {
                        text.Append("\r\n"); 
                        text.Append(value[i]); 
                    }
                    Text = text.ToString(); 
                }
                else {
                    Text = "";
                } 
            }
        } 
 
        /// 
        ///  
        ///    
        ///       Gets or sets the maximum number of
        ///       characters the user can type into the text box control.
        ///     
        /// 
        [ 
        SRCategory(SR.CatBehavior), 
        DefaultValue(32767),
        Localizable(true), 
        SRDescription(SR.TextBoxMaxLengthDescr)
        ]
        public virtual int MaxLength {
            get { 
                return maxLength;
            } 
            set { 
                if (value < 0) {
                    throw new ArgumentOutOfRangeException("MaxLength", SR.GetString(SR.InvalidLowBoundArgumentEx, "MaxLength", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); 
                }

                if (maxLength != value) {
                    maxLength = value; 
                    UpdateMaxLength();
                } 
            } 
        }
 
        /// 
        /// 
        ///    
        ///       Gets or sets a value that indicates that the text box control has been modified by the user since 
        ///       the control was created or its contents were last set.
        ///     
        ///  
        [
        SRCategory(SR.CatBehavior), 
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        SRDescription(SR.TextBoxModifiedDescr)
        ] 
        public bool Modified {
            get { 
                if (IsHandleCreated) { 
                    bool curState = (0 != unchecked( (int) (long)SendMessage(NativeMethods.EM_GETMODIFY, 0, 0)));
                    if (textBoxFlags[modified] != curState) { 
                        // VSWhidbey 94719 - raise ModifiedChanged event.  See WmReflectCommand for more info.
                        textBoxFlags[modified] = curState;
                        OnModifiedChanged(EventArgs.Empty);
                    } 
                    return curState;
                } 
                else{ 
                    return textBoxFlags[modified];
                } 

            }

            set { 
                if (Modified != value) {
                    if (IsHandleCreated) { 
                        SendMessage(NativeMethods.EM_SETMODIFY, value ? 1 : 0, 0); 
                        // VSWhidbey 94719 - must maintain this state always in order for the
                        // test in the Get method to work properly. 
                    }

                    textBoxFlags[modified] = value;
                    OnModifiedChanged(EventArgs.Empty); 
                }
            } 
        } 

        ///  
        /// 
        ///    [To be supplied.]
        /// 
        [SRCategory(SR.CatPropertyChanged), SRDescription(SR.TextBoxBaseOnModifiedChangedDescr)] 
        public event EventHandler ModifiedChanged {
            add { 
                Events.AddHandler(EVENT_MODIFIEDCHANGED, value); 
            }
            remove { 
                Events.RemoveHandler(EVENT_MODIFIEDCHANGED, value);
            }
        }
 
        /// 
        ///  
        ///     
        ///       Gets or sets a value indicating whether this
        ///       is a multiline text box control. 
        ///    
        /// 
        [
        SRCategory(SR.CatBehavior), 
        DefaultValue(false),
        Localizable(true), 
        SRDescription(SR.TextBoxMultilineDescr), 
        RefreshProperties(RefreshProperties.All)
        ] 
        public virtual bool Multiline {
            get {
                return textBoxFlags[multiline];
            } 
            set {
                if (textBoxFlags[multiline] != value) { 
                    using (LayoutTransaction.CreateTransactionIf(AutoSize, ParentInternal, this, PropertyNames.Multiline)) { 
                        textBoxFlags[multiline] = value;
 
                        if (value) {
                            // Multi-line textboxes do not have fixed height
                            //
                            SetStyle(ControlStyles.FixedHeight, false); 
                        }
                        else { 
                            // Single-line textboxes may have fixed height, depending on AutoSize 
                            SetStyle(ControlStyles.FixedHeight, AutoSize);
                        } 

                        RecreateHandle();
                        AdjustHeight(false);
                        OnMultilineChanged(EventArgs.Empty); 
                    }
                } 
            } 
        }
 
        /// 
        /// 
        ///    [To be supplied.]
        ///  
        [SRCategory(SR.CatPropertyChanged), SRDescription(SR.TextBoxBaseOnMultilineChangedDescr)]
        public event EventHandler MultilineChanged { 
            add { 
                Events.AddHandler(EVENT_MULTILINECHANGED, value);
            } 
            remove {
                Events.RemoveHandler(EVENT_MULTILINECHANGED, value);
            }
        } 

        ///  
        ///  
        ///    
        ///    [To be supplied.] 
        ///    
        /// 
        [
        Browsable(false), 
        EditorBrowsable(EditorBrowsableState.Never),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) 
        ] 
        public new Padding Padding {
            get { return base.Padding; } 
            set { base.Padding = value;}
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        [
        Browsable(false), 
        EditorBrowsable(EditorBrowsableState.Never),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        SRCategory(SR.CatLayout), SRDescription(SR.ControlOnPaddingChangedDescr)
        ] 
        public new event EventHandler PaddingChanged {
            add { 
                base.PaddingChanged += value; 
            }
            remove { 
                base.PaddingChanged -= value;
            }
        }
 
        /// 
        ///     Determines if the control is in password protect mode.  This is overridden in TextBox and 
        ///     MaskedTextBox and is false by default so RichTextBox that doesn't support Password doesn't 
        ///     have to care about this.
        ///  
        virtual internal bool PasswordProtect
        {
            get {
                return false; 
            }
        } 
 
        /// 
        ///  
        ///    
        ///       Returns the preferred
        ///       height for a single-line text box.
        ///     
        /// 
        [ 
        SRCategory(SR.CatLayout), 
        Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        SRDescription(SR.TextBoxPreferredHeightDescr)
        ]
        public int PreferredHeight {
            get { 
                // VSWhidbey 523205: COMPAT we must return the same busted height we did in Everett, even
                // if it doesnt take multiline and word wrap into account.  For better accuracy and/or wrapping use 
                // GetPreferredSize instead. 
                int height = FontHeight;
                if (borderStyle != BorderStyle.None) { 
                    height += SystemInformation.BorderSize.Height * 4 + 3;
                }
                return height;
            } 
        }
 
        //  GetPreferredSizeCore 
        //  VSWhidbey 523205: This method can return a different value than PreferredHeight!  It properly handles
        //  border style + multiline and wordwrap. 

        internal override Size GetPreferredSizeCore(Size proposedConstraints)
        {
            // 3px vertical space is required between the text and the border to keep the last 
            // line from being clipped.
            // This 3 pixel size was added in everett and we do this to maintain compat. 
            // old everett behavior was FontHeight + [SystemInformation.BorderSize.Height * 4 + 3] 
            // however the [ ] was only added if borderstyle was not none.
            Size bordersAndPadding = SizeFromClientSize(Size.Empty) + Padding.Size; 

            if (BorderStyle != BorderStyle.None) {
                bordersAndPadding += new Size(0, 3);
            } 

            if (BorderStyle == BorderStyle.FixedSingle) { 
                // VSWhidbey 321520: bump these by 2px to match BorderStyle.Fixed3D - they'll be omitted from the SizeFromClientSize call. 
                bordersAndPadding.Width +=2;
                bordersAndPadding.Height +=2; 
            }
            // Reduce constraints by border/padding size
            proposedConstraints -= bordersAndPadding;
 
            // Fit the text to the remaining space
            // Fix for Dev10 bug 590621: 
            // in text box, we don't interpret ampersand (&) as a directive to underscore the character that follows. 
            TextFormatFlags format = TextFormatFlags.NoPrefix;
            if(!Multiline) { 
                format |= TextFormatFlags.SingleLine;
            } else if(WordWrap) {
                format |= TextFormatFlags.WordBreak;
            } 
            Size textSize = TextRenderer.MeasureText(this.Text, this.Font, proposedConstraints, format);
 
            // We use this old computation as a lower bound to ensure backwards compatibility. 
            textSize.Height = Math.Max(textSize.Height, FontHeight);
            Size preferredSize = textSize + bordersAndPadding; 
            return preferredSize;
        }

        ///  
        ///     Get the currently selected text start position and length.  Use this method internally
        ///     to avoid calling SelectionStart + SelectionLength each of which does essentially the 
        ///     same (save one message round trip). 
        /// 
        internal void GetSelectionStartAndLength( out int start, out int length ){ 
            int end = 0;

            if( !IsHandleCreated ) {
                // It is possible that the cached values are no longer valid if the Text has been changed 
                // while the control does not have a handle. We need to return valid values.  We also need
                // to keep the old cached values in case the Text is changed again making the cached values 
                // valid again.  See VSW#495181. 
                AdjustSelectionStartAndEnd( this.selectionStart, this.selectionLength, out start, out end, -1 );
                length = end - start; 
            }
            else {
                start = 0;
                UnsafeNativeMethods.SendMessage( new HandleRef( this, Handle ), NativeMethods.EM_GETSEL, ref start, ref end ); 

                //Here, we return the max of either 0 or the # returned by 
                //the windows call.  This eliminates a problem on nt4 where 
                // a huge negative # is being returned.
                // 
                start = Math.Max( 0, start );
                // ditto for end
                end = Math.Max( 0, end );
 
                if( this.SelectionUsesDbcsOffsetsInWin9x && Marshal.SystemDefaultCharSize == 1 ) {
                    // When processing EM_GETSEL, EDIT control returns byte offsets instead of character offsets, this 
                    // makes a difference in unicode code pages like Japanese.  We need to adjust the offsets. 
                    ToUnicodeOffsets( WindowText, ref start, ref end );
                } 

                length = end - start;
            }
 
#if DEBUG
            { 
                string t = WindowText; 
                int len;
 
                end = start + length - 1;

                if (t == null) {
                    len = 0; 
                }
                else { 
                    len = t.Length; 
                }
 
                Debug.Assert(end <= len, "SelectionEnd is outside the set of valid caret positions for the current WindowText (end ="
                                + end + ", WindowText.Length =" + len +")");
            }
#endif 
        }
 
        ///  
        /// 
        ///     
        ///       Gets or sets a value indicating whether text in the text box is read-only.
        ///    
        /// 
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(false), 
        RefreshProperties(RefreshProperties.Repaint), 
        SRDescription(SR.TextBoxReadOnlyDescr)
        ] 
        public bool ReadOnly {
            get {
                return textBoxFlags[readOnly];
            } 
            set {
                if (textBoxFlags[readOnly] != value) { 
                    textBoxFlags[readOnly] = value; 
                    if (IsHandleCreated) {
                        SendMessage(NativeMethods.EM_SETREADONLY, value? -1: 0, 0); 
                    }

                    OnReadOnlyChanged(EventArgs.Empty);
 
                    VerifyImeRestrictedModeChanged();
                } 
            } 
        }
 
        /// 
        /// 
        ///    [To be supplied.]
        ///  
        [SRCategory(SR.CatPropertyChanged), SRDescription(SR.TextBoxBaseOnReadOnlyChangedDescr)]
        public event EventHandler ReadOnlyChanged { 
            add { 
                Events.AddHandler(EVENT_READONLYCHANGED, value);
            } 
            remove {
                Events.RemoveHandler(EVENT_READONLYCHANGED, value);
            }
        } 

        ///  
        ///  
        ///    
        ///       The currently selected text in the control. 
        ///    
        /// 
        [
        SRCategory(SR.CatAppearance), 
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        SRDescription(SR.TextBoxSelectedTextDescr) 
        ]
        public virtual string SelectedText { 
            get {
                int selStart, selLength;
                GetSelectionStartAndLength( out selStart, out selLength );
                return Text.Substring(selStart, selLength); 
            }
            set { 
                SetSelectedTextInternal(value, true); 
            }
        } 

        /// 
        ///     Replaces the selected text with the one passed in.
        ///  
        internal virtual void SetSelectedTextInternal(string text, bool clearUndo){
            if (!IsHandleCreated) { 
                CreateHandle(); 
            }
 
            if( text == null ){
                text = "";
            }
 
            // The EM_LIMITTEXT message limits only the text the user can enter. It does not affect any text
            // already in the edit control when the message is sent, nor does it affect the length of the text 
            // copied to the edit control by the WM_SETTEXT message. 
            SendMessage(NativeMethods.EM_LIMITTEXT, 0, 0);
 
            if( clearUndo ){
                SendMessage(NativeMethods.EM_REPLACESEL, 0, text);
                // For consistency with Text, we clear the modified flag
                SendMessage(NativeMethods.EM_SETMODIFY, 0, 0); 
                ClearUndo();
            } 
            else{ 
                SendMessage(NativeMethods.EM_REPLACESEL, /*undoable*/ -1, text);
            } 

            // Re-enable user input.
            SendMessage(NativeMethods.EM_LIMITTEXT, maxLength, 0);
        } 

 
        ///  
        /// 
        ///     
        ///       Gets or sets the number of characters selected in the text
        ///       box.
        ///    
        ///  
        [
        SRCategory(SR.CatAppearance), 
        Browsable(false), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        SRDescription(SR.TextBoxSelectionLengthDescr) 
        ]
        public virtual int SelectionLength {
            get {
                int start, length; 

                GetSelectionStartAndLength( out start, out length ); 
 
                return length;
            } 

            set {
                if (value < 0){
                    throw new ArgumentOutOfRangeException("SelectionLength", SR.GetString(SR.InvalidArgument, "SelectionLength", value.ToString(CultureInfo.CurrentCulture))); 
                }
 
                int selStart, selLength; 
                GetSelectionStartAndLength( out selStart, out selLength );
 
                if (value != selLength) {
                    Select(selStart, value);
                }
            } 
        }
 
        ///  
        /// 
        ///     
        ///       Gets or sets the starting
        ///       point of text selected in the text
        ///       box.
        ///     
        /// 
        [ 
        SRCategory(SR.CatAppearance), 
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        SRDescription(SR.TextBoxSelectionStartDescr)
        ]
        public int SelectionStart {
            get { 
                int selStart, selLength;
 
                GetSelectionStartAndLength( out selStart, out selLength ); 

                return selStart; 
            }
            set {
                if (value < 0){
                    throw new ArgumentOutOfRangeException("SelectionStart", SR.GetString(SR.InvalidArgument, "SelectionStart", value.ToString(CultureInfo.CurrentCulture))); 
                }
                Select(value, SelectionLength); 
            } 
        }
 
        // Call SetSelectionOnHandle inside CreateHandle()
        internal virtual bool SetSelectionInCreateHandle {
            get {
                return true; 
            }
        } 
 
        /// 
        ///  
        ///    
        ///       Gets or sets
        ///       the current text in the text box.
        ///     
        /// 
        [ 
        Localizable(true), 
        Editor("System.ComponentModel.Design.MultilineStringEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))
        ] 
        public override string Text {
            get {
                return base.Text;
            } 
            set {
                if (value != base.Text) { 
                    base.Text = value; 
                    if (IsHandleCreated) {
                        // clear the modified flag 
                        SendMessage(NativeMethods.EM_SETMODIFY, 0, 0);
                    }
                }
            } 
        }
 
        ///  
        [Browsable(false)]
        public virtual int TextLength { 
            get {
                // Note: Currently [....] does not fully support surrogates - VSW#327396.  If
                // the text contains surrogate characters this property may return incorrect values.
 
                if (IsHandleCreated && Marshal.SystemDefaultCharSize == 2) {
                    return SafeNativeMethods.GetWindowTextLength(new HandleRef(this, Handle)); 
                } 
                else {
                    return Text.Length; 
                }
            }
        }
 
        /// 
        ///     Specifies whether the control uses unicode to set/get text selection information (WM_GESEL/WM_SETSEL) 
        ///     in Win9x. 
        /// 
        internal virtual bool SelectionUsesDbcsOffsetsInWin9x { 
            get {
                return true;
            }
        } 

        // Since setting the WindowText while the handle is created 
        // generates a WM_COMMAND message, we must trap that case 
        // and prevent the event from getting fired, or we get
        // double "TextChanged" events. 
        //
        /// 
        /// 
        ///  
        /// 
        internal override string WindowText { 
            get { 
                return base.WindowText;
            } 

            set {
                if (value == null) value = "";
                if (!WindowText.Equals(value)) { 
                    textBoxFlags[codeUpdateText] = true;
                    try { 
                        base.WindowText = value; 
                    }
                    finally { 
                        textBoxFlags[codeUpdateText] = false;
                    }
                }
            } 
        }
 
        ///  
        ///     For VSWhidbey 325345. In certain circumstances we might have to force
        ///     text into the window whether or not the text is the same. 
        ///     Make this a method on TextBoxBase rather than RichTextBox (which is the only
        ///     control that needs this at this point), since we need to set codeUpdateText.
        /// 
        internal void ForceWindowText(string value) { 
            if (value == null) {
                value = ""; 
            } 

            textBoxFlags[codeUpdateText] = true; 
            try {
                if (IsHandleCreated) {
                    UnsafeNativeMethods.SetWindowText(new HandleRef(this, Handle), value);
                } 
                else {
                    if (value.Length == 0) { 
                        Text = null; 
                    }
                    else { 
                        Text = value;
                    }
                }
            } 
            finally {
                textBoxFlags[codeUpdateText] = false; 
            } 
        }
 
        /// 
        /// 
        ///    
        ///       Gets or sets a value indicating whether a 
        ///       multiline text box control automatically wraps words to the beginning of the next
        ///       line when necessary. 
        ///     
        /// 
        [ 
        SRCategory(SR.CatBehavior),
        Localizable(true),
        DefaultValue(true),
        SRDescription(SR.TextBoxWordWrapDescr) 
        ]
        public bool WordWrap { 
            get { 
                return textBoxFlags[wordWrap];
            } 
            set {
                using (LayoutTransaction.CreateTransactionIf(AutoSize, ParentInternal, this, PropertyNames.WordWrap)) {
                    if (textBoxFlags[wordWrap] != value) {
                        textBoxFlags[wordWrap] = value; 
                        RecreateHandle();
                    } 
                } 
            }
        } 

        /// 
        /// 
        ///     Adjusts the height of a single-line edit control to match the height of 
        ///     the control's font.
        ///  
        ///  
        private void AdjustHeight(bool returnIfAnchored) {
 
            // If we're anchored to two opposite sides of the form, don't adjust the size because
            // we'll lose our anchored size by resetting to the requested width.
            //
            if (returnIfAnchored && (this.Anchor & (AnchorStyles.Top | AnchorStyles.Bottom)) == (AnchorStyles.Top | AnchorStyles.Bottom)) { 
                return;
            } 
 
            int saveHeight = requestedHeight;
            try { 
                if (textBoxFlags[autoSize] && !textBoxFlags[multiline]) {
                    Height = PreferredHeight;
                }
                else { 

                    int curHeight = Height; 
 
                    // Changing the font of a multi-line textbox can sometimes cause a painting problem
                    // The only workaround I can find is to size the textbox big enough for the font, and 
                    // then restore its correct size.
                    //
                    if (textBoxFlags[multiline]) {
                        Height = Math.Max(saveHeight, PreferredHeight + 2); // 2 = fudge factor 
                    }
 
                    integralHeightAdjust = true; 
                    try {
                        Height = saveHeight; 
                    }
                    finally {
                        integralHeightAdjust = false;
                    } 
                }
            } 
            finally { 
                requestedHeight = saveHeight;
            } 
        }

        /// 
        ///  
        ///    
        ///       Append text to the current text of text box. 
        ///     
        /// 
        public void AppendText( string text ) { 
            if (text.Length > 0) {
                int selStart, selLength;

                GetSelectionStartAndLength( out selStart, out selLength ); 

                try { 
                    // This enables you to use SelectionColor to AppendText in color. 
                    int endOfText = GetEndPosition();
 
                    SelectInternal(endOfText, endOfText, endOfText);
                    SelectedText = text;
                }
                finally { 
                    // If AppendText is called when the control is docked and the form is minimized,
                    // all the text will scroll to the top and the control will look empty when the 
                    // form is restored. We work around this by selecting back whatever was originally 
                    // selected when AppendText was called.
                    if (this.Width == 0 || this.Height == 0) { 
                        this.Select(selStart, selLength);
                    }
                }
            } 
        }
 
        ///  
        /// 
        ///     
        ///       Clears all text from the text box control.
        ///    
        /// 
        public void Clear() { 
            Text = null;
        } 
 
        /// 
        ///  
        ///    
        ///       Clears information about the most recent operation
        ///       from the undo buffer of the text box.
        ///     
        /// 
        public void ClearUndo() { 
            if (IsHandleCreated) { 
                SendMessage(NativeMethods.EM_EMPTYUNDOBUFFER, 0, 0);
            } 
        }

        /// 
        ///  
        ///    
        ///       Copies the current selection in the text box to the Clipboard. 
        ///     
        /// 
        [UIPermission(SecurityAction.Demand, Clipboard=UIPermissionClipboard.OwnClipboard)] 
        public void Copy() {
            SendMessage(NativeMethods.WM_COPY, 0, 0);
        }
 
        /// 
        ///  
        ///  
        /// 
        protected override void CreateHandle() { 
            // This "creatingHandle" stuff is to avoid property change events
            // when we set the Text property.
            textBoxFlags[creatingHandle] = true;
            try { 
                base.CreateHandle();
 
                if (SetSelectionInCreateHandle) { 
                    // send EM_SETSEL message
                    SetSelectionOnHandle(); 
                }

            }
            finally { 
                textBoxFlags[creatingHandle] = false;
            } 
        } 

        ///  
        /// 
        ///    
        ///       Moves the current selection in the text box to the Clipboard.
        ///     
        /// 
        public void Cut() { 
            SendMessage(NativeMethods.WM_CUT, 0, 0); 
        }
 
        /// 
        ///     Returns the text end position (one past the last input character).  This property is virtual to allow MaskedTextBox
        ///     to set the last input char position as opposed to the last char position which may be a mask character.
        ///  
        internal virtual int GetEndPosition(){
            // +1 because RichTextBox has this funny EOF pseudo-character after all the text. 
            return IsHandleCreated ? TextLength + 1 : TextLength; 
        }
 
                /// 
        /// 
        /// 
        ///    Overridden to handle TAB key. 
        /// 
        protected override bool IsInputKey(Keys keyData) { 
            if ((keyData & Keys.Alt) != Keys.Alt) { 
                switch (keyData & Keys.KeyCode) {
                    case Keys.Tab: 
                        // Single-line RichEd's want tab characters (see WM_GETDLGCODE),
                        // so we don't ask it
                        return Multiline && textBoxFlags[acceptsTab] && ((keyData & Keys.Control) == 0);
                    case Keys.Escape: 
                        if (Multiline)
                            return false; 
                        break; 
                    case Keys.Back:
                        if (!this.ReadOnly) 
                            return true;
                        break;
                    case Keys.PageUp:
                    case Keys.PageDown: 
                    case Keys.Home:
                    case Keys.End: 
                        return true; 
                        // else fall through to base
                } 
            }
            return base.IsInputKey(keyData);
        }
 
        /// 
        ///  
        ///  
        ///    Overridden to update the newly created handle with the settings of the
        ///    MaxLength and PasswordChar properties. 
        /// 
        protected override void OnHandleCreated(EventArgs e) {
            base.OnHandleCreated(e);
            // it's likely here that the create params could have changed 
            // the border size/etc.
            CommonProperties.xClearPreferredSizeCache(this); 
            AdjustHeight(true); 

            UpdateMaxLength(); 
            if (textBoxFlags[modified]){
                SendMessage(NativeMethods.EM_SETMODIFY, 1, 0);
            }
            if (textBoxFlags[scrollToCaretOnHandleCreated]) { 
                ScrollToCaret();
                textBoxFlags[scrollToCaretOnHandleCreated] = false; 
            } 
        }
 
        /// 
        /// 
        /// 
        ///  
        protected override void OnHandleDestroyed(EventArgs e) {
            textBoxFlags[modified] = Modified; 
            textBoxFlags[setSelectionOnHandleCreated] = true; 
            // Update text selection cached values to be restored when recreating the handle.
            GetSelectionStartAndLength( out this.selectionStart, out this.selectionLength ); 
            base.OnHandleDestroyed(e);
        }

        ///  
        /// 
        ///     
        ///       Replaces the current selection in the text box with the contents of the Clipboard. 
        ///    
        ///  
        [UIPermission(SecurityAction.Demand, Clipboard=UIPermissionClipboard.OwnClipboard)]
        public void Paste() {
            Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "ClipboardRead Demanded");
            IntSecurity.ClipboardRead.Demand(); 

            SendMessage(NativeMethods.WM_PASTE, 0, 0); 
        } 

        ///  
        /// 
        ///    [To be supplied.]
        /// 
        [UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)] 
        protected override bool ProcessDialogKey(Keys keyData) {
            Debug.WriteLineIf(ControlKeyboardRouting.TraceVerbose, "TextBoxBase.ProcessDialogKey [" + keyData.ToString() + "]"); 
            Keys keyCode = (Keys)keyData & Keys.KeyCode; 

            if (keyCode == Keys.Tab && this.AcceptsTab && (keyData & Keys.Control) != 0) { 
                // When this control accepts Tabs, Ctrl-Tab is treated exactly like Tab.
                keyData &= ~Keys.Control;
            }
 
            return base.ProcessDialogKey(keyData);
        } 
 
        /// 
        ///  
        ///     TextBox / RichTextBox Onpaint.
        /// 
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        public new event PaintEventHandler Paint {
            add { 
                base.Paint += value; 
            }
            remove { 
                base.Paint -= value;
            }
        }
 

        ///  
        ///  
        ///    [To be supplied.]
        ///  
        protected virtual void OnAcceptsTabChanged(EventArgs e) {
            EventHandler eh = Events[EVENT_ACCEPTSTABCHANGED] as EventHandler;
            if (eh != null) {
                 eh(this, e); 
            }
        } 
 
        /// 
        ///  
        ///    [To be supplied.]
        /// 
        protected virtual void OnBorderStyleChanged(EventArgs e) {
            EventHandler eh = Events[EVENT_BORDERSTYLECHANGED] as EventHandler; 
            if (eh != null) {
                 eh(this, e); 
            } 
        }
 
        /// 
        /// 
        ///    [To be supplied.]
        ///  
        protected override void OnFontChanged(EventArgs e) {
            base.OnFontChanged(e); 
            AdjustHeight(false); 
        }
 
        /// 
        /// 
        ///    [To be supplied.]
        ///  
        protected virtual void OnHideSelectionChanged(EventArgs e) {
            EventHandler eh = Events[EVENT_HIDESELECTIONCHANGED] as EventHandler; 
            if (eh != null) { 
                 eh(this, e);
            } 
        }

        /// 
        ///  
        ///    [To be supplied.]
        ///  
        protected virtual void OnModifiedChanged(EventArgs e) { 
            EventHandler eh = Events[EVENT_MODIFIEDCHANGED] as EventHandler;
            if (eh != null) { 
                 eh(this, e);
            }
        }
 
         /// 
        ///     Raises the MouseUp event. 
        ///  
        protected override void OnMouseUp(MouseEventArgs mevent) {
            Point pt = PointToScreen(mevent.Location); 

            if (mevent.Button == MouseButtons.Left) {
                if (!ValidationCancelled && UnsafeNativeMethods.WindowFromPoint(pt.X, pt.Y) == Handle) {
                    if (!this.doubleClickFired) { 
                        OnClick(mevent);
                        OnMouseClick(mevent); 
                    } 
                    else {
                        this.doubleClickFired = false; 
                        OnDoubleClick(mevent);
                        OnMouseDoubleClick(mevent);
                    }
                } 
                this.doubleClickFired = false;
            } 
            base.OnMouseUp(mevent); 
        }
 
         /// 
        /// 
        ///    [To be supplied.]
        ///  
        protected virtual void OnMultilineChanged(EventArgs e) {
            EventHandler eh = Events[EVENT_MULTILINECHANGED] as EventHandler; 
            if (eh != null) { 
                 eh(this, e);
            } 
        }


        protected override void OnPaddingChanged(EventArgs e) { 
            base.OnPaddingChanged(e);
            AdjustHeight(false); 
        } 

        ///  
        /// 
        ///    [To be supplied.]
        /// 
        protected virtual void OnReadOnlyChanged(EventArgs e) { 
            EventHandler eh = Events[EVENT_READONLYCHANGED] as EventHandler;
            if (eh != null) { 
                 eh(this, e); 
            }
        } 

        protected override void OnTextChanged(EventArgs e) {
            // since AutoSize existed in Everett, (and is the default) we can't
            // relayout the parent when the "preferredsize" of the control changes. 
            // this means a multiline = true textbox wont natrually grow in height when
            // the text changes. 
            CommonProperties.xClearPreferredSizeCache(this); 
            base.OnTextChanged(e);
        } 

        /// 
        /// 
        ///     Returns the character nearest to the given point. 
        /// 
        public virtual char GetCharFromPosition(Point pt) { 
            string t = this.Text; 
            int index = GetCharIndexFromPosition(pt);
            return (index < 0 || index >= t.Length) ? (char)0 : t[index]; 
        }

        /// 
        ///  
        ///     Returns the index of the character nearest to the given point.
        ///  
        public virtual int GetCharIndexFromPosition(Point pt) { 
            int longPoint = NativeMethods.Util.MAKELONG(pt.X, pt.Y);
            int index = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.EM_CHARFROMPOS, 0, longPoint); 
            index = NativeMethods.Util.LOWORD(index);

            if (index < 0) {
                index = 0; 
            }
            else { 
                string t = this.Text; 
                // EM_CHARFROMPOS will return an invalid number if the last character in the RichEdit
                // is a newline. 
                //
                if (index >= t.Length) {
                    index = Math.Max(t.Length - 1, 0);
                } 
            }
            return index; 
        } 

        ///  
        /// 
        ///     Returns the number of the line containing a specified character position
        ///     in a textbox. Note that this returns the physical line number
        ///     and not the conceptual line number. For example, if the first conceptual 
        ///     line (line number 0) word-wraps and extends to the second line, and if
        ///     you pass the index of a overflowed character, GetLineFromCharIndex would 
        ///     return 1 and not 0. 
        /// 
        public virtual int GetLineFromCharIndex(int index) { 
            return unchecked( (int) (long)SendMessage(NativeMethods.EM_LINEFROMCHAR, index, 0));
        }

        ///  
        /// 
        ///     Returns the location of the character at the given index. 
        ///  
        public virtual Point GetPositionFromCharIndex(int index) {
            if (index < 0 || index >= Text.Length) 
                return Point.Empty;

            int i = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.EM_POSFROMCHAR, index, 0);
            return new Point(NativeMethods.Util.LOWORD(i), NativeMethods.Util.HIWORD(i)); 
        }
 
        ///  
        /// 
        ///     Returns the index of the first character of a given line. Returns -1 of lineNumber is invalid. 
        /// 
        public int GetFirstCharIndexFromLine(int lineNumber) {
            if (lineNumber < 0) {
                throw new ArgumentOutOfRangeException("lineNumber", SR.GetString(SR.InvalidArgument, "lineNumber", lineNumber.ToString(CultureInfo.CurrentCulture))); 
            }
            return unchecked( (int) (long)SendMessage(NativeMethods.EM_LINEINDEX, lineNumber, 0)); 
        } 

        ///  
        /// 
        ///     Returns the index of the first character of the line where the caret is.
        /// 
        public int GetFirstCharIndexOfCurrentLine() { 
            return unchecked( (int) (long)SendMessage(NativeMethods.EM_LINEINDEX, -1, 0));
        } 
 

 
        /// 
        /// 
        ///     Ensures that the caret is visible in the TextBox window, by scrolling the
        ///     TextBox control surface if necessary. 
        /// 
        public void ScrollToCaret() { 
            if (IsHandleCreated) { 
                if (String.IsNullOrEmpty(this.WindowText)) {
                    // If there is no text, then there is no place to go. 
                    return;
                }

                bool scrolled = false; 
                object editOle = null;
                IntPtr editOlePtr = IntPtr.Zero; 
                try { 
                    if (UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), RichTextBoxConstants.EM_GETOLEINTERFACE, 0, out editOle) != 0) {
 
                        editOlePtr = Marshal.GetIUnknownForObject(editOle);

                        if (editOlePtr != IntPtr.Zero) {
                            IntPtr iTextDocument = IntPtr.Zero; 
                            Guid iiTextDocumentGuid = typeof(UnsafeNativeMethods.ITextDocument).GUID;
 
                            try { 
                                Marshal.QueryInterface(editOlePtr, ref iiTextDocumentGuid, out iTextDocument);
 
                                UnsafeNativeMethods.ITextDocument textDocument = Marshal.GetObjectForIUnknown(iTextDocument) as UnsafeNativeMethods.ITextDocument;

                                if (textDocument != null) {
                                    int selStart, selLength; 

                                    // vsWhidbey 372764: when the user calls RichTextBox::ScrollToCaret we want the RichTextBox to show as 
                                    // much text as possible. 
                                    // Here is how we do that:
                                    // 1. We scroll the RichTextBox all the way to the bottom so the last line of text is the last visible line. 
                                    // 2. We get the first visible line.
                                    // 3. If the first visible line is smaller than the start of the selection, then we are done:
                                    //      The selection fits inside the RichTextBox display rectangle.
                                    // 4. Otherwise, scroll the selection to the top of the RichTextBox. 
                                    GetSelectionStartAndLength( out selStart, out selLength );
                                    int selStartLine = GetLineFromCharIndex(selStart); 
 
                                    // 1. Scroll the RichTextBox all the way to the bottom
                                    UnsafeNativeMethods.ITextRange textRange = textDocument.Range(this.WindowText.Length - 1, this.WindowText.Length - 1); 
                                    textRange.ScrollIntoView(0);   // 0 ==> tomEnd

                                    // 2. Get the first visible line.
                                    int firstVisibleLine = unchecked( (int) (long)SendMessage(NativeMethods.EM_GETFIRSTVISIBLELINE, 0, 0)); 

                                    // 3. If the first visible line is smaller than the start of the selection, we are done; 
                                    if (firstVisibleLine <= selStartLine) { 
                                        // we are done
                                    } else { 
                                        // 4. Scroll the selection to the top of the RichTextBox
                                        textRange = textDocument.Range(selStart, selStart + selLength);
                                        textRange.ScrollIntoView(32);   // 32 ==> tomStart
                                    } 

                                    scrolled = true; 
                                } 
                            } finally {
                                if (iTextDocument != IntPtr.Zero) { 
                                    Marshal.Release(iTextDocument);
                                }
                            }
                        } 
                    }
                } finally { 
                    if (editOlePtr != IntPtr.Zero) { 
                        Marshal.Release(editOlePtr);
                    } 
                }

                if (!scrolled) {
                    SendMessage(NativeMethods.EM_SCROLLCARET, 0, 0); 
                }
            } 
            else { 
                textBoxFlags[scrollToCaretOnHandleCreated] = true;
            } 
        }

        /// 
        ///  
        ///    
        ///       Sets the SelectionLength to 0. 
        ///     
        /// 
        public void DeselectAll() { 
            this.SelectionLength = 0;
        }

        ///  
        /// 
        ///     
        ///       Selects a range of text in the text box. 
        ///    
        ///  
        public void Select(int start, int length) {
            if (start < 0){
                throw new ArgumentOutOfRangeException("start", SR.GetString(SR.InvalidArgument, "start", start.ToString(CultureInfo.CurrentCulture)));
            } 

            int textLen = TextLength; 
 
            if (start > textLen) {
                //We shouldn't allow positive length if you're starting at the end, but 
                //should allow negative length.
                long longLength = Math.Min(0, (long)length + start - textLen);
                if (longLength < int.MinValue) {
                    length = int.MinValue; 
                }
                else { 
                    length = (int)longLength; 
                }
                start = textLen; 
            }

            SelectInternal(start, length, textLen);
        } 

        ///  
        ///     Performs the actual select without doing arg checking. 
        ///
        ///     Send in -1 for the textLen parameter if you don't have the text 
        ///     length cached when calling this method. It will be computed.
        ///     But if you do have it cached, please pass it in. This will avoid
        ///     the expensive call to the TextLength property.
        ///  
        internal virtual void SelectInternal(int start, int length, int textLen) {
            //if our handle is created - send message... 
            if (IsHandleCreated) { 
                int s, e;
                AdjustSelectionStartAndEnd(start, length, out s, out e, textLen); 

                SendMessage(NativeMethods.EM_SETSEL, s, e);
                //
 
            }
            else { 
                //otherwise, wait until handle is created to send this message. 
                //Store the indices until then...
                this.selectionStart = start; 
                this.selectionLength = length;
                textBoxFlags[setSelectionOnHandleCreated] = true;
            }
        } 

        ///  
        ///  
        ///    
        ///       Selects all text in the text box. 
        ///    
        /// 
        public void SelectAll() {
            int textLen = TextLength; 
            SelectInternal(0, textLen, textLen);
        } 
 
        /// 
        ///  
        ///    Overrides Control.setBoundsCore to enforce autoSize.
        /// 
        /// 
        protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) { 

            if (!integralHeightAdjust && height != Height) 
                requestedHeight = height; 

            if (textBoxFlags[autoSize] && !textBoxFlags[multiline]) 
                height = PreferredHeight;

            base.SetBoundsCore(x, y, width, height, specified);
        } 

        private static void Swap(ref int n1, ref int n2) { 
            int temp = n2; 
            n2 = n1;
            n1 = temp; 
        }

        //
        // Send in -1 if you don't have the text length cached 
        // when calling this method. It will be computed. If not,
        // please pass in the text length as the last parameter. 
        // This will avoid the expensive call to the TextLength 
        // property.
        internal void AdjustSelectionStartAndEnd(int selStart, int selLength, out int start, out int end, int textLen) { 
            start = selStart;
            end = 0;

            if (start <= -1) { 
                start = -1;
            } 
            else { 
                int textLength;
 
                if (textLen >= 0) {
                    textLength = textLen;
                }
                else { 
                    textLength = this.TextLength;
                } 
 
                if (start > textLength) {
                    start = textLength; 
                }

                checked {
                    try { 
                        end = start + selLength;
                    } 
                    catch (OverflowException) { 
                        //Since we overflowed, cap at the max/min value: we'll correct the value below
                        end = start > 0 ? int.MaxValue : int.MinValue; 
                    }
                }

                // Make sure end is in range 
                if (end < 0) {
                    end = 0; 
                } 
                else if (end > textLength) {
                    end = textLength; 
                }

                if (this.SelectionUsesDbcsOffsetsInWin9x && Marshal.SystemDefaultCharSize == 1) {
                    // EDIT control expects selection values to be byte offsets instead of character offsets, 
                    // this makes a difference in unicode code pages like Japanese.
                    // We need to adjust the offsets. 
                    ToDbcsOffsets(WindowText, ref start, ref end); 
                }
            } 
        }

        // Called by CreateHandle or OnHandleCreated
        internal void SetSelectionOnHandle() { 
            Debug.Assert(IsHandleCreated, "Don't call this method until the handle is created.");
            if (textBoxFlags[setSelectionOnHandleCreated]) { 
                textBoxFlags[setSelectionOnHandleCreated] = false; 
                int start, end;
                AdjustSelectionStartAndEnd(this.selectionStart, this.selectionLength, out start, out end, -1); 
                SendMessage(NativeMethods.EM_SETSEL, start, end);
            }
        }
 
        /// 
        ///     Converts byte offsset to unicode offsets. 
        ///     When procssing WM_GETSEL/WM_SETSEL, EDIT control works with byte offsets instead of character positions 
        ///     as opposed to RICHEDIT which does it always as character positions.
        ///     This method is used when handling the WM_GETSEL message. 
        /// 
        static void ToUnicodeOffsets(string str, ref int start, ref int end) {
            Encoding e = Encoding.Default;
 
            // Acutally, we may get away with this call if we can get the bytes from Win9x.  Dont know if it is possible.
            // This can be expensive since start/end could be small, but str.Length can be quite big. 
            byte[] bytes = e.GetBytes(str); 

            bool swap = start > end; 
            if (swap) {
                Swap(ref start, ref end);
            }
 
            // Make sure start and end are within the string
            // 
            if (start < 0){ 
                start = 0;
            } 
            if (start > bytes.Length){
                start = bytes.Length;
            }
            if (end > bytes.Length){ 
                end = bytes.Length;
            } 
 
            // IMPORTANT: Avoid off-by-1 errors!
            // The end value passed in is the character immediately after the last character selected. 

            int newStart = start == 0 ? 0 : e.GetCharCount(bytes, 0, start);
            end = newStart + e.GetCharCount(bytes, start, end - start);
            start = newStart; 

            if (swap){ 
                Swap(ref start, ref end); 
            }
        } 

        /// 
        ///     Converts unicode offsset to byte offsets.
        ///     When procssing WM_GETSEL/WM_SETSEL, EDIT control works with byte offsets instead of character positions 
        ///     as opposed to RICHEDIT which does it always as character positions.
        ///     This method is used when handling the WM_SETSEL message. 
        ///  
        static internal void ToDbcsOffsets(string str, ref int start, ref int end) {
            Encoding e = Encoding.Default; 

            bool swap = start > end;
            if (swap) {
                Swap(ref start, ref end); 
            }
 
            // Make sure start and end are within the string 
            //
            if (start < 0) { 
                start = 0;
            }
            if (start > str.Length) {
                start = str.Length; 
            }
            if (end < start) { 
                end = start; 
            }
            if (end > str.Length) { 
                end = str.Length;
            }

            // IMPORTANT: Avoid off-by-1 errors! 
            // The end value passed in is the character immediately after the last character selected.
 
            int newStart =  start == 0 ? 0 : e.GetByteCount(str.Substring(0, start)); 
            end = newStart + e.GetByteCount(str.Substring(start, end - start));
            start = newStart; 

            if (swap) {
                Swap(ref start, ref end);
            } 
        }
 
 

        ///  
        /// 
        ///    Provides some interesting information for the TextBox control in
        ///    String form.
        ///  
        /// 
        public override string ToString() { 
 
            string s = base.ToString();
 
            string txt = Text;
            if (txt.Length > 40) txt = txt.Substring(0, 40) + "...";
            return s + ", Text: " + txt.ToString();
        } 

        ///  
        ///  
        ///    
        ///       Undoes the last edit operation in the text box. 
        ///    
        /// 
        public void Undo() {
            SendMessage(NativeMethods.EM_UNDO, 0, 0); 
        }
 
        internal virtual void UpdateMaxLength() { 
            if (IsHandleCreated) {
                SendMessage(NativeMethods.EM_LIMITTEXT, maxLength, 0); 
            }
        }

 
        internal override IntPtr InitializeDCForWmCtlColor (IntPtr dc, int msg)
        { 
            if ((msg == NativeMethods.WM_CTLCOLORSTATIC) && !ShouldSerializeBackColor()) { 
                // Let the Win32 Edit control handle background colors itself.
                // This is necessary because a disabled edit control will display a different 
                // BackColor than when enabled.
                return IntPtr.Zero;
            }
            else { 
                return base.InitializeDCForWmCtlColor(dc, msg);
            } 
        } 

        ///  
        /// 
        /// 
        /// 
        private void WmReflectCommand(ref Message m) { 
            if (!textBoxFlags[codeUpdateText] && !textBoxFlags[creatingHandle]) {
                if (NativeMethods.Util.HIWORD(m.WParam) == NativeMethods.EN_CHANGE && CanRaiseTextChangedEvent) { 
                    OnTextChanged(EventArgs.Empty); 
                }
                else if (NativeMethods.Util.HIWORD(m.WParam) == NativeMethods.EN_UPDATE) { 
                    // VSWhidbey 94719: force update to the Modified property, which will trigger
                    // ModifiedChanged event handlers
                    bool force = this.Modified;
                } 
            }
        } 
 
        /// 
        ///  
        /// 
        /// 
        void WmSetFont(ref Message m) {
            base.WndProc(ref m); 
            if (!textBoxFlags[multiline]) {
                SendMessage(NativeMethods.EM_SETMARGINS, NativeMethods.EC_LEFTMARGIN | NativeMethods.EC_RIGHTMARGIN, 0); 
            } 
        }
 
        void WmGetDlgCode(ref Message m) {
            base.WndProc(ref m);
            if (AcceptsTab) {
                Debug.WriteLineIf(Control.ControlKeyboardRouting.TraceVerbose, "TextBox wants tabs"); 
                m.Result = (IntPtr)(unchecked( (int) (long)m.Result) | NativeMethods.DLGC_WANTTAB);
            } 
            else { 
                Debug.WriteLineIf(Control.ControlKeyboardRouting.TraceVerbose, "TextBox doesn't want tabs");
                m.Result = (IntPtr)(unchecked( (int) (long)m.Result) & ~(NativeMethods.DLGC_WANTTAB | NativeMethods.DLGC_WANTALLKEYS)); 
            }
        }

        ///  
        ///     Handles the WM_CONTEXTMENU message based on this
        ///     table: 
        ///     ShortcutsEnabled    #1      #2      #3 
        ///     Yes                 strip   context system
        ///     No                  strip   context N/A 
        /// 
        /// 
        private void WmTextBoxContextMenu(ref Message m) {
 
            if (ContextMenu != null || ContextMenuStrip != null) {
                int x = NativeMethods.Util.SignedLOWORD(m.LParam); 
                int y = NativeMethods.Util.SignedHIWORD(m.LParam); 
                Point client;
                bool keyboardActivated = false; 
                // lparam will be exactly -1 when the user invokes the context menu
                // with the keyboard.
                //
                if (unchecked((int)(long)m.LParam) == -1) { 
                    keyboardActivated = true;
                    client = new Point(Width/2, Height/2); 
                } 
                else {
                    client = PointToClientInternal(new Point(x, y)); 
                }

                //
 
                // VisualStudio7 # 156, only show the context menu when clicked in the client area
                if (ClientRectangle.Contains( client )) { 
                    if (ContextMenu != null) { 
                        ContextMenu.Show(this, client);
                    } 
                    else if (ContextMenuStrip != null) {
                        ContextMenuStrip.ShowInternal(this, client, keyboardActivated);
                    }
                    else { 
                      Debug.Fail("contextmenu and contextmenustrip are both null... hmm how did we get here?");
                      DefWndProc( ref m ); 
                    } 
                }
            } 
        }

        /// 
        ///  
        /// 
        ///    The control's window procedure.  Inheriting classes can override this 
        ///    to add extra functionality, but should not forget to call 
        ///    base.wndProc(m); to ensure the control continues to function properly.
        ///  
        [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
        protected override void WndProc(ref Message m) {
            switch (m.Msg) {
                case NativeMethods.WM_LBUTTONDBLCLK: 
                    this.doubleClickFired = true;
                    base.WndProc(ref m); 
                    break; 
                case NativeMethods.WM_REFLECT + NativeMethods.WM_COMMAND:
                    WmReflectCommand(ref m); 
                    break;
                case NativeMethods.WM_GETDLGCODE:
                    WmGetDlgCode(ref m);
                    break; 
                case NativeMethods.WM_SETFONT:
                    WmSetFont(ref m); 
                    break; 
                case NativeMethods.WM_CONTEXTMENU:
                    if (ShortcutsEnabled) { 
                        //calling base will find ContextMenus in this order:
                        // 1) ContextMenu 2) ContextMenuStrip 3) SystemMenu
                        base.WndProc(ref m);
                    } 
                    else {
                        // we'll handle this message so we can hide the 
                        // SystemMenu if Context and Strip menus are null 
                        WmTextBoxContextMenu(ref m);
                    } 
                    break;
                default:
                    base.WndProc(ref m);
                    break; 
            }
        } 
     } 
}

// 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