Delphi — цветной StringGrid

До чего же оказывается скучен в Delphi компонент StringGrid. В этой статье я расскажу как это хотя бы немного исправить. А именно, как разукрашивать у него ячейки. Но не ячейки которые попадают под конкретное условие, а именно любые. Например: ячейка которая содержит нуль должна быть синей. Для этого мы могли бы воспользоваться кодом:

if StringGrid.Cells[ACol, ARow] = '0' then
  with StringGrid.Canvas do
  begin
    Brush.Color := clBlue;
    FillRect(Rect);
  end;

Но, а если нам необходимо любой ячейке присваивать нужный нам цвет. Мне встречались на эту тему две или три статьи, но там (не хочу обидеть их авторов) скажем так не полный ход реализации. Но, одна статься меня все-таки вдохновила, воспользоваться примером из книги Дмитрия Осипова «Delphi профессиональные программирование». Там разбирался пример, как можно в ячейки StringGrid вставлять изображения. Собственно это и послужило вдохновением для написания этой статьи, но только по разукрашиванию ячеек, так как данная необходимость встречается чаще. Я решил написать на мой взгляд несколько универсальных функций, чтобы в дальнейшем не приходилось тратить время на написание кода (хотя его и немного) под различные ситуации. Дело в том, что StringGrid может хранить ссылки на объекты. Эти ссылки размещаются в массиве свойств:

Property Objects [ACol, ARow: Integer]: TObject;

Теперь приступим к практике. Создайте форму, поместите на нее StringGrid и одну кнопку.

Раскрашивание StringGrid - заготовка

Я обнулил у StringGrid свойства FixedCols и FixedRows. Ну а далее для начала нам необходимо создать новый тип:

type
  TCellsColor = class(TObject)
  public
    BrushColor: TColor; // Наш цвет

Далее создадим процедуру по созданию объектов, в которых и будем хранить значение цвета:

procedure TPrimary.CreateObj(Obj: TStringGrid);
var
  i, j: Integer;
  CellsColor: TCellsColor;
begin
  with Obj do
    for i := 0 to ColCount - 1 do
      for j := 0 to RowCount - 1 do
      begin
        CellsColor := TCellsColor.Create; // Создаем объект
        Objects[i, j] := CellsColor;      // Связываем объект с ячейкой

        if Obj.Objects[i, j] is TCellsColor then
          // Присваиваем ячейкам цвет по умолчанию
          with Obj.Objects[i, j] as TCellsColor do BrushColor := clWhite;
      end;
end;

Эту процедуру мы вызовем при показе формы:

procedure TPrimary.FormShow(Sender: TObject);
begin
  // Вызываем процедуру по созданию
  // объектов для дальнейшей приязки к ячейкам
  CreateObj(StringGrid);
end;

И не будем откладывать на потом создание процедуры по уничтожению объектов, а сразу напишем и ее:

procedure TPrimary.FreeObjects(Obj: TStringGrid);
var
  i, j: Integer;
begin
  for i := 0 to Obj.ColCount - 1 do
    for j := 0 to Obj.RowCount - 1 do
      if Obj.Objects[i, j] is TCellsColor then
        // Уничтожаем объект
        with Obj.Objects[i, j] as TCellsColor do free;
end;

Эту процедуру мы вызовем при закрытии формы:

procedure TPrimary.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  // Вызов процедуры для уничтожения
  // созданных объектов
  FreeObjects(StringGrid);
end;

Еще нам осталось создать процедуру по разукрашиванию ячеек и написать немного кода в обработчике события отвечающего за прорисовку ячеек StringGrid. Напишем для начала процедуру для разукрашивания ячеек:

procedure TPrimary.Painting(Obj: TStringGrid);
var
  i, j: Integer;
begin
  Randomize;
  for i := 0 to Obj.ColCount - 1 do
    for j := 0 to Obj.RowCount - 1 do
      if Obj.Objects[i, j] is TCellsColor then
        with Obj.Objects[i, j] as TCellsColor do
            BrushColor:= Random(10000000);

  Obj.Repaint; // Перерисовка Grid
end;

Цвет ячеек для демонстрации выбирается случайно. Теперь делаем последние штрихи, а именно напишем код в обработчике события отвечающего за прорисовку ячеек:

procedure TPrimary.StringGridDrawCell(Sender: TObject; ACol,
  ARow: Integer; Rect: TRect; State: TGridDrawState);
begin
  if StringGrid.Objects[ACol, ARow] is TCellsColor then
    with StringGrid.Canvas do
    begin
      // Преобразовываем к типу TCellsColor и извлекаем цвет ячейки
      Brush.Color := TCellsColor(StringGrid.Objects[ACol, ARow]).BrushColor;
      // Заполняем ячейку
      FillRect(Rect);
    end;
end;

Теперь мы можем посмотреть, что у нас получилось. Для этого вызовем следующую процедуру и передадим ей ссылку на объект StringGrid:

Painting(StringGrid);

Ну, вот и все можно наслаждаться результатом.

Раскрашенный StringGrid

Самое обидное то, что вот такие мелочи, бывает, иногда стопорят работу. Надеюсь, что кому ни будь это поможет. Здесь можно скачать исходник.