TIP: Filtrar números en un campo de edición

Si uno quiere aplicar una máscara dentro de un campo de edición, tiene a su disposición el componente MaskEdit, que posee una propiedad llamada Mask y que, asignando ahí una serie de símbolos predefinidos, nos guiará a la hora de qué texto podemos introducir. Perfectamente válida en muchas situaciones, en otras es un engorro de lo más complicado, ya que, aunque la potencia del filtrado es enorme, a veces no nos permite una flexibilidad adecuada. En mi caso no he podido encontrar la máscara adecuada a la introducción de cualquier valor numérico entero sin tener problemas con los sombreados, los valores por defecto y un largo etcétera.


Por eso, siempre que necesito un campo numérico cualquiera sin formato, es decir, un campo que me permita introducir valores como «0», «33», «56789,89» de forma libre sin los problemas de la máscara -el que haya usado el componente sabrá a qué me refiero-, puede utilizar una técnica alternativa bastante sencilla.


Si tiene varios controles en una misma ficha que sólo permitan la introducción de valores numéricos, lo primero a realizar es seleccionar todos esos controles de edición de forma conjunta, irse a la ventana de propiedades y seleccionar la pestaña de eventos. Haciendo doble clic en el evento KeyDown obtendrá un manejador único para todos los controles seleccionados.


Otra forma consiste en, una vez generado dicho evento para un solo control, seleccionar uno a uno (o varios a la vez) los demás controles de edición y, en el mismo lugar que antes, abrir el desplegable del evento KeyDown y seleccionar el evento anterior.


Ya solo nos queda la edición del código que nos interesa. En mi caso, el código es:



void ConfigForm::EEditKeyDown(Object ^,KeyEventArgs^ e)
{
  if
(!
    (
      (e->KeyCode>=Keys::D0 && e->KeyCode<=Keys::D9
)||
      (e->KeyCode>=Keys::NumPad0 && e->KeyCode<=Keys::NumPad9
)||
       e->KeyCode==Keys::NumLock
|| 
       e->KeyCode==Keys::Left
|| 
       e->KeyCode==Keys::Right
|| 
       e->KeyCode==Keys::Insert
|| 
       e->KeyCode==Keys::Delete
||
       e->KeyCode==Keys::Tab
|| 
       e->KeyCode==Keys::Escape
|| 
       e->KeyCode==Keys::OemPeriod
|| 
       e->KeyCode==Keys::
Back
   
)
 
)
    e->SuppressKeyPress=true
;
}


Básicamente estamos eliminando cualquier tecla que no se corresponda a las listadas. Las dos primeras líneas de la sentencia condicional miran si el valor introducido es un número, y las siguientes si se ha presionado dicha tecla especial. Como la sentencia está negada, el condicional sólo se ejecutará en el caso de que la tecla pulsada no sea ninguna de ellas.


Evidentemente, siempre podremos añadir o quitar las teclas que queramos a la lista.


Otra opción quizás más sencilla, es la de colocar todos los valores válidos dentro de un array estático dentro de la ficha (o incluso fuera de ella, en una clase propia) y realizar la comprobación mediante un bucle o incluso ordenar el array y utlizar el método BinarySearch junto a un predicado. Esa parte la deja el autor como ejercicio para el lector, y si éste tiene dudas para hacerlo, que me lo comunique y pondré una posible solución.


Y todavía podemos afinar más, mediante la realización de un componente que de alguna forma nos de la opción de elegir qué teclas permitimos (por ejemplo mediante un editor visual que nos permita marcar dichas teclas, o mediante una lista a la que podemos añadir/quitar elementos), pero aquí el autor considera que la ineficiencia del control (que llevaría mucho código sin utilizar), no supera la facilidad de uso; además, dicho control sería un ensamblado a acompañar a nuestra aplicación…


 

Un comentario sobre “TIP: Filtrar números en un campo de edición”

  1. En Borland utilizo algo similar, además de para sólo leer números, para poder cambiar las teclas y facilitar la entrada de datos especializados.

    Es más fácil poner el código, que intentar explicarlo. La clase que sólo permite enteros es ‘teclas_virtuales_int’ y creo que es el equivalente a tu código. Las otras clases están como curiosidad. En los comentarios de la cabecera está el modo de uso:

    ///////////////////////////////////////////////////////////
    /////////////// Fichero teclas_virtuales.h ////////////////

    #ifndef bcn_teclas_virtualesH
    #define bcn_teclas_virtualesH

    #include

    /* MODO DE USO
    Se debe crear un gestor de teclas virtuales de la clase deseada:
    bcn::teclas_virtuales_enter_es_tab TeclaEnterEsTAb;
    bcn::teclas_virtuales_int TeclasInt;
    bcn::teclas_virtuales_double TeclasDouble;
    bcn::teclas_virtuales_qui TeclasQui;
    bcn::teclas_virtuales_gol TeclasGol;

    En el Event OnKeyPress del TEdit del que deseemos mapear las teclas:
    void TfrmTest::Edit1KeyPress(TObject *Sender, char &Key) {
    TeclasGol.Test(Handle,Key);
    }
    */

    namespace bcn {

    class teclas_virtuales_enter_es_tab {
    protected:
    bool OcultarRestoTeclas(char &Key) const;
    public:
    bool Test(HWND Handle, char & Key); // true si ha cambiado Key
    };

    class teclas_virtuales_int : public teclas_virtuales_enter_es_tab {
    public:
    bool Test(HWND Handle, char & Key); // true si ha cambiado Key
    };

    class teclas_virtuales_double : public teclas_virtuales_enter_es_tab {
    public:
    bool Test(HWND Handle, char & Key); // true si ha cambiado Key
    };

    class teclas_virtuales_qui : public teclas_virtuales_enter_es_tab {
    public:
    bool Test(HWND Handle, char & Key); // true si ha cambiado Key
    };

    class teclas_virtuales_gol : public teclas_virtuales_enter_es_tab {
    public:
    bool Test(HWND Handle, char & Key);
    };

    } // fin namespace bcn

    #endif

    ///////////////////////////////////////////////////////////
    /////////////// Fichero teclas_virtuales.cpp //////////////

    #include «bcnteclas_virtuales.h»

    bool bcn::teclas_virtuales_enter_es_tab::Test(HWND Handle, char & Key) {
    if (VK_RETURN==Key) {
    Key = 0;
    PostMessage(Handle,WM_NEXTDLGCTL,0,0);
    return true;
    }
    return false;
    }

    bool bcn::teclas_virtuales_enter_es_tab::OcultarRestoTeclas(char &Key) const {
    if (( 32< =static_cast(Key))&&(254>=static_cast(Key))) {
    Key = 0;
    return true;
    }
    return false;
    }

    ///////////////////////////////////////////////////////////
    ///////////// Fichero teclas_virtuales_int.cpp ////////////

    #include «bcnteclas_virtuales.h»

    bool bcn::teclas_virtuales_int::Test(HWND Handle, char & Key) {
    if (teclas_virtuales_enter_es_tab::Test(Handle,Key)) return true;
    if ((‘0’< =Key)&&('9'>=Key)) return true;
    return OcultarRestoTeclas(Key);
    }

    ///////////////////////////////////////////////////////////
    //////////// Fichero teclas_virtuales_double.cpp //////////

    #include «bcnteclas_virtuales.h»

    bool bcn::teclas_virtuales_double::Test(HWND Handle, char & Key) {
    if (teclas_virtuales_enter_es_tab::Test(Handle,Key)) return true;
    if ((‘0’< =Key)&&('9'>=Key)) return true;
    if (‘,’==Key) return true;
    if (‘.’==Key) {Key=’,’;return true;}
    return OcultarRestoTeclas(Key);
    }

    ///////////////////////////////////////////////////////////
    ///////////// Fichero teclas_virtuales_qui.cpp ////////////

    #include «bcnteclas_virtuales.h»

    // Permite utilizar el teclado numérico para introducir los signos de las
    // Quinielas(1X2) utilizando la posición ‘lógica’ de las teclas

    bool bcn::teclas_virtuales_qui::Test(HWND Handle, char & Key) {
    if (teclas_virtuales_enter_es_tab::Test(Handle,Key)) return true;
    if ((‘1’==Key) || (‘4’==Key) || (‘7’==Key)) {
    Key=’1’;
    return true;
    }
    if ((‘X’==Key) || (‘x’==Key) || (‘3’==Key) || (‘5’==Key) || (‘8’==Key)) {
    Key=’X’;
    return true;
    }
    if ((‘2’==Key) || (‘6’==Key) || (‘9’==Key)) {
    Key=’2’;
    return true;
    }
    return OcultarRestoTeclas(Key);
    }

    ///////////////////////////////////////////////////////////
    ///////////// Fichero teclas_virtuales_gol.cpp ////////////

    #include «bcnteclas_virtuales.h»

    // Permite utilizar el teclado numérico para introducir los signos del
    // Quinigol(012M) utilizando directamente los goles. (No funciona para
    // más de nueve goles).

    bool bcn::teclas_virtuales_gol::Test(HWND Handle, char & Key) {
    if (teclas_virtuales_enter_es_tab::Test(Handle,Key)) return true;
    if (‘0’==Key) return true;
    if (‘1’==Key) return true;
    if (‘2’==Key) return true;
    if (‘M’==Key) return true;
    if ((‘m’==Key) || ((‘3’< =Key)&&('9'>=Key))) {
    Key=’M’;
    return true;
    }
    return OcultarRestoTeclas(Key);
    }

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *