如何打开和关闭TStringGrid中的单元格颜色和文本 [英] How To Toggle The cell Colour And Text In A TStringGrid On And Off

查看:157
本文介绍了如何打开和关闭TStringGrid中的单元格颜色和文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在运行Lazarus v0.9.30(32位编译器).

I am running Lazarus v0.9.30 (32 bit compiler).

我有一个带有标准TStringGrid的TForm.网格设置了以下属性. RowCount = 5,ColumnCount = 5,FixedCols = 0,FixedRows = 0.

I have a TForm with a standard TStringGrid on it. The grid has the following properties set. RowCount = 5, ColumnCount = 5, FixedCols = 0, FixedRows = 0.

我用Google搜索了一些代码,该代码向我展示了如何更改单元格颜色和当用户单击TStringGrid单元格时,向该单元格添加一些文本.一切正常,我对其进行了稍微扩展,以在GridClick事件上打开和关闭颜色/文本.

I Googled some code that showed me how to change the cell colour and add some text to the cell when a user clicks on a TStringGrid cell. All works fine and I have extended it slightly to toggle the color/text on and off on the GridClick event.

我的问题更多是为了更好地理解代码某些元素的目的.

The questions I have are more to better understand the purpose behind some of the elements of the code.

有一组Foregroud(FG)和Background(BG)TColor对象.它们是否存储在GridClick事件上设置的单元格颜色属性,因此,如果出于任何原因需要再次触发DrawCell事件,则单元格可以自行重绘?您是否可以避免使用TColors数组,而仅根据需要在DrawCell事件中设置颜色/文本?

There is an array of Foregroud (FG) and Background (BG) TColor objects. Are they there to store the cell color attributes that are set on the GridClick event, so if the DrawCell event needs to get triggered again for any reason the cell can redraw itself? Can you avoid using the array of TColors and just set the colour / text in the DrawCell event as required?

如果需要使用数组,我将假定尺寸必须与Grid.ColCount和Grid.RowCount匹配(即通过Form.Create中的SetLength调用设置)

If you need to use the arrays, I would assume that dimensions must match the Grid.ColCount and Grid.RowCount (ie. set via the SetLength call in Form.Create)

有没有一种方法可以检测到您在stringgrid的5 x 5单元格之外(即在空格中)单击,从而防止GridClick调用DrawCell事件.无论您在何处单击,都始终获得Row和Col的有效值.

Is there a way to detect that you are clicking outside of the 5 x 5 cells of the stringgrid (ie in the whitespace) and thus prevent the GridClick from calling the DrawCell event. No matter where you click you always get a valid value for Row and Col.

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.

推荐答案

如果设置 AllowOutboundEvents False

If you set the AllowOutboundEvents to False, the OnClick event will be fired only when you click on a certain cell, not when you click on a whitespace. So if you use this property, you will always get valid cell coordinates when you click somewhere.

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

另一点是,您应该使用 OnPrepareCanvas 事件而不是OnDrawCell,因为在OnDrawCell中您将必须绘制所有内容,包括文本渲染.使用 OnPrepareCanvas ,您只需设置 Brush.Color

Another point is that you should use the OnPrepareCanvas event instead of OnDrawCell, because in OnDrawCell you would have to paint everything, including text rendering. With OnPrepareCanvas you just set the Brush.Color and Font.Color for each cell which is going to be rendered.

而且,您不需要使用数组,可以使用 Objects 并且还显示了 OnPrepareCanvas 事件,但请注意,此示例以及您所提问的示例都会使所有单元格(包括固定单元格)着色:

And, you don't need to use arrays, you can use the Objects like you did with your columns, but surely you can keep the colors in the arrays. In the following example I've used the Objects and there's also shown the usage of the OnPrepareCanvas event, but note that this example as well as yours from the question colorize all cells including the fixed ones:

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;

这篇关于如何打开和关闭TStringGrid中的单元格颜色和文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆