2012-01-28 17 views
2

第1質問:ボタン付き文字列グリッド

どのように表示されない文字列グリッドの部分を呼び出しますか?あなたはそれを見るためにスクロールする必要があります。
例:
文字列グリッドに20行ありますが、一度に10文字しか表示されません。あなたは他の10を見るためにスクロールする必要があります。どのように "隠された"ものが呼び出されますか?

第二問:

私は、これはおそらく、いくつかのポインタをいただければ幸いですので、それを行うには正しい方法ではありません知っています。
私は1つの固定された行の文字列グリッドを持っています。実行時にColorButtonを追加します。だから私は1つの列にボタンを設定します。 このボタンを使って行を「挿入/削除」します。すべてのグリッドが「目に見える」部分にある限り、これはうまく機能します。 新しい行を「挿入」し、ボタンを「隠し」部分に移動すると、問題が発生することがあります。最後のボタンはCell [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のボタンにアクセスしようとしましたが、「アクセスが拒否されました」というエラーが表示されます。ドッキングボタンをグリッドセルにドックしましたが、最後に表示されるボタンの高さがグリッドの目に見える部分に縮小されます。もちろん、最後のボタンはCell [0,0]に描画されます。 – user805528

答えて

5
  1. 可視部分についてVisibleRowCountVisibleColCount特性が存在します。 TGridAxisDrawInfoレコードタイプは可視部分の名前を境界とすべての部分を合わせてエクステント(またはその逆、私は決して覚えていません)。そのため、文字列グリッドの不可視部分のVCL宣言された名前では特定のものはありません。 目に見えない部分です。

  2. グリッドをスクロールすると、ではなく、のボタンが移動していると誤解していると思います。移動しているように見えるかもしれませんが、それはScrollWindowへの内部呼び出しのためにデバイスコンテキストの内容を移動した結果にすぎません。文字列グリッドコンポーネントのスクロールバーはカスタム追加されており、たとえばTScrollBox。その後、

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

    は、すべての行の行の高さと列のグリッドの高さが変化することはありません:

    は常に、彼らが実際にある場所にすべてのボタンを表示OnTopLeftChangedイベントに文字列のグリッドを再描画するにはすべてのボタンを1回だけ作成して、そのボタンを押したままにしておけば十分です。これは、すべてのボタンが行に「アタッチ」されておらず、Objectsプロパティにそれらを格納することはもはや意味を持ちません。ボタンを押すと、ボタンの位置から目的の行インデックスをグリッドの最初に表示されるスクロール可能な行のインデックスを指定する文字列グリッドのTopRowプロパティと組み合わせて計算します。

    グリッドのサイズを変更できる場合は、アンカーによって、親のOnResizeイベントのボタン数を更新します。文字列グリッドの行数が表示可能な最大行数より少なくなる場合は、(表示可能な)ボタン数も更新してください。

    もっと答えが必要な場合は、質問を更新し、グリッドやボタンとのやりとりのためにMoveRowPlusMoveRowMinusルーチンがどのように呼び出されたかを説明してください。欲しいです。

    CellRectは、間違った座標を示します。つまり、CellRectは完全な(または部分的な)可視セルでのみ機能するためです。 OPのコメント

    私は次のコードは何をしたいんだと思うに

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


追加:documentationを引用します。各ボタンの元の行インデックスは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

+0

(コメント2/2)..2空の行には「副照会」が設定されます。ボタンの数は同じままです。もう一度ボタンをクリックすると(今キャプション付き:= ' - ')MoveRowMinusが呼び出され、グリッドが初期状態に戻ります。 (サブクエリが閉じます)。私は、私が達成したいと思っていることについて私が十分に明確であったことを願っています。これはObjectプロパティを使わなくても達成できると思いますか? (NGLNで - atNameはうまくいきません) – user805528

+0

(atNGLN)ありがとうございます。これは私が必要とするものです。私は自分で偽のボタンを描くことを検討していましたが、この解決法はずっと良くなっています。私はこの方法を使うことの "賛否両論"に込められています。なぜonDrawの使用をお勧めしますか?あなたの時間とインテリジェントに感謝します。 I.Bagon – user805528

関連する問題