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:
lMultiSelect
con valor .F.nActiveRow
con valor 0 (cero)nLastRow
con valor 0 (cero)nRecs2Change
con 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