Página principal
Artículos y trucos
Catálogo de productos
Ejemplos y descargas
Mis libros
Cursos de formación
Investigación y desarrollo
Libros recomendados
Mis páginas favoritas
Acerca del autor
 
En colaboración con Amazon
 
Intuitive Sight

Coordenadas y registros en rejillas

Suponga que está realizando una operación de arrastrar y soltar... y que el objeto arrastrado es soltado sobre una rejilla de datos, un TDBGrid. ¿Cómo sabemos sobre qué registro ha caído el objeto? En otros componentes que visualizan colecciones, como TListBox y TListView, existen métodos especiales, como ItemAtPos, que reciben las coordenadas del ratón y devuelven un puntero al elemento que se encuentra en dichas coordenadas, si es que hay uno. ¿Existe algo parecido para TDBGrid?

Por desgracia, no de forma directa. Si se tratase de un TDrawGrid o un TStringGrid podríamos calcular el número de fila y columna de la celda que se encuentra bajo el ratón. Tratándose de un TDBGrid, en cambio, no existen métodos públicos (al menos que yo conozca) que identifiquen el registro que se está mostrando en determinada fila. Por suerte existe un truco que, combinando varios métodos protegidos de TDBGrid permiten seleccionar una fila dada partiendo de unas coordenadas del ratón. Primero tenemos que ganar acceso a la sección protegida de TDBGrid, y la forma indicada consiste en definir una clase en la misma unidad donde programaremos la función de localización:

type
   TGridHack = class(TDBGrid);

Existe una regla en Delphi que permite el acceso a la sección protegido de cualquier clase definida dentro de la misma unidad. TDBGrid está definida en otra unidad, pero nuestro invento, TGridHack, tiene la misma estructura que su ancestro y sí compartirá unidad con nuestro código. Por lo tanto, tenemos acceso a sus declaraciones protegidas, que lógicamente son las mismas heredades de TDBGrid, su ancestro inmediato.

La función que necesitamos, en sí, es la siguiente:

function SeleccionarFila(G: TDBGrid;
   X, Y: Integer): Boolean;
begin
   Result := Assigned(G.DataSource) and
      Assigned(G.DataSource.DataSet) and
      not G.DataSource.DataSet.IsEmpty and
      (G.MouseCoord(X, Y).Y > 0);
   if Result then
      TGridHack(G).MouseDown(mbLeft, [], X, Y);
end;

Primero comprobamos si, efectivamente, hay algún registro asociado a la rejilla, comprobando que ésta esté enlazada a algún conjunto de datos no vacío. El método MouseCoord convierte una coordenada en píxeles en una coordenada compuesta por el número de fila y el número de columna de la correspondiente celda. Solamente necesitamos saber el número de fila: la fila de títulos se considera la fila cero, y MouseCoord devuelve posiciones negativas si no existen registros en las coordenadas indicadas. Finalmente, si hay alguna fila debajo del ratón, simulamos su selección llamando al método protegido MouseDown, que es común a todos los controles de la VCL.