2008. január 29., kedd

Force a selection of cells in a TStringGrid


Problem/Question/Abstract:

I'm attempting to force a selection of cells based on the user clicking in the grid. Here is my code:

procedure TSizeSelectFrm.SizeSelectStrngGrdSelectCell(Sender: TObject;
  ACol, ARow: Integer; var CanSelect: Boolean);
var
  Select: TGridRect;
begin
  CanSelect := False;
  Select.Left := 0;
  Select.Right := 2;
  if ARow < 10 then
  begin
    Select.Top := ARow;
    Select.Bottom := SizeSelectStrngGrd.Selection.Bottom;
  end;
  if ARow > 10 then
  begin
    Select.Top := SizeSelectStrngGrd.Selection.Top;
    Select.Bottom := ARow;
  end;
  SizeSelectStrngGrd.Selection := Select;
end;

What happens is sometimes the selected cells don't always select properly. In the debugger, the value for select seems to be always set properly. Is there something wrong with the way I'm "applying" the selection?

Answer:

Your selection is overwritten when the mouse crosses a cell boundary or when the mouse button is released. SizeSelectStrngGrd.Selection. Right is made to correspond to the most recent cursor position. You can put it back like so:

procedure TForm1.SizeSelectStrngGrdMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  Select: TGridRect;
begin
  {When the mouse button is released set the right of the selected range}
  Select := SizeSelectStrngGrd.Selection;
  Select.Right := 2;
  SizeSelectStrngGrd.Selection := Select;
  {Record that the mouse button is up}
  MouseDown := false;
end;

MouseDown is a class-scope Boolean that is used later. The mouse up handler above gives the right selection, but the grid looks naff as the selected area spreads out to the right then contracts when the mouse button is released. You can improve on that by recording whether the left mouse button is up or down:

procedure TForm1.SizeSelectStrngGrdMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  {Record that the mouse button is down}
  MouseDown := mbLeft = Button;
end;

and controlling how the grid is drawn so that cells you don't want to be selected are not drawn as though they were selected:

procedure TForm1.SizeSelectStrngGrdDrawCell(Sender: TObject;
  ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
begin
  {When the mouse is down only allow cells in column two to be drawn as though they are selected}
  if ((ACol <> 2) and (gdSelected in State) and MouseDown) then
    State := State - [gdSelected];
  with SizeSelectStrngGrd.Canvas do
  begin
    {Choose a brush colour to suit the cell}
    if gdFixed in State then
      Brush.Color := clBtnFace
    else if gdSelected in State then
      Brush.Color := clHighlight
    else
      Brush.Color := clWindow;
    {Colour the cell background}
    FillRect(Rect);
    {Display the text}
    TextOut(Rect.Left + 2, Rect.Top + 2, SizeSelectStrngGrd.Cells[ACol, ARow]);
  end;
end;

This will likely need some polishing before it's ready for use, but it does let you control what is
selected.







Nincsenek megjegyzések:

Megjegyzés küldése