Опубликован: 07.05.2010 | Доступ: свободный | Студентов: 2868 / 291 | Оценка: 4.49 / 4.19 | Длительность: 25:58:00
Лекция 12:

Работа с сеткой DBGrid

< Лекция 11 || Лекция 12: 123 || Лекция 13 >

Выделение отдельных строк

Очень часто в практике приходится выделять какие-то строки, изменяя их фон или цвет шрифта. Например, в бухгалтерии обычно выделяют строки, в которых значение меньше нуля. Допустим, ваша программа показывает клиентов, а какой-то столбец содержит их баланс на счету вашей компании. Если этот баланс меньше 0, значит, клиент имеет задолженность перед вашей фирмой. Бухгалтеру будет очень удобно, если дебиторы (должники) будут выделяться в общем списке красным цветом.

Способ прорисовки данных в сетке DBGrid зависит от значения ее свойства DefaultDrawing. По умолчанию свойство равно True, то есть данные прорисовываются автоматически. Если свойство содержит False, то прорисовку придется кодировать самостоятельно в свойствах OnDrawColumnCell или OnDrawDataCell, о которых уже упоминалось в этой лекции.

Если мы написали алгоритм прорисовки, но свойство DefaultDrawing содержит True, то вначале сетка заполнится данными автоматически, а затем будет выполнен наш алгоритм. Другими словами, прорисовка некоторых частей сетки будет выполнена дважды. Это не очень хорошо для быстродействия программы, однако нам придется поступать именно так: ведь мы не все строки и столбцы собираемся выводить другим способом, а только некоторые. Остальные будут заполнены данными по умолчанию.

Разберем этот метод подробней. Если найти его в справке Delphi, то увидим:

property OnDrawColumnCell: TDrawColumnCellEvent;

То есть, этот метод имеет тип TDrawColumnCellEvent. Описание типа такое:

type TDrawColumnCellEvent = procedure (Sender:TObject; const Rect:TRect; 
DataCol:Integer; Column:TColumn; State:TGridDrawState) of object;

Разберемся с параметрами.

Rect - координаты прорисовки.

DataCol - порядковый номер текущего столбца (начиная с 0).

Column - данные текущего столбца.

State - состояние ячейки. Может быть:

  • gdSelected - ячейка выделена
  • gdFocused - фокус ввода в ячейке
  • gdFixed - ячейка - заголовок столбца.

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

Выделение строк

Рис. 12.7 . Выделение строк

Заметим сразу, что наличие пустых столбцов создает дополнительные, но решаемые проблемы. Код события OnDrawColumnCell придется переделать, он будет таким:

{Прорисовка таблицы}
procedure TfMain.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
  s: String;
begin

  with DBGrid1.Canvas do begin
    //поле "Военнообязанный" содержит истину?
      if (ADOTable1['Военнообязанный'])= True and
         not (gdSelected in State) then begin
        //выводим все ячейки строки красным по белому:
        Font.Color:= clRed;
        FillRect(Rect);
      end; //if

  //если это пустой сборный столбец
  if Column.Index = 0 then begin
    if ADOTable1['Фамилия'] <> Null then
      s:= ADOTable1['Фамилия'] + ' ';
    if ADOTable1['Имя'] <> Null then
      s:= s + Copy(ADOTable1['Имя'], 1, 1) + '.';
    if ADOTable1['Отчество'] <> Null then
      s:= s + Copy(ADOTable1['Отчество'], 1, 1)+ '.';
    DBGrid1.Canvas.TextOut(Rect.Left, Rect.Top, s);
  end //if
  //если это пустой столбец с кнопкой "..."
  else if Column.Index = 6 then begin
    DBGrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State);
    Exit;
  end //if
  //все остальные столбцы
  else
    TextOut(Rect.Left+2, Rect.Top+2, Column.Field.Text);
  end; //with
end;

Разберемся с кодом. Вначале с помощью with мы указываем, что будем работать непосредственно со свойством DBGrid1.Canvas, которое отвечает за стиль прорисовки ячейки. Далее мы смотрим, содержится ли True в поле "Военнообязанный" текущей записи. Если да, то указываем, что цвет шрифта должен быть красным, а затем функцией FillRect(Rect) мы стираем стандартный вывод.

Далее мы определяем, прорисовывается ли в данный момент пустой сборный столбец с "Фамилия И.О.". Если это он, то мы формируем переменную s с нужными данными и выводим их, как в прошлый раз.

Если же это пустой столбец с кнопкой "…", то мы делаем стандартный вывод и выходим из процедуры. Если мы этого не сделаем, то получим ошибку программы.

Все остальные столбцы мы выводим строкой

TextOut(Rect.Left+2, Rect.Top+2, Column.Field.Text);

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

Некорректная прорисовка

Рис. 12.8 . Некорректная прорисовка

Количество добавляемых пикселей зависит от формата данных и размера шрифта. Обычно это определяется путем проб. Например, ячейка может содержать цифры, которые обычно прижимаются к правому краю, и тут двумя пикселями не обойтись.

Сделать проверку на тип данных можно, например, так:

//если текст, сдвинем только на 2 пикселя
if Column.Field.DataType = ftString then
  TextOut(Rect.Left, Rect.Top+2, Column.Field.Text)
//если цифры, сдвинем их вправо на 28 пикселей
else TextOut(Rect.Left+28, Rect.Top+2, Column.Field.Text);

Выделение строки красным текстом может оказаться недостаточным для заказчика. Что, если он потребует, чтобы эти строки выделялись красной строкой с белым шрифтом? Тогда вместо

Font.Color:= clRed;
FillRect(Rect);

вам придется написать

//выводим все ячейки строки белым текстом по красному фону:
Brush.Color:= clRed;
Font.Color:= clWhite;
FillRect(Rect);

Как видите, подсвойство

DBGrid1.Canvas.Brush.Color

отвечает за цвет заливки ячейки, а

DBGrid1.Canvas.Font.Color

за цвет выводимого в ней шрифта. Список доступных цветов вы можете открыть в любом свойстве Color любого компонента. Теперь вы сможете создать сетку со сложными элементами прорисовки.

< Лекция 11 || Лекция 12: 123 || Лекция 13 >
Евгений Медведев
Евгений Медведев

В лекции №2 вставляю модуль данных. При попытке заменить name на  fDM выдает ошибку: "The project already contains a form or module named fDM!". Что делать? 

Анна Зеленина
Анна Зеленина

При вводе типов успешно сохраняется только 1я строчка. При попытке ввести второй тип вылезает сообщение об ошибке "project mymenu.exe raised exception class EOleException with message 'Microsoft Драйвер ODBC Paradox В операции должен использоваться обновляемый запрос'. 

Сергей Власюк
Сергей Власюк
Украина
Игорь Крещенников
Игорь Крещенников
Россия, Новосибирск