В лекции №2 вставляю модуль данных. При попытке заменить name на fDM выдает ошибку: "The project already contains a form or module named fDM!". Что делать? |
Работа с сеткой DBGrid
Выделение отдельных строк
Очень часто в практике приходится выделять какие-то строки, изменяя их фон или цвет шрифта. Например, в бухгалтерии обычно выделяют строки, в которых значение меньше нуля. Допустим, ваша программа показывает клиентов, а какой-то столбец содержит их баланс на счету вашей компании. Если этот баланс меньше 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;
Разберемся с параметрами.
DataCol - порядковый номер текущего столбца (начиная с 0).
Column - данные текущего столбца.
State - состояние ячейки. Может быть:
- gdSelected - ячейка выделена
- gdFocused - фокус ввода в ячейке
- gdFixed - ячейка - заголовок столбца.
Допустим, в нашем примере требуется, чтобы строки с военнообязанными сотрудниками выделялись красным цветом:
Заметим сразу, что наличие пустых столбцов создает дополнительные, но решаемые проблемы. Код события 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);
Обратите внимание, что мы добавили по два пикселя к крайней левой и крайней верхней координате ячейки. Если этого не сделать, то новая прорисовка не будет целиком закрашивать старую:
Количество добавляемых пикселей зависит от формата данных и размера шрифта. Обычно это определяется путем проб. Например, ячейка может содержать цифры, которые обычно прижимаются к правому краю, и тут двумя пикселями не обойтись.
Сделать проверку на тип данных можно, например, так:
//если текст, сдвинем только на 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 любого компонента. Теперь вы сможете создать сетку со сложными элементами прорисовки.