Author: Tomas Rutkauskas
Is there any way to allow the user to select multiple rows that are not consecutive
for example selecting rows 1,4,5,13, and 16 but not 2,3,6,7,8... ?
Answer:
The standard selection mechanism build into the stringgrid only supports one
consecutive block of selected cells (via the selection property). If you want more
you have to code it. Find a way to store the selected state on a per-cell or
per-row basis and then use the mouse events to give the user a means to change the
state and a OnDrawCell handler to draw the cells accordingly.
I used the fixed column 0 in this grid to store the selected state for a row, the
cell is either empty (not selected) or contains a space character (selected). I
choose to draw a selection marker in column 0 instead of painting the selected rows
with another background/ foreground color in this app. Something missing is the
ability to click on the fixed column cell to toggle the selected state. I never got
around to add that, you would use MouseToCell in OnMouseUp for that and make sure
the Row property is set to that cells row before calling ToggleSelection. More work
needs to be invested to support range selections as well.
1 const
2 sRowSelected = ' ';
3 sRowNotSelected = #0;
4
5 {This method is attached to the OnKeyPress event handler for the SGridIndications
6 object. We use it to implement selection/ deselection of rows in the grid by a
7 press of the spacebar. The grid is otherwise read-only.}
8
9 procedure TEinsendeMainForm.SGridIndicationsKeyPress(Sender: TObject; var Key:
10 Char);
11 begin
12 if key = ' ' then
13 ToggleSelectedState;
14 key := #0;
15 end;
16
17 {This method is attached to the OnMouseUp event handler for the SGridIndications
18 object. We use it to implement selection/deselection of rows in the grid by a click
19 of the mouse. Any mouse button can be used.}
20
21 procedure TEinsendeMainForm.SGridIndicationsMouseUp(Sender: TObject;
22 Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
23 begin
24 ToggleSelectedState;
25 end;
26
27 {procedure TEinsendeMainForm.SGridIndicationsDrawCell
28
29 Parameters:
30 Sender: the SGridIndications object
31 Col: column index for cell to draw
32 Row: row index for cell to draw
33 Rect: cell rectangle
34 State: cell state
35
36 Call method: static
37
38 Description:
39 This method is attached to the grids OnDrawCell event that is called every time a
40 cell needs to be draw. We rely mostly on the default drawing done by the grid
41 to display the data.The only thing we add is for the fixed column 0 cells:
42 if the cell contains a blank as a marker that it is selected we draw a red triangle
43 as a visual cue for the selected state for this row. This type of selection is
44 independend of the standard row selection the grid is set up for and allows any
45 number of rows to be selected and deselected individually. The grid does not
46 support this kind of selection directly.
47
48 Error Conditions: none
49
50 Created: 29.06.97 11:58:58 by Peter Below
51 }
52
53 procedure TEinsendeMainForm.SGridIndicationsDrawCell(Sender: TObject;
54 Col, Row: Longint; Rect: TRect; State: TGridDrawState);
55 var
56 poly: array[1..3] of TPoint;
57 dy, dx: Integer;
58 begin
59 if (Col = 0) and ((Sender as TStringGrid).Cells[0, Row] = ' ') then
60 begin
61 with TStringGrid(Sender).Canvas do
62 begin
63 Brush.Color := clRed;
64 Pen.Color := clRed;
65 poly[1].X := Rect.Right - 5;
66 poly[1].Y := (Rect.Bottom - Rect.Top) div 2 + Rect.Top;
67 dy := (Rect.Bottom - Rect.Top) * 6 div 10;
68 dx := Round(Sqrt(3 * dy * dy) / 2);
69 poly[2].X := poly[1].X - dx;
70 poly[3].X := poly[2].X;
71 poly[2].Y := poly[1].Y - dy div 2;
72 poly[3].Y := poly[1].Y + dy div 2;
73 Polygon(poly);
74 end;
75 end;
76 end;
77
78 {function TEinsendeMainForm.CountSelectedIndications
79 Parameters: none
80
81 Returns:
82 the number of rows currently marked as selected in the indication grid.
83
84 Call method: static
85
86 Description:
87 Iterates over all rows of the grid and checks the content of column 0.
88
89 Error Conditions: none
90
91 Created: 29.06.97 13:42:31 by P. Below
92 }
93
94 function TEinsendeMainForm.CountSelectedIndications: Integer;
95 var
96 i: Integer;
97 begin
98 Result := 0;
99 with SGridIndications do
100 for i := 1 to RowCount - 1 do
101 if Cells[0, i][1] = sRowSelected then
102 Inc(Result);
103 end;
104
105 {procedure TEinsendeMainForm.UnselectAllIndications
106 |
107 Parameters: none
108
109 Call method: static
110
111 Description: Deselects all indications in the indication grid.
112
113 Error Conditions: none
114
115 Created: 07.07.97 13:28:28 by P. Below
116 }
117
118 procedure TEinsendeMainForm.UnselectAllIndications;
119 var
120 i: Integer;
121 begin
122 with sGridIndications do
123 for i := 1 to RowCount - 1 do
124 Cells[0, i] := sRowNotSelected;
125 end;
126
127 {procedure TEinsendeMainForm.ToggleSelectedState
128
129 Parameters: none
130
131 Call method: static
132
133 Description:
134 Inverts the selection state of the current row in the indication grid. Called by
135 several event handlers for the grid.
136
137 Error Conditions: none
138
139 Created: 29.06.97 13:44:28 by P. Below
140 }
141
142 procedure TEinsendeMainForm.ToggleSelectedState;
143 begin
144 with SGridIndications do
145 if Cells[0, row] = sRowSelected then
146 Cells[0, row] := sRowNotSelected
147 else
148 Cells[0, row] := sRowSelected;
149 LblNumSelIndications.Caption := IntToStr(CountSelectedIndications) +
150 sIndicationsSelected;
151 end;
152
153 {procedure TEinsendeMainForm.SelectIndication
154
155 Parameters:
156 IndicationCode: the numeric (Prisma) code for the indication
157 state: new state (selected or unselected) to set.
158
159 Call method: static
160
161 Description: Searches thru the indication grid for the indication and sets it
162 state, if found.
163
164 Error Conditions: none
165
166 Created: 07.07.97 13:31:41 by P. Below
167 }
168
169 procedure TEinsendeMainForm.SelectIndication(const IndicationCode: string; state:
170 Boolean);
171 var
172 i: Integer;
173 ch: Char;
174 begin
175 with sGridIndications do
176 begin
177 i := Cols[1].IndexOf(IndicationCode);
178 if i > 0 then
179 begin
180 if state then
181 ch := sRowSelected
182 else
183 ch := sRowNotSelected;
184 Cells[0, i] := ch;
185 end;
186 end;
187 end;
|