Author: Tomas Rutkauskas
I'm attempting to force a selection of cells based on the user clicking in the
grid. Here is my code:
1 2 procedure TSizeSelectFrm.SizeSelectStrngGrdSelectCell(Sender: TObject;
3 ACol, ARow: Integer; var CanSelect: Boolean);
4 var5 Select: TGridRect;
6 begin7 CanSelect := False;
8 Select.Left := 0;
9 Select.Right := 2;
10 if ARow < 10 then11 begin12 Select.Top := ARow;
13 Select.Bottom := SizeSelectStrngGrd.Selection.Bottom;
14 end;
15 if ARow > 10 then16 begin17 Select.Top := SizeSelectStrngGrd.Selection.Top;
18 Select.Bottom := ARow;
19 end;
20 SizeSelectStrngGrd.Selection := Select;
21 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:
22 23 procedure TForm1.SizeSelectStrngGrdMouseUp(Sender: TObject;
24 Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
25 var26 Select: TGridRect;
27 begin28 {When the mouse button is released set the right of the selected range}29 Select := SizeSelectStrngGrd.Selection;
30 Select.Right := 2;
31 SizeSelectStrngGrd.Selection := Select;
32 {Record that the mouse button is up}33 MouseDown := false;
34 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:
35 36 procedure TForm1.SizeSelectStrngGrdMouseDown(Sender: TObject;
37 Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
38 begin39 {Record that the mouse button is down}40 MouseDown := mbLeft = Button;
41 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:
42 43 procedure TForm1.SizeSelectStrngGrdDrawCell(Sender: TObject;
44 ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
45 begin46 {When the mouse is down only allow cells in column two to be drawn as though they 47 are selected}48 if ((ACol <> 2) and (gdSelected in State) and MouseDown) then49 State := State - [gdSelected];
50 with SizeSelectStrngGrd.Canvas do51 begin52 {Choose a brush colour to suit the cell}53 if gdFixed in State then54 Brush.Color := clBtnFace
55 elseif gdSelected in State then56 Brush.Color := clHighlight
57 else58 Brush.Color := clWindow;
59 {Colour the cell background}60 FillRect(Rect);
61 {Display the text}62 TextOut(Rect.Left + 2, Rect.Top + 2, SizeSelectStrngGrd.Cells[ACol, ARow]);
63 end;
64 end;
This will likely need some polishing before it's ready for use, but it does let you
control what is
selected.