none
Poner el foco al inicio de un texbox RRS feed

  • Pregunta

  • Hola 

    Trabajo con Windows Forms, VS 2019

    Tengo el siguiente problema cuando ingreso un registro desde una caja de texto el foco se encuentra al final de donde se escribio en el textbox no regresa al inicio del texbox

    El código que utilizo es el siguiente

    public void Nuevo()
            {
                tabControl1.SelectedTab = tabDatos;
                Opener.HabilitarBotonesCuandoNuevo(false);
                Utilidades.LimpiarControles(this);
                Utilidades.ActivarDesactivarControles(this, true);
                txtNombre.Select();
                txtNombre.Focus();
                //ActiveControl = txtNombre;
            }

    Si escribí hasta la mitad del texbox presiono nuevo y el puntero(el foco no aparece al inicio del texbox), solo tengo una caja de texto no tengo mas controles en el form.

    Saludos.


    Pedro Ávila
    "El hombre sabio querrá estar siempre con quien sea mejor que él."
    Lima - Perú

    jueves, 2 de enero de 2020 16:46

Respuestas

  • hola

    >>obj.GetAllControls(); lleva a la clase que muestro abajo

    y eso para que te esta sirviendo sino asignas la respuesta a ninguna variable

    estas invocando codigo cuya respuesta nunca usas

    el

    obj.GetAllControls();

    deberias eliminarlo

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Marcado como respuesta Pedro Ávila viernes, 3 de enero de 2020 0:20
    jueves, 2 de enero de 2020 23:57

Todas las respuestas

  • hola

    >>Si escribí hasta la mitad del texbox presiono nuevo y el puntero(el foco no aparece al inicio del texbox),

    Pero cuando presionas nuevo no deberias limpiar el contenido del textbox ? digo dejarlo vario para ingresar un nuevo dato

    Podrias ver de usar el

    SelectionStart

    para indicar donde comienza la seleccion

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    jueves, 2 de enero de 2020 16:53
  • Hola

    Cuando presiono nuevo limpio el textbox y pongo txtnombre.focus pero igual el puntero o cursor o foco queda al final en donde se escribio el ultimo caracter.

    El control queda limpio vacío pero el cursor queda en donde se escribio el ultimo caracter

    Con un simple focus el cursor debería estar al principio de texbox pero no hace eso ojo cuando el texbox esta vacío pero el cursor se queda posicionado en donde se escribio el último caracter.


    Pedro Ávila
    "El hombre sabio querrá estar siempre con quien sea mejor que él."
    Lima - Perú


    jueves, 2 de enero de 2020 16:56
  • hola

    >>Cuando presiono nuevo limpio el textbox y pongo txtnombre.focus

    como lo limpias ? usas

    txtNombre.Text = "";

    porque si haces eso no podrias quedar el cursor mal ubicado

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    jueves, 2 de enero de 2020 17:15
  • Hola

    public static void LimpiarControles(Form frm)
            {
                Control obj = new Control();
                obj.GetAllControls();
    
                var controles = from b in frm.GetAllControls()
                                where b is TextBox || b is ComboBox || b is CheckBox || b is CheckBoxX
                                select b;
    
                foreach (var control in controles)
                {
                    if (control is CheckBox)
                    {
                        ((CheckBox)control).Checked = false;
                    }
                    if (control is ComboBox)
                    {
                        if (((ComboBox)control).DataSource != null)
                            ((ComboBox)control).SelectedIndex = 0;
                    }
                    if (control is TextBox)
                    {
                        ((TextBox)control).Text = string.Empty;
                    }
                    if (control is CheckBoxX)
                        ((CheckBoxX)control).Checked = false;
                }
            }

    string.empty


    Pedro Ávila
    "El hombre sabio querrá estar siempre con quien sea mejor que él."
    Lima - Perú

    jueves, 2 de enero de 2020 17:17
  • Hola

    El problema es que en el form hay un solo control que es el texbox como no tengo mas controles el foco tiene que regresar al mismo control si lo hace pero en una posición donde se escribio el ultimo carácter, cuando tengo mas de un control se comporta bien.

    Cuando escribo en el control si comienza a escribir desde el inicio, solo el detalle es que el puntero aparece en otro lado.


    Pedro Ávila
    "El hombre sabio querrá estar siempre con quien sea mejor que él."
    Lima - Perú

    jueves, 2 de enero de 2020 17:27
  • Puede deberse a un efecto que genere la posicion del foco cuando no termino de limpiar el control

    podrias ver de poner un

    Thread.Sleep(1000);

    despues de LimpiarControles()

    para ver si al darle algo de tiempo y que despues posicione el foco

    ------

    En LimpiarControles() para que son estas dos linea ?

    Controlobj = new Control();

    obj.GetAllControls();

    porque no veo tengan ninguna utilidad

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    jueves, 2 de enero de 2020 20:44
  • obj.GetAllControls(); lleva a la clase que muestro abajo

    public static class ExtensionControl
        {
            public static IEnumerable<Control> GetAllControls(this Control control)
            {
                List<Control> ctl = new List<Control>();
    
                Action<Control.ControlCollection> recursive = null;
                recursive = new Action<Control.ControlCollection>((a) =>
                {
                    foreach (Control c in a)
                    {
                        ctl.Add(c);
                        recursive(c.Controls);
                    }
                });
    
                recursive(control.Controls);
                return ctl;
            }
        }

    El cursor siempre queda ahí nunca se mueve.

    Había olvidado que el texbox es un control personlizado.

    namespace GlobalTech.TextBoxControl
    {
        [ToolboxBitmap(typeof(TextBox))]
        public partial class TextBoxUniversal : TextBox
        {
            private bool Sombra;
            private bool _mTeclaPermitida;
            private string separafecha = "/";
    
            public enum TipoDato
            {
                AlfaNumerico = 0,
                Enteros = 1,
                Letras = 2,
                Numeric = 3,
                Fecha = 4
            }
    
            public TextBoxUniversal()
            {
                InitializeComponent();
                if (TipoValidacion == TipoDato.Letras) this.CharacterCasing = System.Windows.Forms.CharacterCasing.Upper;
                if (TipoValidacion == TipoDato.Fecha) this.MaxLength = 10;
                
            }
    
            private short decimales = 2; // Por default permitira 2 decimales.
            private bool punto = false; // Auxiliar para limitar el número de puntos en el textboxt.
    
            // Creates the private variable that will store the value of your 
            // property.
            private bool _varDecimal;
    
            // Declares the property.
            public bool AcceptDecimal
            {
                // Establece el método para recuperar el valor de su propiedad.
                get
                {
                    return _varDecimal;
                }
                // Establece el método para establecer el valor de su propiedad.
                set
                {
                    _varDecimal = value;
                    //if (value)
                    //    this.TipoControl = TipoDato.Numeric;
                }
            }
    
            #region Propiedades del TextBox
            // Implementar la propiedad que permita al usuario establecer el número de decimales a mostrar
            // Agregamos una descripcion a la propiedad que pueda leer el usuario.
            [Description("Define el número de decimales para el cuadro de texto.")]
            public short NumeroDecimales
            {
                get { return this.decimales; }
                set { this.decimales = value; }
            }
    
            TipoDato TipoValidacion;
            [Description("Permite escojer entre los tipos de validación aceptado por el TextBox")]
            [RefreshProperties(System.ComponentModel.RefreshProperties.Repaint)]
            public TipoDato TipoControl
            {
                get { return this.TipoValidacion; }
                set
                { 
                    this.TipoValidacion = value;
    
                  
                    switch (value)
                    {
                        case TipoDato.Numeric: _varDecimal = true; break;
                        case TipoDato.Fecha: this.MaxLength = 10; _varDecimal = false; break;
                        default: _varDecimal = false;  break;
                    }
                }
            }
    
            [Description("Permite escojer entre seleccionar texto o no seleccionar en el TextBox")]
            public bool SombrearTexto
            {
                get { return this.Sombra; }
                set { this.Sombra = value; }
            }
            #endregion
    
            protected override void OnKeyPress(KeyPressEventArgs e)
            {
                base.OnKeyPress(e);
    
                switch (TipoValidacion)
                {
                    case TipoDato.AlfaNumerico:
                        break;
                    case TipoDato.Enteros:
                        if (!Char.IsDigit(e.KeyChar) && !Char.IsControl(e.KeyChar))
                        {
                            e.Handled = true; // Rechazar el carácter
                            return;
                        }
                        break;
                    case TipoDato.Letras:
                        if (!Char.IsLetter(e.KeyChar) &&
                            !Char.IsControl(e.KeyChar) &&
                            !Char.IsSeparator(e.KeyChar))
                        {
                            e.Handled = true;
                            return;
                        }
                       
                        break;
                    case TipoDato.Numeric:
                        //verificar si el textbox contiene el caracter punto y actualizar nuestra variable a true si ya se tiene un punto
                        if (this.Text.Contains(".") == true)
                            punto = true;
                        else
                            punto = false;
    
                        //permitir solo los caracteres de digitos y punto
                        // e.KeyChar == (char)Keys.Home
                        if (char.IsDigit(e.KeyChar) || e.KeyChar == '.')
                        {
                            //validar si el usuario esta ingresando el caracter (punto)
                            if (e.KeyChar == '.')
                            {
                                //limitar el numero de puntos en el textbox
                                if (punto)
                                {
                                    e.Handled = true;// si ya existe un punto, bloquear el caracter
                                    return;
                                }
                                //si no existe ningun punto en el textbox, permitir el caracter
                                punto = true;
    
                            }
    
                            //si el caracter es un digito
                            //comprobar que el cuadro de texto cumpla con la expresion regular:
                            //0 a n digitos(punto)n numero de decimales
                            //si cumple con la expresion, permitir el digito ingresado
                            if (Regex.IsMatch(this.Text, @"^\d*\.\d{" + decimales + "}$")) e.Handled = true;
                        }
                        else
                        {
                            //si es tecla de control especial, permitirla
                            if (!Char.IsControl(e.KeyChar))
                            {
                                e.Handled = true;
                                return;
                            }
                        }
                        break;
                    case TipoDato.Fecha:
                        if((int)e.KeyChar == (int)Keys.Divide){
    	                    e.Handled = true;
    	                    return;
                        }
                        if (!Char.IsDigit(e.KeyChar) && !Char.IsControl(e.KeyChar) && (e.KeyChar != '/')){
    	                    e.Handled = true;
    	                    return;
                        }
                       
                        break;
                }
    
            }
    
            protected override void OnGotFocus(EventArgs e)
            {
                base.OnGotFocus(e);
    
                if (TipoControl == TipoDato.Enteros || TipoControl == TipoDato.Numeric)
                    this.TextAlign = HorizontalAlignment.Right;
              
                //if (AutoSelectAll == true)
                //{
                //    if (this.SelectionLength == 0)
                //        this.SelectAll();
                //}
    
                if (SombrearTexto == true)
                {
                    if (this.SelectionLength == 0)
                        this.SelectAll();
                }
        
            }
    
            protected override void OnTextChanged(EventArgs e)
            {
                base.OnTextChanged(e);
                if (this.Enabled == false || this.Enabled == true)
                    if (TipoControl == TipoDato.Enteros || TipoControl == TipoDato.Numeric)
                    //if (TipoControl == TipoDato.Enteros)
                        this.TextAlign = HorizontalAlignment.Right;
    
                //if (AcceptDecimal == true)
                //{
                //    decimal numero = default(decimal);
                //    bool bln = decimal.TryParse(this.Text, out numero);
    
                //    if (string.IsNullOrEmpty(this.Text))
                //        return;
                //    else
                //    {
                //        string NDecimales = "N" + NumeroDecimales;
                //        this.Text = numero.ToString(NDecimales);
                //        this.DeselectAll();
                //    }
                //}
            }
    
            protected override void OnLeave(EventArgs e)
            {
                base.OnLeave(e);
                if (AcceptDecimal == true)
                {
                    decimal numero = default(decimal);
                    bool bln = decimal.TryParse(this.Text, out numero);
    
                    if (string.IsNullOrEmpty(this.Text))
                        return;
                    else
                    {
                        string NDecimales = "N" + NumeroDecimales;
                        this.Text = numero.ToString(NDecimales);
                        this.DeselectAll();
                    }
                }
    
                //DateTime fecha;
                //if (TipoControl == TipoDato.Fecha && !string.IsNullOrEmpty(this.Text))
                //{
                //   if( DateTime.TryParse(this.Text, out fecha));
                //    string.Format("{0:dd/MM/yyyy}", this.Text);
                //}
    
                if (TipoControl == TipoDato.Fecha && !string.IsNullOrEmpty(this.Text))
                {
                    string[] expectedFormats = { "dd/MM/yyyy", "ddMMyyyy", "MM/dd/yyyy", "MMddyyyy", "yyyyMMdd" };
                    DateTime date;
                    if (DateTime.TryParseExact(this.Text, expectedFormats, System.Globalization.CultureInfo.InvariantCulture,
                                               System.Globalization.DateTimeStyles.None, out date))
                    {
                        this.Text = date.ToString("dd/MM/yyyy");
                    }
                }
            }
    
            /// <summary>
            /// Verifica si la expresión se puede evaluar como un número.
            /// </summary>
            /// <author>Enrique Martínez Montejo</author>
            /// <date>31/07/2005</date>
            /// <Modifier>José Luis García Bautista</Modifier> 
            /// <date>15/02/2013</date>
            /// <param>Expresión numérica o alfanumérica que será evaluada. <name>value</name> </param>
            /// <param>Si es True, se rechazarán los valores numéricos
            /// especificados en notación científica, base hexadecimal o base octal. <name>onlyDecimalBase</name> </param>
            /// <param name="valor">Valor a ser evaluado </param>
            /// <returns></returns>
            /// <remarks></remarks>
            public static Boolean IsNumeric(string valor)
            {
                BigInteger result;
                return BigInteger.TryParse(valor, out result);
            }
    
            public static Boolean IsDecimal(string valor)
            {
                decimal result;
                return decimal.TryParse(valor, out result);
            }
    
    
            //****************************************************************************************
            // Comentarios:  A diferencia de la función IsNumeric, la función IsNumber devolverá
            //               False si el número decimal se ha expresado en notación científica
            //               (1,20E+06), en base hexadecimal (&H125EA5) o en base octal (&O4457245),
            //               y siempre que se desee evaluar un número en base decimal.
            //
            //               Como la función se basa en la función IsNumeric, se tendrá en
            //               cuenta el símbolo de moneda de la configuración regional. En
            //               cambio, no se tiene en cuenta el punto o la coma que pueda
            //               existir como símbolo decimal en la configuración regional.
            //****************************************************************************************
            private bool IsNumber(string value, bool onlyDecimalBase)
            {
                if ((string.IsNullOrEmpty(value)))
                    return false;
    
                try
                {
    
                    if ((!_varDecimal) & (!(IsNumeric(value))))
                        return false;
                    if ((_varDecimal) & (!IsDecimal(value)))
                        return false;
    
                    // Primero compruebo si es un número mediante la función IsNumeric de Visual Basic.
                    //
                    //if (!(IsNumeric(value)) & (!IsDecimal(value))) //Quitar comentario para permitir los numeros decimales en el control textbox
                    //    return false;
                    if ((!(onlyDecimalBase)))
                        return true;
    
    
    
    
                    // Aún siendo un número, compruebo que el mismo no
                    // se haya expresado como notación científica (E),
                    // en base hexadecimal (&H) o en base octal (&O).
                    //
                    // Modelo que representa la lista de caracteres
                    // que pueden estar incluidos en una expresión
                    // en notación científica, base decimal u octal.
                    //
                    const string pattern = "*[&HOA-F]*";
    
                    return (!(value.ToUpperInvariant().Contains(pattern)));
    
                }
                catch (Exception ex)
                {
                    throw ex;
    
                }
    
            }
    
            [System.Diagnostics.DebuggerStepThrough]
            protected override void WndProc(ref Message m)
            {
                const Int32 emUndo = 0xc7;// Es el mensaje Deshacer para los controles TextBox de una única línea.
                const Int32 wmClear = 0x303;
                const Int32 wmCopy = 0x301;
                const Int32 wmCut = 0x300;
                const Int32 wmPaste = 0x0302;
                const Int32 wmUndo = 0x304;// Es el mensaje Deshacer para los controles TextBox multilínea.
    
                switch (m.Msg)
                {
                    case wmClear:
                        _mTeclaPermitida = true;
    
                        break;
                    case wmCopy:
                        _mTeclaPermitida = true;
    
                        break;
                    case wmCut:
                        _mTeclaPermitida = true;
    
                        break;
                    case wmPaste:
                        var dataObject = Clipboard.GetDataObject();
                        if (dataObject != null && !(dataObject.GetDataPresent(DataFormats.Text)))
                            return;
    
                        // Comprobamos si el contenido del portapapeles es numérico.
                        if ((!(ValidateClipboardText())))
                        {
                            _mTeclaPermitida = false;
                            return;
                        }
    
                        _mTeclaPermitida = true;
    
                        break;
                    case emUndo:
                        _mTeclaPermitida = true;
    
                        break;
                    case wmUndo:
                        _mTeclaPermitida = true;
    
                        break;
                }
    
                // Procesamos los restantes mensajes
                base.WndProc(ref m);
    
            }
    
            // La función comprobará el contenido del portapapeles de windows
            // Para verificar si su contenido es o no numérico.
            private bool ValidateClipboardText()
            {
                var dataObject = Clipboard.GetDataObject();
                if (dataObject != null && (dataObject.GetDataPresent(DataFormats.Text)))
                {
                    // Contenido actualmente existente en el portapapeles
                    string value = Clipboard.GetText(TextDataFormat.Text);
    
                    bool bln = IsNumber(value, true);
                    if (!bln)
                        return false;
    
                    // Le añadimos el texto actualmente existente en el control
                    // y lo volvemos a validar
                    value = Text + value;
                    return IsNumber(value, true);
                }
                return false;
            }
    
        }
    }


    Pedro Ávila
    "El hombre sabio querrá estar siempre con quien sea mejor que él."
    Lima - Perú

    jueves, 2 de enero de 2020 21:32
  • hola

    >>obj.GetAllControls(); lleva a la clase que muestro abajo

    y eso para que te esta sirviendo sino asignas la respuesta a ninguna variable

    estas invocando codigo cuya respuesta nunca usas

    el

    obj.GetAllControls();

    deberias eliminarlo

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Marcado como respuesta Pedro Ávila viernes, 3 de enero de 2020 0:20
    jueves, 2 de enero de 2020 23:57
  • hola


    >>Había olvidado que el texbox es un control personlizado.

    intentaste cambiarlo por un textbox normal para ver si se comporta de la misma forma? si lo hace entonces queda claro que algo esta mail en el control personalizado que has creado

    quizas en ese control personalizado te esten quedando caracteres vacios por eso el cursor se posiciona al final de estos

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    viernes, 3 de enero de 2020 0:01
  • Hola

    Efectivamente con un textbox normal funciona excelente el problema es el control personalizado.


    Pedro Ávila
    "El hombre sabio querrá estar siempre con quien sea mejor que él."
    Lima - Perú

    viernes, 3 de enero de 2020 0:32