2012-03-13 29 views
3

我正在運行Lazarus v0.9.30(32位編譯器)。如何切換單元格顏色和文本在TStringGrid開和關

我有一個TForm標準的TStringGrid就可以了。網格具有以下屬性集。行數= 5,列數= 5,FixedCols = 0,FixedRows = 0

我Google了一些code是教我如何更改單元格顏色和一些文本添加到該小區當用戶點擊一個TStringGrid細胞。所有工作正常,我已經稍微擴展它,以在GridClick事件上打開和關閉顏色/文本。

我的問題更多的是爲了更好地理解代碼中某些元素背後的目的。

有一系列Foregroud(FG)和Background(BG)TColor對象。他們是否在那裏存儲在GridClick事件中設置的單元格顏色屬性,因此如果由於某種原因需要再次觸發DrawCell事件,單元格可能會重繪自己?你可以避免使用TColors數組,只需根據需要設置DrawCell事件中的顏色/文本?

如果需要使用數組,我會假設,尺寸必須與Grid.ColCount匹配和Grid.RowCount(即通過在Form.Create的SetLength呼叫建立)

有沒有一種方法來檢測您要點擊字符串網格的5 x 5個單元格之外(即在空白處),從而阻止GridClick調用DrawCell事件。如果設置AllowOutboundEventsFalse,則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; 

另一點是,你應該使用,而不是OnDrawCellOnPrepareCanvas事件,因爲在OnDrawCell你一定要畫的一切,包括文本渲染。使用OnPrepareCanvas您只需爲將要呈現的每個單元設置Brush.ColorFont.Color

而且,您不需要使用數組,您可以像使用列一樣使用Objects,但確實可以保留數組中的顏色。在下面的例子中,我使用了Objects還有還有所示OnPrepareCanvas事件的使用,但要注意,這個例子以及你從問題上色的所有細胞,包括固定的:

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

不知道是什麼你的意思是使用TCustomStringGrid對象?代碼的作者有多維數組來存儲TColors .....如何使用TCustomStringGrid幫助我? – user1174918 2012-03-14 04:51:44

+0

對不起,誤導你。修復並添加了一些其他提示和示例。 – TLama 2012-03-14 09:45:12

+0

好的....我看到你在做什麼.....我打算加載一個對象的每個細胞....我只需要添加TColor屬性,因爲我有一個屬性,就像'StateYes' 。一個問題:您沒有使用網格DrawCell事件來繪製單元格,就像在這個答案中一樣? [鏈接](http://stackoverflow.com/questions/6701462/delphi-how-can-i-change-color-of-a-cell-in-string-grid) – user1174918 2012-03-14 12:37:47

相關問題