INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Jobs

Graphical User Interface

Implementing Multi Select String Grid by Opieo
Posted: 17 May 07 (Edited 20 Jul 07)

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: Coloring selected Row in a dbgrid.

First, you will need an array of Boolean (referred to here as ItemsSelected).
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 SetLength (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 OnDrawCell 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 begin and end 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;  // Default color
  StringGrid1.Canvas.Brush.Color := clWhite;
  if ((ACol = 0) OR (ARow = 0)) then   // First check if Fixed row or column
   begin
    StringGrid1.Canvas.Brush.Color := clBtnFace;
   end
  else
   begin
    if not (ARow = (StringGrid1.RowCount - 1)) then  // Avoid empty row
     begin
      if (ItemsSelected[StringGrid1.Row - 1] = True) then
       begin        // Will only color selected rows
        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 OnMouseUp event. Everything I tried with the OnSelectCell seemed to just fail and give me errors. That is partly why I coded everything this way. Also did not want to use the OnMouseDown 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);  // This will tell us what cell (we need row) was selected
  if ((row > 0) AND (row < StringGrid1.RowCount - 1)) then  // Again don't select fixed or blank row
   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 Invalidate 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 False (or True if thats your desire).

One note that is worthy of mentioning:
For error trapping, do not have the form visible and add ShowMessage 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.

Back to Embarcadero: Delphi FAQ Index
Back to Embarcadero: Delphi Forum

My Archive

Resources

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close