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 TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Implementing Multi Select String Grid

Graphical User Interface

Implementing Multi Select String Grid

by  Opieo  Posted    (Edited  )
I was looking for a way to allow multi select in a TStringGrid. A DBGrid allows this, but I cannot use a DBGrid because I need the information in the database to remain as unlocked as possible (so I pull the data in locally and use the String Grid). For this, multi select for the TStringGrid was required. This FAQ expands on faq102-2231.

First, you will need an [color blue]array of Boolean[/color] (referred to here as [color blue]ItemsSelected[/color]).
This will keep track of what rows are selected.
When you fill your string grid you will dynamically assign the length of the array using [color blue]SetLength[/color] (that is assuming its dynamically sized, and not a constant size of, say for example, 5.

First, lets set up our color schemes.
For your String Grid you need to add some code to the [color blue]OnDrawCell[/color] event.
First, a couple of notes:
1. I follow all information with a blank row, but do not want to allow them to select the blank row.
2. I have every possible set of ( ) and [color blue]begin[/color] and [color blue]end[/color] in here for portability across Delphi versions, but not all of them may be required for you.
There may be a slightly more efficient way, but this gets the job done nicely:
Code:
procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
 begin
  StringGrid1.Canvas.Font.Color := clBlack;  [color green]// Default color[/color]
  StringGrid1.Canvas.Brush.Color := clWhite;
  if ((ACol = 0) OR (ARow = 0)) then   [color green]// First check if Fixed row or column[/color]
   begin
    StringGrid1.Canvas.Brush.Color := clBtnFace;
   end
  else
   begin
    if not (ARow = (StringGrid1.RowCount - 1)) then  [color green]// Avoid empty row[/color]
     begin
      if (ItemsSelected[StringGrid1.Row - 1] = True) then
       begin        [color green]// Will only color selected rows[/color]
        StringGrid1.Canvas.Font.Color := clWhite;
        StringGrid1.Canvas.Brush.Color := clBlue;
       end;
     end;
   end;
  StringGrid1.Canvas.FillRect(Rect);
  StringGrid1.Canvas.TextOut(Rect.Left, Rect.Top, StringGrid1.Cells[ACol, ARow]);
 end;

Okay, now our grid will draw the proper colors for any given scenario (you can of course use whatever colors you want to).
How do we change when a row is selected though?
For that I use the [color blue]OnMouseUp[/color] event. Everything I tried with the [color blue]OnSelectCell[/color] seemed to just fail and give me errors. That is partly why I coded everything this way. Also did not want to use the [color blue]OnMouseDown[/color] because I wanted to make sure that the cell / row was selected as normally happens when the user presses the mouse key. Okay, the Mouse event:

Code:
procedure TForm1.StringGrid1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
 var
  col, row : Integer;

 begin
  StringGrid1.MouseToCell(X, Y, col, row);  [color green]// This will tell us what cell (we need row) was selected[/color]
  if ((row > 0) AND (row < StringGrid1.RowCount - 1)) then  [color green]// Again don't select fixed or blank row[/color]
   if (ItemsSelected[StringGrid1.Row - 1] = True) then
    begin
     ItemsSelected[StringGrid1.Row - 1] := False;
    end
   else
    begin
     ItemsSelected[StringGrid1.Row - 1] := True;
    end;
  StringGrid1.Invalidate;
 end;

Again, you could probably just do ItemsSelected[StrToInt(StringGrid1.Cells[0, row]) - 1] := not ItemsSelected[StrToInt(StringGrid1.Cells[0, row]) - 1];
but that might not work in all versions of Delphi.
Adding the [color blue]Invalidate[/color] ensures that the grid will be redrawn with the newly (un)selected row.

Thats it! Just be sure that when you create your array to monitor whether items are selected or not, that you initialize it all to [color blue]False[/color] (or True if thats your desire).

One note that is worthy of mentioning:
For error trapping, do not have the form visible and add [color blue]ShowMessage[/color] in there at the same time. Chances are you will enter an infinite loop with you clicking on the little pop up box and the grid trying to redraw itself since it was covered in any way.
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