Как включить и отключить цвет и текст ячейки в TStringGrid - PullRequest
3 голосов
/ 13 марта 2012

Я использую Lazarus v0.9.30 (32-битный компилятор).

У меня есть TForm со стандартной TStringGrid.Сетка имеет следующие свойства.RowCount = 5, ColumnCount = 5, FixedCols = 0, FixedRows = 0.

Я прогуглил некоторый код , который показал мне, как изменить цвет ячейки и добавить некоторый текст в ячейку, когдапользователь нажимает на ячейку TStringGrid.Все работает нормально, и я немного расширил его, чтобы включить или выключить цвет / текст в событии GridClick.

У меня больше вопросов, чтобы лучше понять цель некоторых элементов кода.

Существует массив объектов Foregroud (FG) и Background (BG) TColor.Должны ли они хранить атрибуты цвета ячейки, которые установлены в событии GridClick, поэтому, если событие DrawCell должно быть запущено снова по какой-либо причине, ячейка может перерисовать себя?Можете ли вы избежать использования массива TColors и просто установить цвет / текст в событии DrawCell, как требуется?

Если вам нужно использовать массивы, я бы предположил, что измерения должны соответствовать Grid.ColCount и Grid.RowCount (т. Е. Устанавливается с помощью вызова SetLength в Form.Create)

Есть ли способ обнаружить, что вы щелкаете за пределами 5 × 5 ячеек сетки строк (т. Е. В пустом пространстве) и, таким образом, предотвращатьGridClick от вызова события DrawCell.Независимо от того, где вы нажимаете, вы всегда получаете действительное значение для строки и столбца.

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.

1 Ответ

4 голосов
/ 13 марта 2012

Если вы установите AllowOutboundEvents на False, событие OnClick будет срабатывать только при нажатии на определенную ячейку, а не при нажатии напробельные.Поэтому, если вы используете это свойство, вы всегда будете получать действительные координаты ячейки, когда щелкаете куда-либо.

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

Другой момент заключается в том, что вы должны использовать событие OnPrepareCanvas вместо OnDrawCell, потому что в OnDrawCell вам придется рисовать все, включая отрисовку текста.С помощью OnPrepareCanvas вы просто устанавливаете Brush.Color и Font.Color для каждой ячейки, которая будет отображаться.

Ивам не нужно использовать массивы, вы можете использовать Objects, как вы это делали со своими столбцами, но, конечно, вы можете сохранить цвета в массивах.В следующем примере я использовал Objects, и там также показано использование события OnPrepareCanvas, но обратите внимание, что этот пример, как и ваш, из вопроса colorizeвсе ячейки, включая фиксированные:

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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...