Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How can I add MultiSelect functionality to a grid?

Grids

How can I add MultiSelect functionality to a grid?

by  ChrisRChamberlain  Posted    (Edited  )
If you want to add Multiselect functionality to a grid that emulates Windows Explorer behaviour, try the following:-

Subclass a grid into a suitable class library.

Add 4 new properties to the class,

[color blue].lMultiSelect[/color] with value of .F.
[color blue].nActiveRow[/color] with value of 0
[color blue].nLastRow[/color] with value of 0
[color blue].nRecs2Change[/color] with value of 0

and 1 new method

[color blue].mSelectRecords()[/color]

Ensure the [color blue].RecordSource[/color] of the grid is not indexed, so create it from a SELECT - SQL statement. The [color blue].RecordSource[/color] also requires an additional logical field, [color blue]selected[/color].

In the [color blue].AfterRowColChange()[/color] event of the grid, put

[color blue]THIS.mSelectRecords()[/color]

In the [color blue].mSelectRecords()[/color] event of the grid, put
[color blue]
LOCAL lcSelected,;
lcRecordSource

#DEFINE VK_lSHIFT 0x10 [/color][color green]&& Relocate to a header file[/color][color blue]
#DEFINE VK_lCONTROL 0x11 [/color][color green]&& Relocate to a header file[/color][color blue]

DECLARE INTEGER GetKeyState IN WIN32API INTEGER[/color][color green] && Relocate to where WinAPI calls are declared[/color]
[color blue]
WITH THIS
.nActiveRow = .ActiveRow[/color][color green] && Assign value to class property[/color][color blue]
lcSelected = .RecordSource + [.selected][/color][color green] && Assign value to local variable[/color][color blue]
lcRecordSource = .RecordSource[/color][color green] && Assign value to local variable[/color][color blue]

DO CASE
CASE GetKeyState(VK_lSHIFT) < 0 ;
OR GetKeyState(VK_lSHIFT) > 1[/color][color green] && Check for shift key press[/color][color blue]

DO CASE
CASE .nLastRow > .nActiveRow[/color][color green] && Last recd below current recd in grid[/color][color blue]

.nRecs2Change = .nLastRow - .nActiveRow[/color][color green] && Calculate no of recds to change[/color][color blue]

REPLACE (lcSelected) WITH .T. IN (lcRecordSource)[/color][color green] && Replace current recd[/color][color blue]
FOR i = 1 TO .nRecs2Change
REPLACE (lcSelected) WITH .T. IN (lcRecordSource)
SKIP IN (lcRecordSource)
ENDF

CASE .nLastRow < .nActiveRow[/color][color green] && Last recd above current recd in grid[/color][color blue]

.nRecs2Change = .nActiveRow - .nLastRow[/color][color green] && Calculate no of recds to change[/color][color blue]
REPLACE (lcSelected) WITH .T. IN (lcRecordSource)[/color][color green] && Replace current recd[/color][color blue]

GO .nLastRow IN (lcRecordSource)[/color][color green] && Goto the last recd[/color][color blue]
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[/color][color green] && Check for control key press[/color][color blue]

REPLACE (lcSelected) WITH .T. IN (lcRecordSource)

.lMultiSelect = .T.

OTHERWISE[/color][color green] && Neither shift or ctrl pressed[/color][color blue]
DO CASE
CASE .lMultiSelect
REPLACE (lcSelected) WITH .F. ;
ALL IN (lcRecordSource)[/color][color green] && Update all recds[/color][color blue]
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)[/color][color green] && Change new value[/color][color blue]
REPLACE (lcSelected) WITH .T. IN (lcRecordSource)

.lMultiSelect = .F.
ENDC

IF RECCOUNT(lcRecordSource) > 0
DO CASE[/color][color green] && Set colours according to OS[/color][color blue]
CASE UPPER(OS(1)) = [WINDOWS 5.00][/color][color green] && Win 2K[/color][color blue]
.SetAll([DynamicBackColor] ,;
"IIF(&lcSelected ,;
RGB(10,36,106) ,;
RGB(255,255,255))" ,;
[Column])
CASE UPPER(OS(1)) = [WINDOWS 5.01][/color][color green] && Win XP[/color][color blue]
.SetAll([DynamicBackColor] ,;
"IIF(&lcSelected ,;
RGB(49,106,197) ,;
RGB(255,255,255))" ,;
[Column])
CASE UPPER(OS(1)) = [WINDOWS 6.00][/color][color green] && Vista[/color][color blue]
.SetAll([DynamicBackColor] ,;
"IIF(&lcSelected ,;
RGB(51,153,255) ,;
RGB(255,255,255))" ,;
[Column])
CASE UPPER(OS(1)) = [WINDOWS 6.01][/color][color green] && Windows 7[/color][color blue]
.SetAll([DynamicBackColor] ,;
"IIF(&lcSelected ,;
RGB(51,153,255) ,;
RGB(255,255,255))" ,;
[Column])
ENDCASE

.SetAll([DynamicForeColor] ,;[/color][color green] && All OS[/color][color blue]
"IIF(&lcSelected ,;
RGB(255,255,255) ,;
RGB(0,0,0))" ,;
[Column])

.nLastRow = .nActiveRow [/color][color green]&& Mark current row for next time through[/color]
[color blue] ENDIF
ENDWITH[/color]

*!* *!* *!* *!* *!* *!* *!* *!* *!* *!* *!*

Left mouse click will select the current record only, shift + click followed by shift + click will select a block of records, and ctrl + click will select individual records, all selected records being highlighted.

Scrolling with the arrow keys does not select records.

You can programatically determine if there are multiple selected records with:-
[color blue]
IF THISFORM.grid1.lMultiSelect[/color]
[color green] *!* Code[/color][color blue]
ENDI
[/color]
You now have a scope clause available for copying, printing, deleting etc, expressed as:-
[color blue]
REPORT FORM reportname.frx FOR CURSORNAME.selected
[/color]
Have fun

FAQ184-2483 - answering getting answered.​
Chris [pc2]
[link http://www.pdfcommander.com]PDFcommander.com[/link]
[link http://www.pdfcommander.co.uk]PDFcommander.co.uk[/link]
Register to rate this FAQ  : BAD 1 2 3 4 5 6 7 8 9 10 GOOD
Please Note: 1 is Bad, 10 is Good :-)

Part and Inventory Search

Back
Top