2005. február 26., szombat
Select multiple rows in a TStringGrid
Problem/Question/Abstract:
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.
const
sRowSelected = ' ';
sRowNotSelected = #0;
{This method is attached to the OnKeyPress event handler for the SGridIndications object. We use it to implement selection/ deselection of rows in the grid by a press of the spacebar. The grid is otherwise read-only.}
procedure TEinsendeMainForm.SGridIndicationsKeyPress(Sender: TObject; var Key: Char);
begin
if key = ' ' then
ToggleSelectedState;
key := #0;
end;
{This method is attached to the OnMouseUp event handler for the SGridIndications object. We use it to implement selection/deselection of rows in the grid by a click of the mouse. Any mouse button can be used.}
procedure TEinsendeMainForm.SGridIndicationsMouseUp(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
ToggleSelectedState;
end;
{procedure TEinsendeMainForm.SGridIndicationsDrawCell
Parameters:
Sender: the SGridIndications object
Col: column index for cell to draw
Row: row index for cell to draw
Rect: cell rectangle
State: cell state
Call method: static
Description:
This method is attached to the grids OnDrawCell event that is called every time a
cell needs to be draw. We rely mostly on the default drawing done by the grid
to display the data.The only thing we add is for the fixed column 0 cells:
if the cell contains a blank as a marker that it is selected we draw a red triangle as a visual cue for the selected state for this row. This type of selection is independend of the standard row selection the grid is set up for and allows any
number of rows to be selected and deselected individually. The grid does not support this kind of selection directly.
Error Conditions: none
Created: 29.06.97 11:58:58 by Peter Below
}
procedure TEinsendeMainForm.SGridIndicationsDrawCell(Sender: TObject;
Col, Row: Longint; Rect: TRect; State: TGridDrawState);
var
poly: array[1..3] of TPoint;
dy, dx: Integer;
begin
if (Col = 0) and ((Sender as TStringGrid).Cells[0, Row] = ' ') then
begin
with TStringGrid(Sender).Canvas do
begin
Brush.Color := clRed;
Pen.Color := clRed;
poly[1].X := Rect.Right - 5;
poly[1].Y := (Rect.Bottom - Rect.Top) div 2 + Rect.Top;
dy := (Rect.Bottom - Rect.Top) * 6 div 10;
dx := Round(Sqrt(3 * dy * dy) / 2);
poly[2].X := poly[1].X - dx;
poly[3].X := poly[2].X;
poly[2].Y := poly[1].Y - dy div 2;
poly[3].Y := poly[1].Y + dy div 2;
Polygon(poly);
end;
end;
end;
{function TEinsendeMainForm.CountSelectedIndications
Parameters: none
Returns:
the number of rows currently marked as selected in the indication grid.
Call method: static
Description:
Iterates over all rows of the grid and checks the content of column 0.
Error Conditions: none
Created: 29.06.97 13:42:31 by P. Below
}
function TEinsendeMainForm.CountSelectedIndications: Integer;
var
i: Integer;
begin
Result := 0;
with SGridIndications do
for i := 1 to RowCount - 1 do
if Cells[0, i][1] = sRowSelected then
Inc(Result);
end;
{procedure TEinsendeMainForm.UnselectAllIndications
|
Parameters: none
Call method: static
Description: Deselects all indications in the indication grid.
Error Conditions: none
Created: 07.07.97 13:28:28 by P. Below
}
procedure TEinsendeMainForm.UnselectAllIndications;
var
i: Integer;
begin
with sGridIndications do
for i := 1 to RowCount - 1 do
Cells[0, i] := sRowNotSelected;
end;
{procedure TEinsendeMainForm.ToggleSelectedState
Parameters: none
Call method: static
Description:
Inverts the selection state of the current row in the indication grid. Called by several event handlers for the grid.
Error Conditions: none
Created: 29.06.97 13:44:28 by P. Below
}
procedure TEinsendeMainForm.ToggleSelectedState;
begin
with SGridIndications do
if Cells[0, row] = sRowSelected then
Cells[0, row] := sRowNotSelected
else
Cells[0, row] := sRowSelected;
LblNumSelIndications.Caption := IntToStr(CountSelectedIndications) +
sIndicationsSelected;
end;
{procedure TEinsendeMainForm.SelectIndication
Parameters:
IndicationCode: the numeric (Prisma) code for the indication
state: new state (selected or unselected) to set.
Call method: static
Description: Searches thru the indication grid for the indication and sets it state, if found.
Error Conditions: none
Created: 07.07.97 13:31:41 by P. Below
}
procedure TEinsendeMainForm.SelectIndication(const IndicationCode: string; state:
Boolean);
var
i: Integer;
ch: Char;
begin
with sGridIndications do
begin
i := Cols[1].IndexOf(IndicationCode);
if i > 0 then
begin
if state then
ch := sRowSelected
else
ch := sRowNotSelected;
Cells[0, i] := ch;
end;
end;
end;
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése