2012-03-13 60 views
3

私はLazarus v0.9.30(32ビットコンパイラ)を実行しています。TStringGridのセルの色とテキストをオン/オフに切り替える方法

標準のTStringGridを持つTFormがあります。グリッドには次のプロパティが設定されています。

私は、ユーザーがTStringGridセルをクリックしたときに、セルの色を変更し、セルにテキストを追加する方法を示したいくつかのグーグルcodeを見つけました。すべて正常に動作し、GridClickイベントで色やテキストをオン/オフに切り替えるために少し拡張しました。

私が持っている質問は、コードのいくつかの要素の背後にある目的をよりよく理解することです。

Foreground(FG)と背景(BG)TColorオブジェクトの配列があります。 GridClickイベントに設定されているセルの色属性を格納するのですか?そのため、何らかの理由でDrawCellイベントを再度トリガする必要がある場合は、セルを再描画できますか? TColorsの配列を使用しないで、必要に応じてDrawCellイベントの色/テキストを設定するだけですか?あなたは、配列を使用する必要がある場合、私は寸法がGrid.ColCountと一致してGrid.RowCountしなければならないことを前提としています

(すなわち。Form.CreateではsetLengthの呼び出しを介して設定)

を検出する方法はあります文字列グリッド(つまり空白)の5×5セルの外側をクリックしているため、GridClickがDrawCellイベントを呼び出すのを防ぐことができます。あなたが特定のセルをクリックしたときFalseからAllowOutboundEventsは、OnClickイベントのみが起動されます設定した場合、あなたはあなたをクリックどんなには常に行と大佐

unit testunit; 

{$mode objfpc}{$H+} 

interface 

uses 
    Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, 
    ExtCtrls, Menus, ComCtrls, Buttons, Grids, StdCtrls, Windows, Variants, 
    LCLType; 
type 

    { TForm1 } 

    TForm1 = class(TForm) 
    Grid: TStringGrid; 
    procedure FormCreate(Sender: TObject); 
    procedure GridClick(Sender: TObject); 
    procedure GridDrawCell(Sender: TObject; aCol, aRow: Integer; 
     aRect: TRect; aState: TGridDrawState); 
    end; 

var 
    Form1: TForm1; 

implementation 

var 
    FG: array of array of TColor; 
    BG: array of array of TColor; 

{$R *.lfm} 

{ TForm1 } 

procedure TForm1.FormCreate(Sender: TObject); 
var 
    Col, Row: integer; 
begin 
    // Set the sizes of the arrays 
    SetLength(FG, 5, 5); 
    SetLength(BG, 5, 5); 

    // Initialize with default colors 
    for Col := 0 to Grid.ColCount - 1 do begin 
    for Row := 0 to Grid.RowCount - 1 do begin 
     FG[Col, Row] := clBlack; 
     BG[Col, Row] := clWhite; 
    end; 
    end; 
end; 

procedure TForm1.GridDrawCell(Sender: TObject; aCol, aRow: Integer; 
    aRect: TRect; aState: TGridDrawState); 
var 
    S: string; 
begin 
    S := Grid.Cells[ACol, ARow]; 

    // Fill rectangle with colour 
    Grid.Canvas.Brush.Color := BG[ACol, ARow]; 
    Grid.Canvas.FillRect(aRect); 

    // Next, draw the text in the rectangle 
    Grid.Canvas.Font.Color := FG[ACol, ARow]; 
    Grid.Canvas.TextOut(aRect.Left + 22, aRect.Top + 2, S); 
end; 

procedure TForm1.GridClick(Sender: TObject); 
var 
    Col, Row: integer; 
begin 
    Col := Grid.Col; 
    Row := Grid.Row; 

    // Set the cell color and text to be displayed 
    if (Grid.Cells[Col,Row] <> 'Yes') then 
    begin 
     BG[Col, Row] := rgb(131, 245, 44); 
     FG[Col, Row] := RGB(0, 0, 0); 
     Grid.Cells[Col, Row] := 'Yes' 
    end {if} 
    else 
    begin 
     BG[Col, Row] := rgb(255, 255, 255); 
     FG[Col, Row] := RGB(255, 255, 255); 
     Grid.Cells[Col, Row] := ''; 
    end; {else} 
end; 

end. 

答えて

4

に有効な値を取得し、あなたはクリックしないとき空白に。したがって、このプロパティを使用すると、どこかをクリックすると常に有効なセル座標が取得されます。

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    StringGrid1.AllowOutboundEvents := False; 
    ... 
end; 

もう一つのポイントは、OnDrawCellには、テキストのレンダリングなどのすべてを、ペイントしなければならないので、あなたが、代わりにOnDrawCellOnPrepareCanvasイベントを使用する必要があるということです。 OnPrepareCanvasを使用すると、レンダリングされるセルごとにBrush.ColorFont.Colorを設定するだけです。

また、配列を使用する必要はありませんが、カラムの場合と同様にObjectsを使用できますが、配列内の色を確実に保持できます。

type 
    TCellData = class(TObject) 
    private 
    FStateYes: Boolean; 
    FForeground: TColor; 
    FBackground: TColor; 
    public 
    property StateYes: Boolean read FStateYes write FStateYes; 
    property Foreground: TColor read FForeground write FForeground; 
    property Background: TColor read FBackground write FBackground; 
    end; 

procedure TForm1.FormCreate(Sender: TObject); 
var 
    Col, Row: Integer; 
    CellData: TCellData; 
begin 
    for Col := 0 to StringGrid1.ColCount - 1 do 
    for Row := 0 to StringGrid1.RowCount - 1 do 
    begin 
     CellData := TCellData.Create; 
     CellData.StateYes := False; 
     CellData.Foreground := clBlack; 
     CellData.Background := clWhite; 
     StringGrid1.Objects[Col, Row] := CellData; 
    end; 
    StringGrid1.AllowOutboundEvents := False; 
end; 

procedure TForm1.FormDestroy(Sender: TObject); 
var 
    Col, Row: Integer; 
begin 
    for Col := 0 to StringGrid1.ColCount - 1 do 
    for Row := 0 to StringGrid1.RowCount - 1 do 
     StringGrid1.Objects[Col, Row].Free; 
end; 

procedure TForm1.StringGrid1Click(Sender: TObject); 
var 
    Col, Row: Integer; 
    CellData: TCellData; 
begin 
    Col := StringGrid1.Col; 
    Row := StringGrid1.Row; 

    if StringGrid1.Objects[Col, Row] is TCellData then 
    begin 
    CellData := TCellData(StringGrid1.Objects[Col, Row]); 
    if CellData.StateYes then 
    begin 
     StringGrid1.Cells[Col, Row] := ''; 
     CellData.StateYes := False; 
     CellData.Foreground := RGB(255, 255, 255); 
     CellData.Background := RGB(255, 255, 255); 
    end 
    else 
    begin 
     StringGrid1.Cells[Col, Row] := 'Yes'; 
     CellData.StateYes := True; 
     CellData.Foreground := RGB(0, 0, 0); 
     CellData.Background := RGB(131, 245, 44); 
    end; 
    end; 
end; 

procedure TForm1.StringGrid1PrepareCanvas(sender: TObject; aCol, aRow: Integer; 
    aState: TGridDrawState); 
var 
    CellData: TCellData; 
begin 
    if StringGrid1.Objects[ACol, ARow] is TCellData then 
    begin 
    CellData := TCellData(StringGrid1.Objects[ACol, ARow]); 
    StringGrid1.Canvas.Brush.Color := CellData.Background; 
    StringGrid1.Canvas.Font.Color := CellData.Foreground; 
    end; 
end; 
+1

何をわからない:次の例では、私はこの例だけでなく、質問からあなたとは、固定のものを含むすべてのセルを色付けすることをObjectsを使用しましたし、またOnPrepareCanvasイベントの使用方法を示していますが、注意してくださいTCustomStringGridオブジェクトを使用することを意味しますか?コードの作者はTColorsを格納する多次元配列を持っています..... TCustomStringGridを使用するとどうすれば私を助けますか? – user1174918

+0

あなたを誤解して申し訳ありません。他のヒントや例を修正して追加しました。 – TLama

+0

Ok ....私はあなたがやっていることを見る.....私はオブジェクトを持つすべてのセルをロードするつもりだった....私は 'StateYes'のようなプロパティを持っているので、TColorプロパティを追加する必要があります。質問:グリッドのDrawCellイベントを使用して、この回答のようにセルをペイントしていませんか? [リンク](http://stackoverflow.com/questions/6701462/delphi-how-can-i-change-color-of-a-cell-in-string-grid) – user1174918

関連する問題