1st Question:
How do you call the part in stringgrid that is not visible? You need to scroll to see it.
For example:
There are 20 rows in a stringgrid but you can see only 10 at a time. You need to scroll to see other 10. How are the "hidden" ones called?
2nd Question:
I know this is probably not the right way to do it so some pointers would be appreciated.
I have a string grid with 1 fixed row. I add ColorButtons at runtime. So I populate 1 column with buttons.
I use this buttons to "insert/delete" rows. As long as all of the grid is in the "visible" part this works well.
Problem occcurs when I "insert" new rows and move the buttons to the "hidden" part. The last button is then drawn to Cell[0,0]. Other buttons in the "hidden" part are drawn correctly. Any idea why this happens? Should I find a way to manage this problem in the OnDraw method or is there a better (correct) way to do this?
Code:
procedure Tform1.addButton(Grid : TStringGrid; ACol : Integer; ARow : Integer);
var
bt : TColorButton;
Rect : TRect;
index : Integer;
begin
Rect := Grid.CellRect(ACol,ARow);
bt := TColorButton.Create(Grid);
bt.Parent := Grid;
bt.BackColor := clCream;
bt.Font.Size := 14;
bt.Width := 50;
bt.Top := Rect.Top;
bt.Left := Rect.Left;
bt.Caption := '+';
bt.Name := 'bt'+IntToStr(ARow);
index := Grid.ComponentCount-1;
bt :=(Grid.Components[index] as TColorButton);
Grid.Objects[ACol,ARow] := Grid.Components[index];
bt.OnMouseUp := Grid.OnMouseUp;
bt.OnMouseMove := Grid.OnMouseMove;
bt.Visible := true;
end;
procedure MoveRowPlus(Grid : TStringGrid; Arow : Integer; stRow : Integer);
var
r, index : Integer;
bt : TColorButton;
Rect : TRect;
begin
Grid.RowCount := Grid.RowCount+stRow;
for r := Grid.RowCount - 1 downto ARow+stRow do
begin
Grid.Rows[r] := Grid.Rows[r-StRow];
end;
index := Grid.ComponentCount-1;
for r := Grid.RowCount - 1 downto ARow+stRow do
begin
bt :=(Grid.Components[index] as TColorButton);
Rect := Grid.CellRect(10,r);
bt.Top := Rect.Top;
bt.Left := Rect.Left;
Grid.Objects[10,r] := Grid.Components[index];
dec(index);
end;
for r := ARow to (ARow +stRow-1) do
begin
Grid.Rows[r].Clear;
end;
end;
procedure MoveRowMinus(Grid : TStringGrid; Arow : Integer; stRow : Integer);
var
r, index : Integer;
bt : TColorButton;
Rect : TRect;
begin
for r := ARow to Grid.RowCount-stRow-1 do
begin
Grid.Rows[r] := Grid.Rows[r+StRow];
end;
index := ARow-1;
for r := ARow to Grid.RowCount-stRow-1 do
begin
Rect := Grid.CellRect(10,r);
bt :=(Grid.Components[index] as TColorButton);
bt.Top := Rect.Top;
bt.Left := Rect.Left;
Grid.Objects[10,r] := Grid.Components[index];
bt.Visible := true;
inc(index);
end;
for r := Grid.RowCount-stRow to Grid.RowCount-1 do
begin
Grid.Rows[r].Clear;
end;
Grid.RowCount := Grid.RowCount-stRow;
end;
For the visible part there exist the
VisibleRowCount
andVisibleColCount
properties. TheTGridAxisDrawInfo
record type names the visible part Boundary and all parts together Extent (or vice versa, I never remember). So there is no specific by the VCL declared name for the unvisible part of a string grid. It just is the unvisible part.I think you are making a logical error: the buttons are not moved when you scroll the grid. Though it may seem like they move, that is just the result of moving the device context contents due to an internal call to
ScrollWindow
. The scroll bars in the string grid component are custom added, and do not work like those of e.g. aTScrollBox
.To always show all buttons on the locations where they really are, repaint the string grid in the
OnTopLeftChanged
event:When the row heights of all rows and the height of string grid never change, then it is sufficient to create all buttons only once, and let them stay where they are. This means that every button no longer is "attached" to a row, and storing them in the
Objects
property has no significance any more. When a button is pressed, simply calculate the intended row index from the position of the button in combination with theTopRow
property of the string grid which specifies the index of the first visible scrollable row in the grid.If the grid can resize, e.g. by anchors, then update the button count in the parent's OnResize event. And if the row count of the string grid may become less then the maximum visible row count, then also update the (visible) button count.
If you want more of an answer, then please update your question and explain how the
MoveRowPlus
and theMoveRowMinus
routines are called due to interaction with the grid and or buttons, because now I do not fully understand what it is that you want.And about
CellRect
giving the wrong coordinates: that is becauseCellRect
only works on full (or partial) visible cells. To quote the documentation:Addition due to OP's comments
I think the following code does what you want. The original row index of every button is stored in the
Tag
property.But may I say that this is also possible without the use of button controls: I suggest drawing fake button controls in the string grid's OnDrawCell event.