Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 01-06-2007
Avatar de gluglu
[gluglu] gluglu is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Málaga - España
Posts: 1.455
Poder: 21
gluglu Va por buen camino
MultiSelect en DBGrid con Shift

Hola compañeros !

A raiz de este hilo estuve comiéndome el coco y he encontrado la siguiente solución al problema del MultiSelect en un DBGrid con la tecla Shift, que no viene implementado por defecto en Delphi y el componente TDBGrid.

Primero un poco de explicación teórica y más adelante el código al respecto :

1. Cuando abrimos la consulta SQL correspondiente al DBGrid, creamos un TSringtList, y lo completamos con los Bookmarks de los registros de la consulta SQL en el mismo orden correspondiente a la consulta.

Para ello, justo después de la consulta SQL, podemos deshabilitar los controles del DBGrid y hacer un recorrido secuencial desde el primer registro hasta el último de la consulta.

2. De esta manera habremos obtenido un StringList 'paralelo' que contendrá todos los Bookmarks de los registros de la consulta. Este StringList nos servirá para añadir o borrar registros 'seleccionados' al correspondiente SelectedRows del propio DBGrid. Cada vez que añadamos o borremos un registro de la lista de seleccionados, bastará con un Repaint del DBGrid para actualizar en pantalla aquellos registros que estén seleccionados.

3. Para añadir o borrar un registro de la lista de seleccionados, utilizaremos el evento OnDataChange del DataSet asociado al DBGrid. Dicho evento se activará al hacer Click con el raton sobre un registro diferente al que estemos, y habrá que interceptar ahí la tecla Shift.

4. La lógica a seguir para marcar registros con el Shift-Click es a partir de un registro marcado, mirar primero hasta el final de los registros de la consulta para ver si hay alguno marcado, y si fuera así, marcar desde el actual hasta el último de los registros marcados, y en caso contrario, buscar hacia arriba para ver el inmediatamente superior de los registros marcados a partir del actual, teniendo en cuenta que si el anterior al inmediatamente superior (recursivamente) está también marcado, considerarlo también como marcado en conjunto.

5. Al recorrer siempre única y exclusivamente nuestro StringList 'auxiliar' de Bookmarks en memoria, el DBGrid no modifica ninguno de sus punteros, y como ya indiqué arriba, bastará un simple DBGrid.Repaint para conseguir el efecto deseado.


Vamos al código :

Código Delphi [-]
private
  GridBookMarks : TStringList
 
procedure TForm.FormCreate(Sender: TObject);
begin
  GridBookMarks.Create;
end;
 
procedure TForm.ConsultaSQL(Sender: TObject);
begin
 
  // Realizar la consulta correspondiente
  IBDataSet1.Open;
 
  GridBookMarks.Clear;
  with IBDataSet1 do begin
    DisableControls;
    while not Eof do begin
      GridBookMarks.Add(IBDataSet1.Bookmark);
      Next;
    end;
    First;
    EnableControls;
  end;
 
end;
 
procedure TForm.DataSource1DataChange(Sender: TObject; Field: TField);
var
  Last_Marked : TBookmarkStr;
  Actual_Pos  : Int64;
  Aux_Pos     : Int64;
begin

  if (GetKeyState(VK_SHIFT) < 0) then begin
 
    // Look if bellow are existing marked.
    // If so, look for the last marked record.
    Last_Marked := null;
    Actual_Pos  := GridBookmarks.IndexOf(IBDataSet1.Bookmark);
    Aux_Pos     := GridBookmarks.IndexOf(IBDataSet1.Bookmark);
    while Aux_Pos <= GridBookmarks.Count-1 do begin
      Inc(Aux_Pos);
      if (Aux_Pos <= GridBookMarks.Count-1) and (DBGrid1.SeletecRows.IndexOf(GridBookmarks[Aux_Pos]) <> -1) then
        Last_Marked := GridBookmarks[Aux_Pos];
    end;
 
    // Found, mark records
    if not (Last_Marked is Null) then begin
      DBGrid1.SelectedRows.Clear;
      DBGrid1.SelectedRows.Add(GridBookmarks[Actual_Pos]);
      Aux_Pos := GridBookmarks.IndexOf(IBDataSet1.Bookmark);
      while GridBookmarks[Aux_Pos]) <> Last_Marked do begin
        Inc(Aux_Pos);
        DBGrid1.SelectedRows.Add(GridBookmarks[Aux_Pos]);
      end;
    end
    else begin
 
      // Look for first record above selected
      Last_Marked := null;
      Aux_Pos     := GridBookmarks.IndexOf(IBDataSet1.Bookmark);
      Dec(Aux_Pos);
      while Aux_Pos >= 0 do begin
        if DBGrid1.SelectedRows.IndexOf(GridBookmarks[Aux_Pos]) <> -1 then begin
          Last_Marked := GridBookmarks[Aux_Pos];
          if (Aux_Pos > 0) and (DBGrid1.SelectedRows.IndexOf(GridBookmarks[Aux_Pos-1]) = -1) then Break;
        end;
        Dec(Aux_Pos);
      end;
 
      if not (Last_Marked is null) then begin
        // Mark Records
        Aux_Pos := GridBookmarks.IndexOf(IBDataSet1.Bookmark);
        DBGrid1.SelectedRows.Clear;
        DBGrid1.SelectedRows.Add(GridBookmarks[Aux_Pos]);
        while GridBookmarks[Aux_Pos]) <> Last_Marked do begin
          Dec(Aux_Pos);
          DBGrid1.SelectedRows.Add(GridBookmarks[Aux_Pos]);
        end;
      end;
    end;
  end;

  DBGrid1.Repaint;

end;

Debo de indicar que el código arriba expuesto no lo tengo probado tal y como está, planteado con Bookmarks. Realmente yo utilizo mi propia rutina de 'MultiSelect' y en vez de activar la propiedad del propio DBGrid, lo que hago es mantener ese StringList adicional independiente, en vez de como he planteado aquí con el propio SelectedRows del DBGrid. Espero que el código de arriba 'teórico' funcione . De la manera que yo lo utilizo (en vez de con Bookmarks con los números almacenados en un campo interno de la tabla, funciona de maravilla ).

No creo que en este sitio sea el lugar adecuado para exponer todo la funcionalidad y código adicional, pero además tengo programadas las siguientes funciones :

A. En caso de haber más de un registro seleccionado, el movimiento de la rueda del ratón provoca un scroll del DBGrid sin deseleccionar los registros elegidos hasta el momento.

B. Aparte del MultiSelect con el Shift, tengo implementado también la multi selección con la tecla Control (en teoría con lo arriba expuesto lo debería hacer el propio Delphi).

C. Contemplo la funcionalidad Drag & Drop con múltiples registros. Para ello debo de llevar control adicional de cuando debe 'marcar' o 'desmarcar' registros y con qué evento de la tecla del ratón debo actuar.

Aquí está la problemática principal !! Resulta que con el MultiSelect (al menos por lo que yo he probado), una vez seleccionados los registros correspondientes (más de uno), si quiero hacer un Drag & Drop del conjunto de registros seleccionados, si hago Click sólo con el botón Izquierdo del ratón sobre alguno de los registros marcados, me desmarca todos de nuevo !! Es por ello que yo en vez de hacerlo con los Bookmarks y la propiedad MultiSelect del propio DBGrid, he implementado mi solución con un StringList adicional y con número de registros internos.

De esta manera, controlo el evento Drag & Drop con variable auxiliar y si existen varios registros marcados, no 'desmarcaría' en teoría hasta el evento MouseUp, en caso de que no se terminara la operación de Drag & Drop.

La operación de Drag & Drop la activo manualmente con BeginDrag y controlo posteriormente las actuaciones correspondientes.

D. Con mi solución propia, la de llevar un StringList adicional de los números internos de los registros, en vez de utilizar el SelectedRows del DBGrid, me permite además colorear de diferente manera los registros seleccionados diferenciándolos del registro actualmente seleccionado en el DBGrid.

Bueno amigos, espero no haberme enrollado demasiado y que esta idea pueda ayudar a otros.

Si alguien precisa de información adicional a estos últimos puntos, o de aclaración a lo expuesto, me lo indique e intentaré dar más detalles.

Un saludo a todos !
__________________
Piensa siempre en positivo !
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Dbgrid y Multiselect jorge_mosquera OOP 3 26-04-2007 03:22:41
Multiselect con celdas en DBGrid??? Jonnathan OOP 0 26-09-2006 20:38:02
DBGrid y Bookmark sin MultiSelect gluglu Varios 2 18-05-2006 16:42:07
Duda con opción MultiSelect en DBgrid cybergerman OOP 0 28-10-2004 16:25:27
Multiselect en DbGrid sin Ctrl taita Varios 6 03-08-2004 11:16:11


La franja horaria es GMT +2. Ahora son las 01:50:05.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi