2012-01-28 59 views
2

1問:Stringgrid的按鈕

你怎麼稱呼的部分stringgrid不可見?你需要滾動才能看到它。
例如:
stringgrid中有20行,但一次只能看到10行。你需要滾動查看其他10.如何「隱藏」的叫?

第二個問題:

我知道這可能不是做正確的方式,使一些三分球,將不勝感激。
我有一個固定行的字符串網格。我在運行時添加ColorButtons。所以我用按鈕填充1列。 我使用這個按鈕來「插入/刪除」行。只要所有的網格都處於「可見」部分,這就很好。 當我「插入」新行並將按鈕移動到「隱藏」部分時,會出現問題。最後一個按鈕然後被繪製到單元格[0,0]。 「隱藏」部分中的其他按鈕繪製正確。任何想法爲什麼發生這種情況我應該在OnDraw方法中找到一種方法來管理這個問題,或者有更好的方法來做到這一點嗎?

代碼:

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; 
+0

好吧,我已經嘗試訪問OnDrawCell中的按鈕,但我得到「訪問被拒絕」的錯誤。我嘗試將按鈕對接到網格單元格,但最後可見的按鈕高度降低到網格的可見部分。當然最後一個按鈕被繪製到單元[0,0]。 – user805528 2012-01-28 20:08:53

回答

5
  1. 對於可見部分存在的VisibleRowCountVisibleColCount性能。 TGridAxisDrawInfo記錄類型名稱可見部分邊界和所有部分在一起範圍(反之亦然,我從來不記得)。所以沒有特定的VCL聲明的字符串網格的不可見部分的名稱。它只是不可見部分

  2. 我認爲你在製作一個邏輯錯誤:按鈕是而不是當你滾動網格時移動。雖然看起來像是在移動,但這只是由於內部調用ScrollWindow而導致移動設備上下文內容的結果。字符串網格組件中的滾動條是自定義添加的,並且不像那些例如那樣。一個TScrollBox

    始終顯示在哪裏他們真的是地點的所有按鍵,重繪字符串中的網格OnTopLeftChanged事件:

    procedure TForm1.StringGrid1TopLeftChanged(Sender: TObject); 
    begin 
        StringGrid1.Repaint; 
    end; 
    

    當所有行的行高和串格的高度不能改變的,那麼僅創建一次所有按鈕就足夠了,並讓它們保持在原來的位置。這意味着每個按鈕不再「附加」到一行,並將它們存儲在Objects屬性中不再有任何意義。按下按鈕時,只需從按鈕位置計算預期行索引,並結合指定網格中第一個可見滾動行的索引的字符串網格的TopRow屬性。

    如果網格可以調整大小,例如通過錨點,然後更新父級的OnResize事件中的按鈕計數。如果字符串網格的行數可能小於最大可見行數,那麼也更新(可見)按鈕數。

    如果你想要更多的答案,那麼請更新您的問題,並解釋如何MoveRowPlusMoveRowMinus程序被稱爲由於與電網和或按鈕的互動,因爲現在我不完全理解的是,你什麼想。

    而大約CellRect給出了錯誤的座標:這是因爲CellRect只適用於完整(或部分)可見單元格。引述documentation

    If the indicated cell is not visible, CellRect returns an empty rectangle.


加成由於OP的評論

我認爲下面的代碼你想要做什麼。每個按鈕的原始行索引都存儲在Tag屬性中。

unit Unit1; 

interface 

uses 
    Windows, Classes, Controls, Forms, StdCtrls, Grids; 

type 
    TForm1 = class(TForm) 
    Grid: TStringGrid; 
    procedure GridTopLeftChanged(Sender: TObject); 
    procedure FormCreate(Sender: TObject); 
    private 
    FPrevTopRow: Integer; 
    procedure CreateGridButtons(ACol: Integer); 
    procedure GridButtonClick(Sender: TObject); 
    procedure RearrangeGridButtons; 
    function GetInsertRowCount(ARow: Integer): Integer; 
    function GridButtonToRow(AButton: TButton): Integer; 
    procedure MoveGridButtons(ButtonIndex, ARowCount: Integer); 
    end; 

implementation 

{$R *.dfm} 

type 
    TStringGridAccess = class(TStringGrid); 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    FPrevTopRow := Grid.TopRow; 
    CreateGridButtons(2); 
end; 

procedure TForm1.CreateGridButtons(ACol: Integer); 
var 
    R: TRect; 
    I: Integer; 
    Button: TButton; 
begin 
    R := Grid.CellRect(ACol, Grid.FixedRows); 
    Inc(R.Right, Grid.GridLineWidth); 
    Inc(R.Bottom, Grid.GridLineWidth); 
    for I := Grid.FixedRows to Grid.RowCount - 1 do 
    begin 
    Button := TButton.Create(Grid); 
    Button.BoundsRect := R; 
    Button.Caption := '+'; 
    Button.Tag := I; 
    Button.ControlStyle := [csClickEvents]; 
    Button.OnClick := GridButtonClick; 
    Button.Parent := Grid; 
    Grid.Objects[0, I] := Button; 
    OffsetRect(R, 0, Grid.DefaultRowHeight + Grid.GridLineWidth); 
    end; 
end; 

procedure TForm1.GridButtonClick(Sender: TObject); 
var 
    Button: TButton absolute Sender; 
    N: Integer; 
    I: Integer; 
begin 
    N := GetInsertRowCount(Button.Tag); 
    if Button.Caption = '+' then 
    begin 
    Button.Caption := '-'; 
    Grid.RowCount := Grid.RowCount + N; 
    for I := 1 to N do 
     TStringGridAccess(Grid).MoveRow(Grid.RowCount - 1, 
     GridButtonToRow(Button) + 1); 
    MoveGridButtons(Button.Tag, N); 
    end 
    else 
    begin 
    Button.Caption := '+'; 
    for I := 1 to N do 
     TStringGridAccess(Grid).MoveRow(GridButtonToRow(Button) + 1, 
     Grid.RowCount - 1); 
    Grid.RowCount := Grid.RowCount - N; 
    MoveGridButtons(Button.Tag, -N); 
    end; 
end; 

procedure TForm1.GridTopLeftChanged(Sender: TObject); 
begin 
    RearrangeGridButtons; 
    FPrevTopRow := Grid.TopRow; 
end; 

procedure TForm1.RearrangeGridButtons; 
var 
    I: Integer; 
    Shift: Integer; 
begin 
    Shift := (Grid.TopRow - FPrevTopRow) * 
    (Grid.DefaultRowHeight + Grid.GridLineWidth); 
    for I := 0 to Grid.ControlCount - 1 do 
    begin 
    Grid.Controls[I].Top := Grid.Controls[I].Top - Shift; 
    Grid.Controls[I].Visible := Grid.Controls[I].Top > 0; 
    end; 
end; 

function TForm1.GetInsertRowCount(ARow: Integer): Integer; 
begin 
    //This function should return the number of rows which is to be inserted 
    //below ARow. Note that ARow refers to the original row index, that is: 
    //without account for already inserted rows. For now, assume three rows: 
    Result := 3; 
end; 

function TForm1.GridButtonToRow(AButton: TButton): Integer; 
begin 
    for Result := 0 to Grid.RowCount - 1 do 
    if Grid.Objects[0, Result] = AButton then 
     Exit; 
    Result := -1; 
end; 

procedure TForm1.MoveGridButtons(ButtonIndex, ARowCount: Integer); 
var 
    I: Integer; 
begin 
    for I := 0 to Grid.ControlCount - 1 do 
    if Grid.Controls[I].Tag > ButtonIndex then 
     Grid.Controls[I].Top := Grid.Controls[I].Top + 
     ARowCount * (Grid.DefaultRowHeight + Grid.GridLineWidth); 
end; 

end. 

但我可以說,這也是可能的,而無需使用按鈕控件:我建議在字符串網格的OnDrawCell事件繪製假按鈕控件。

+0

(評論1/2)謝謝你的回答。我今天會嘗試。我看到我對我想達到的目標有點不清楚。我想用數據和按鈕填充網格。當用戶點擊一個按鈕(標題:='+')時,MoveRowPlus被調用參數:Grid,ARow(按鈕所在的行)和stRow(需要在ARow下插入的行數)。例如:我有20行20個按鈕。我點擊第3行的按鈕,將第4行到第20行移動到stRow。如果stRow是2,那麼第4行變成第6行,直到網格結束。 (按鈕隨指定的行移動)然後填充2個空行 – user805528 2012-01-29 13:44:41

+0

(評論2/2)..2空行隨後填充「子查詢」。按鈕數量保持不變。當我再次點擊按鈕(現在帶有標題:=' - ')時,MoveRowMinus被調用並且Grid返回初始狀態。 (子查詢關閉)。我希望我對我想達到的目標足夠清楚。你認爲這可以在不使用Object屬性的情況下實現嗎? (在NGLN - 對不起atName似乎不起作用) – user805528 2012-01-29 13:54:00

+0

(atNGLN)謝謝。這正是我需要的。我正在考慮自己繪製假按鈕,但是這個解決方案看起來好多了。我在使用這種方法的「優點和缺點」中有所作爲。爲什麼你推薦使用onDraw?謝謝你的時間和英特爾。 I.Bagon – user805528 2012-01-29 18:10:04