jueves, noviembre 21, 2024

Como capturar pulsaciones del teclado en un control DataGrid

Descargar Ejemplo DataGrid_capturar_pulsaciones.zip

En diversas ocaciones durante el transcurso de la programación de código resulta necesario capturar pulsaciones de teclado para poder controlar acciones a realizar. El control DataGrid es uno de varios tipos de controles en donde puede ser necesario la captura de teclas. Existen ejemplos que muestran diversos acercamientos a cómo realizar dicha captura, por ejempo, mediante la creación de un Windows Control Library modificado, objeto que permite reutilización y agregado al ToolBox. El ejemplo que se presenta en esta nota, muestra una metodología directa, simple y fácil de entender en C# .NET.

La pulsación de una tecla durante la fase de ejecución de un programa es controlada por un Mensaje Windows que se puede capturar mediante el evento ProcessCmdKey. Si agregamos este evento a un Formulario, por ejemplo a la clase Form1 (derivada de la clase base Form), ya estamos en condiciones de capturar las pulsaciones del teclado que afecten a todo el Formulario, sin importar cual objeto esté focalizado. En este caso, lo que nos interesa es capturar sólo las pulsaciones que se focalicen en un DataGrid.

Lo que vamos a hacer, entonces, es agregar, en una clase dataGrid1 (derivada de la clase DataGrid), un override del método específico ProcessCmdKey, que se burbujea hasta el método del mismo nombre del objeto padre que lo contiene (Form1), y que nos va a permitir no sólo capturar las teclas Arriba, Abajo, Izquierda y Derecha de movimiento de cursor, sino tambien pulsaciones combinadas mediante CTRL y ALT.

Veamos la estructura básica de la clase derivada:

class dataGrid1 : System.Windows.Forms.DataGrid
{
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
return base.ProcessCmdKey(ref msg,keyData);
}
}

El método ProcessCmdKey recibe 2 parámetros:

– msg : contiene un Windows Message (x ej. WM_KEYDOWN)
– keyData : contiene el código numérico (KeyCode) de la tecla pulsada (x ej. DOWN). Si se pulsó tambien otra tecla como CTRL o ALT, este parámetro contiene información ModifierKey.

Para capturar teclas específicas se evalúa el keyCode (que viene en keyData) y se compara con la enumeración Keys. Esta enumeración contiene constantes que se utilizan para procesar entradas por teclado. Cada tecla se identifica mediante un valor que consiste de un código de tecla y un conjunto de modificadores, que se combinan en un valor entero único: los 4 dígitos a la izquierda contienen el código de tecla, y los 4 dígitos a la derecha contienen los bits modificadores para las teclas SHIFT, ALT y CONTROL.

Por ejemplo, veamos los códigos de valor para las siguentes teclas:

Left: 37 (0x25h)
Up: 38
Right: 39
Down: 40 (0x28h)

Alt: 18 (0x12h)
Alt Modifier Key: 262144 (0x40000h)
Ctrl: 17 (0x11h)
Ctrl Modifier Key: 131072 (0x20000h)
Shift: 16 (0x10h)
Shift Modifier Key: 65536 (0x10000h)

Tecla pulsada: Shift + Down
msg : 256 (0x100h)

Shift: 16 (0x10h)
KeyData: 65552 (0x10010)
Shift Modifier Key: 65536 (0x10000h)

Down: 40 (0x28h)
KeyData: 40 (0x28h)

Shift (Modifier) + Down
KeyData: 65576 (0x10028h)

Veamos que sucede al efectuar una operación de bitwise OR sobre los valores mencionados (campos de bit):

65536 | 40 -> 65576

El método ProcessCmd Key retorna 1 valor:

– true : indicando que procesó un tecla de comando (CTRL, ALT, SHIFT)
– false : indicando que se trata de cualquier otro tipo de tecla (salvo, por ejemplo, PrintScreen)

Veamos un ejemplo:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace MyTestApplication
{
public class dataGrid1 : System.Windows.Forms.DataGrid
{
//Constructor
public dataGrid1()
{
}
//Estructura de acceso público
public static PressedKeyData myPress = new PressedKeyData();
//Método suplantado
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
//Carga la Propiedad con el dato de la Tecla pulsada
myPress.KeyData = keyData;
return base.ProcessCmdKey(ref msg,keyData);
}
//Nueva Propiedad
public struct PressedKeyData
{
private Keys keydata;
public Keys KeyData
{
get{return keydata;}
set{keydata = value;}
}
}
}
//Definición de una Estructura de Datos para llenar el DataGrid
public struct gridData
{
private string nombre;
private int edad;
public gridData(string n,int e)
{
nombre=n;
edad=e;
}
public string Nombre
{
get{return nombre;}
set{nombre = value;}
}
public int Edad
{
get{return edad;}
set{edad=value;}
}
}
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.TextBox TBoxKey;
private System.ComponentModel.Container components = null;
public Form1()
{
InitializeComponent();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code

/// Required method for Designer support – do not modify
/// the contents of this method with the code editor.
///

private void InitializeComponent()
{
this.TBoxKey = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// TBoxKey
//
this.TBoxKey.Location = new System.Drawing.Point(32, 168);
this.TBoxKey.Name = «TBoxKey»;
this.TBoxKey.Size = new System.Drawing.Size(328, 20);
this.TBoxKey.TabIndex = 1;
this.TBoxKey.Text = «»;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(464, 301);
this.Controls.Add(this.TBoxKey);
this.Name = «Form1»;
this.Text = «Form1»;
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
#endregion
protected gridData[] dataArray = new gridData[5];
public dataGrid1 mydataGrid = new dataGrid1();
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void Form1_Load(object sender, System.EventArgs e)
{

//Agrega el DataGrid al Formulario
mydataGrid.Location = new System.Drawing.Point(32, 10);
mydataGrid.Size = new System.Drawing.Size(208, 140);
this.Controls.Add(mydataGrid);
//Define datos para el DataGrid y lo carga
dataArray[0]=new gridData(«Marcos»,39);
dataArray[1]=new gridData(«Pedro»,22);
dataArray[2]=new gridData(«Jorge»,42);
dataArray[3]=new gridData(«Alberto»,18);
dataArray[4]=new gridData(«Eloy»,29);
mydataGrid.DataSource=dataArray;
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
//Muestra en un TextBox el nombre de la Tecla Pulsada
TBoxKey.Text = dataGrid1.myPress.KeyData.ToString();
return base.ProcessCmdKey(ref msg,keyData);
}
}
}

Podemos ver la definición de un Formulario Form1, que contiene 2 controles: un objeto tipo DataGrid (DataGrid1) llamado mydataGrid, que se agrega dinámicamente, y un objeto tipo TextBox, llamado TBoxKey. El DataGrid se llena en forma dinámica mediante un arreglo llamado dataArray. Cuando se ejecuta la aplicación, se muestra el Formulario con un DataGrid con datos ejemplo. Efectuemos un clic sobre una celda del DataGrid y pulsemos una tecla de movimiento de cursor (o combinación de teclas con las teclas de comando CTRL, ALT o SHFT): el cuadro de texto muestra el nombre de dicha pulsación.

Descargar Ejemplo DataGrid_capturar_pulsaciones.zip

Roy Rojas
Roy Rojashttp://www.dotnetcr.com
Con más de 20 años de experiencia en programación, experto en lenguajes .NET, VB, C#, ASP.NET, Xamarin, XCode, DBA en SQL Server. Creador de dotnetcr.com, sitio web para programadores en español. royrojas.com | dotnetcr.com | GitHub
Roy Rojas
Roy Rojashttp://www.dotnetcr.com
Con más de 20 años de experiencia en programación, experto en lenguajes .NET, VB, C#, ASP.NET, Xamarin, XCode, DBA en SQL Server. Creador de dotnetcr.com, sitio web para programadores en español. royrojas.com | dotnetcr.com | GitHub