Esta la saque de http://www.tek-tips.com/faqs.cfm?fid=433. Aquí la pongo traducida:
¿Cómo agregar la funcionalidad de multiselección en un Grid?
faq184-433
Posted: 29 Jan 01 (Edited 30 Sep 06)
Si desean agregar la funcionalidad multiselección a un Grid para que emule la del explorador de Windows, intenten lo siguiente:
Subclaseen un Grid en una librería de clases y agregen 4 nuevas propiedades:
lMultiSelectcon valor .F.nActiveRowcon valor 0 (cero)nLastRowcon valor 0 (cero)nRecs2Changecon valor 0 (cero)
Y un nuevo método:
mSelectRecords()
Asegurense de que RecordSource del Grid no este indexado, lo crean con una sentencia SELECT-SQL. El RecordSource necesita un campo logico adicional, "Selected".
En el evento AfterRowColChange() pongan:
THIS.mSelectRecords()
En el método mSelectRecords() del Grid pongan:
LOCAL lcSelected,lcRecordSource
#DEFINE VK_lSHIFT 0x10 && Relocate to a header file
#DEFINE VK_lCONTROL 0x11 && Relocate to a header file
DECLARE INTEGER GetKeyState IN WIN32API INTEGER && Relocate to where WinAPI calls are declared
WITH THIS
.nActiveRow = .ACTIVEROW && Assign value to class property
lcSelected = .RECORDSOURCE + [.selected] && Assign value to local variable
lcRecordSource = .RECORDSOURCE && Assign value to local variable
DO CASE
CASE GetKeyState(VK_lSHIFT) < 0 ;
OR GetKeyState(VK_lSHIFT) > 1 && Check for shift key press
DO CASE
CASE .nLastRow > .nActiveRow && Last recd below current recd in grid
.nRecs2Change = .nLastRow - .nActiveRow && Calculate no of recds to change
REPLACE (lcSelected) WITH .T. IN (lcRecordSource) && Replace current recd
FOR i = 1 TO .nRecs2Change
REPLACE (lcSelected) WITH .T. IN (lcRecordSource)
SKIP IN (lcRecordSource)
ENDF
CASE .nLastRow < .nActiveRow && Last recd above current recd in grid
.nRecs2Change = .nActiveRow - .nLastRow && Calculate no of recds to change
REPLACE (lcSelected) WITH .T. IN (lcRecordSource) && Replace current recd
GO .nLastRow IN (lcRecordSource) && Goto the last recd
FOR i = 1 TO .nRecs2Change
REPLACE (lcSelected) WITH .T. IN (lcRecordSource)
SKIP IN (lcRecordSource)
ENDF
ENDC
.lMultiSelect = .T.
CASE GetKeyState(VK_lCONTROL) < 0 ;
OR GetKeyState(VK_lCONTROL) > 1 && Check for control key press
REPLACE (lcSelected) WITH .T. IN (lcRecordSource)
.lMultiSelect = .T.
OTHERWISE && Neither shift or ctrl pressed
DO CASE
CASE .lMultiSelect
REPLACE (lcSelected) WITH .F. ;
ALL IN (lcRecordSource) && Update all recds
CASE .nLastRow # 0
TRY
GO .nLastRow IN (lcRecordSource)
CATCH
GO BOTTOM IN (lcRecordSource)
ENDTRY
REPLACE (lcSelected) WITH .F. IN (lcRecordSource)
ENDCASE
GO .nActiveRow IN (lcRecordSource) && Change new value
REPLACE (lcSelected) WITH .T. IN (lcRecordSource)
.lMultiSelect = .F.
ENDC
IF RECCOUNT(lcRecordSource) > 0
DO CASE && Set colours according to OS
CASE UPPER(OS(1)) = [WINDOWS 5.00] && Win 2K
.SETALL([DynamicBackColor], ;
"IIF(&lcSelected, RGB(10,36,106), RGB(255,255,255))", ;
[Column])
CASE UPPER(OS(1)) = [WINDOWS 5.01] && Win XP
.SETALL([DynamicBackColor], ;
"IIF(&lcSelected, RGB(49,106,197), RGB(255,255,255))", ;
[Column])
ENDCASE
.SETALL([DynamicForeColor], ; && All OS
"IIF(&lcSelected, RGB(255,255,255), RGB(0,0,0))", ;
[Column])
.nLastRow = .nActiveRow && Mark current row for next time through
ENDIF
ENDWITH
Seran seleccionados solos registros que se cliqueen con Mayusculas o Control. Usando los cursores direccionales no seleccionara registros.
Programaticamente pueden determinar si hay selecciones multiples de registros con:
IF THISFORM.grid1.lMultiSelect *!* Code ENDIF
Otra solucion mas simple es agregar un campo numerico al cursor que esta en el RecordSource del Grid. Por ejemplo mselec n(5).
En el Init del Form poner:
THISFORMSET.frm_enviaryrecibir.grd_recibidos.SETALL("dynamicbackcolor", ;
"IIF(mselec = 1,RGB(49,106,197), RGB(255,255,255))", "Column")
THISFORMSET.frm_enviaryrecibir.grd_recibidos.SETALL("dynamicforecolor", ;
"IIF(mselec = 1,RGB(255,255,255), RGB(0,0,0))", "Column")
Y en el Click del Grid:
LOCAL lcSelected,lcRecordSource
#DEFINE VK_lSHIFT 0x10 && Relocate to a header file
#DEFINE VK_lCONTROL 0x11 && Relocate to a header file
DECLARE INTEGER GetKeyState IN WIN32API INTEGER && Relocate to where WinAPI calls are declared
DO CASE
CASE GetKeyState(VK_lSHIFT) < 0 OR GetKeyState(VK_lSHIFT) > 1 && Check for shift key press
IF mselec = 0
REPLACE mselec WITH 1
ELSE
REPLACE mselec WITH 0
ENDIF
CASE GetKeyState(VK_lCONTROL) < 0 OR GetKeyState(VK_lCONTROL) > 1 && Check for control key press
IF mselec = 0
REPLACE mselec WITH 1
ELSE
REPLACE mselec WITH 0
ENDIF
ENDCASE
con esto cada vez que hagan Click con Mayúscula o Control presionado van a seleccionar los registros y el Grid los pinta.
Para poder hacer algo con la selección hacen:
SELEC MICURSOR SCAN FOR mselec = 1 *! mi codigo para la seleccion ENDSCAN
Suerte!!!!
Carlos Caremi
Yo solo agrego una columna "Marca" de tipo Logica, asocio el Grid a un cursor y luego solo verifico el campo Marca para ver cuales eligio el usuario y cuales no. Aunque tu ejemplo parece interesante. :)
ResponderBorrar