Сеточки (TStringGrid, TDrawGrid) в Delphi

  • Borderstyle— стиль обрамления. Здесь возможны варианты bssingie или bsNone. Можно самостоятельно, по очереди, установить оба этих типа и посмот­реть, что они собой представляют.
  • coiumncount — количество колонок в сетке. Оставим так, как есть — 5 штук.
  • Defauitcoiwidth — ширина колонок по умолчанию.
  • DefauitDrawing— рисование по умолчанию. Если здесь установлено true, то компонент сам будет отображать введенные данные. Если False, то это придет­ся делать самостоятельно, реагируя на соответствующие события.
  • DefauitcoiHeight— высота строк по умолчанию. Значение, установленное здесь, достаточно большое, поэтому давайте введем 16. Так сетка будет выгля­деть более элегантно, по крайней мере на мой вкус.
  • Fixedcoior— цвет фиксированных колонок и строк. В фиксированные ячейки нельзя вводить текст, они используются в качестве заголовков. На рис. 11.9 пер­вая колонка и первая строка фиксированы и поэтому отображены цветом эле­ментов управления (цвет по умолчанию).
  • Fixedcois— количество фиксированных колонок. Они всегда первые, нельзя создать фиксированную колонку в середине сетки. Хотя нет, возможно, все это только вопрос времени, но для этого придется писать код самостоятельно.
  • FixedRows— количество фиксированных строк. Они всегда первые, нельзя создать фиксированную строку в середине сетки. Это можно сделать только самостоятельно.
  • GridLinewidth — толщина разделительных линий сеток.
  • Options— настройки сетки. Если дважды щелкнуть левой кнопкой мыши по этому свойству или один раз по квадратику слева от названия свойства, то рас­кроется большой список дополнительных свойств. 

Рассмотрим каждое из них в отдельности:

    • goFixedVertLine— рисовать вертикальные линии сетки у фиксированных ячеек;
    • goFixedHorzLine— рисовать горизонтальные линии сетки у фиксированных ячеек;
    • govertLine — рисовать вертикальные линии сетки у нефиксированных ячеек;
    • goHorzLine— рисовать горизонтальные линии сетки у нефиксированных ячеек;
    • goRangeSeiect — позволять выделять несколько ячеек;
    • goDrawFocuSeiected — рисовать фокус выделенной ячейки;
    • goRowSizing — можно ли изменять размер строк перетягиванием мышью;
    • goCoisizing — можно ли изменять размер колонок перетягиванием мышью;
    • goRowMoving — можно ли перемещать строки (если true, то можно нажать кнопку мыши, установив ее указатель на фиксированную ячейку строки, и перетащить в новое положение);
    • goCoiMoving— можно ли перемещать колонки (если true, то можно нажать кнопку мыши, установив ее указатель на фиксированную ячейку колонки, и перетащить ее в новое положение);
    • goEditing— можно ли вводить с клавиатуры данные в сетку (для нашего примера установим в true);
    • goTabs — если здесь установить true, то между ячейками можно путешест­вовать с помощью клавиши <ТаЬ>;
    • goRowseiect— если здесь false, то выделяется только выделенная ячейка (если true, то вся строка);
    • goAlwaysshowEditor— если false, то когда вы обратились к ячейке, для ее редактирования нужно нажать <Enter> или <F2>, если true, то как только выделяется ячейка, ее сразу можно редактировать;
    • goThumbTracking— будут ли данные прорисовываться, пока пользователь перемещает полосу прокрутки.
  • RowCount — количество строк. Для первого примера нам хватит пяти.
  • scrollBars— нужно ли показывать полосы прокрутки. 
    • ssNone — не показывать;
    • ssHorizontal —только горизонтальную полосу;
    • ssVertical — только вертикальную полосу.
Итак, давайте напишем первый пример. Создайте обработчик события Onshow для формы и напишите там содержимое листинга 

 

procedure TMainForm.FormShow(Sender: TObject) ;

begin

// Заполняем значениями первую колонку
StringGrid1.Cells[0,1]:='Иванов';
StringGrid1.Cells[0,2]:='Петров';
StringGrid1.Cells[0,3]:='Сидоров';
StringGrid1.Cells[0,4]:='Смирнов';
// Заполняем значениями первую строку
StringGrid1.Cells[1,0]:='Год рожд.';
StringGrid1.Cells[2,0]:='Место рожд.';
StringGrid1.Cells[3,0]:='Прописка';
StringGrid1.Cells[4,0]:='Семейное положение';
end;

У объекта TStringGrid есть еще одно свойство, которое не описано в объект­ном инспекторе—cells. Это свойство—двумерный массив из строк, в которых хранятся данные, отображаемые в сетке. Чтобы получить доступ к какой-либо ячейке, нужно записать StringGridl.Cells[номер колонки, номер ячейки].

ВНИМАНИЕ. Нумерация колонок и строк начинается с нуля.

Например, если вы хоти­те записать во вторую колонку и четвертую строку текст "Привет", то необходимо записать:

StringGrid1.Cells[1,3] : = 'Привет' .

Таким же способом можно и чи­тать содержимое ячеек:

if StringGridl.Cells[1,3]='Привет' then Сделать [какие-либо действия].

 

На рис. 11.10 вы можете увидеть окно, в котором показан пример в запущен­ном виде.

 

Давайте усилим этот пример и заодно поглубже познакомимся с сеткой. Как ви­дите, в примере есть поле Год рождения. В это поле должны вводиться даты, а значит, они должны

Сеточки (TStringGrid, TDrawGrid) в Delphi

 иметь определенный формат. Было бы очень удобно, если бы в этом поле можно было бы задать маску ввода, но сетка такое не поддерживает. Тут можно использовать одну хитрость— когда пользователь щелкает мышью по нужному полю, подставлять компонент TMaskEdit, и пускай пользователь вводит информацию в него в строго определенном формате.

 

Давайте, реализуем сказанное на практике. Для этого поместите на форму ком­понент TMaskEdit (место расположения не имеет значения) и назовите его DateEdit. Установите маску для ввода даты 99/99/9999. Теперь установите у него свойство visible в false, чтобы компонент не был виден.

Создайте обработчик события onDrawCeii и в нем напишите содержимое лис­тинга: 

procedure TMainForm.StringGridlDrawCell(Sender: TObj ect; ACol,ARow: Integer; Rect: TRect; State: TGridDrawState);

begin

DateEdit.Visible := false; // Сделать невидимым компонент DateEdit

if (gdFocused in State) then // Если текущая ячейка в фокусе, то ...

begin

if ACol=l then // Если рисуется ячейка первой колонки, то ...

begin

// Записать в DateEdit текст ячейки DateEdit.Text:=StringGridl.Cells[ACol, ARow]; // Установить левую позицию

DateEdit.Left := Rect.Left + StringGridl.Left+2; // Установить верхнюю позицию

DateEdit.Top := Rect.Top + StringGridl.top+2; // Установить ширину

DateEdit.Width := Rect.Right - Rect.Left; // Установить высоту

DateEdit.Height := Rect.Bottom - Rect.Top; // Сделать компонент DateEdit видимым

DateEdit.Visible := true;

exit;

end;

end;

end;

Этот обработчик вызывается каждый раз, когда надо прорисовать какую-нибудь ячейку. Если прорисовывается вся сетка, то он вызывается для каждой ячейки отдель­но. ДЛЯ нас Delphi СОЗДал процедуру обработчик события StringGridlDrawCell со следующими параметрами:

sender-—здесь передается указатель на объект, который сгенерировал событие;

  • arow и acol — номер строки и номер столбца (координаты) ячейки, которую надо прорисовать;
  • Rect— структура, в которой указаны относительные размеры и положения ячейки.

Что понимается под словом "относительные"? Структура Rect выглядит так: 

type TRect = record

Left, Top, Right, Bottom: Integer; end;

 

Как видите, это структура из четырех параметров— левой, верхней, правой и нижней позиции. На рис. 11.11 стрел­ками показан тот размер, который будет в параметрах Left и Right структуры Rect. Размеры будут указаны в пикселах. В параметре Right будет указано рас­стояние в пикселах от левого края сетки 

до правого края ячейки, а в параметре левая и верхняя позиции ячейки

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

Ну и последний параметр, передаваемый нам в процедуру-обработчик собы­тия,— state. В нем находится информация о состоянии ячейки, которую надо прорисовать. Состояния могут быть следующими:

  • gdseiected — ячейка выделена;
  • gdFocused — ячейка имеет фокус ввода;
  • gdFixed — ячейка является фиксированной.

Если в параметре state нет ни одного из этих значений, то это простая ячейка. Параметр state объявлен как набор значений. Это значит, что он может прини­мать любое из указанных значений или их сочетания. Чтобы проверить, установле­но ли что-нибудь в state, надо написать:

if (значение in State) then Выполнить действие

Именно так проверяется во второй строке кода наличие значения gdFocused. И только если ячейка, которую надо прорисовать, имеет фокус, выполняются сле­дующие действия. Сеточки (TStringGrid, TDrawGrid) в DelphiНо перед этим мы прячем нашу маскированную строку ввода, потому что она могла находиться видимой в другой ячейке, и чтобы не было про­блем, лучше ее спрятать.

 

Если рисуемая ячейка в фокусе, мы проверяем, в какой колонке находится ри­суемая ячейка. Если это первая колонка (где мы должны вводить дату), то мы пока­зываем DateEdit на месте рисуемой ячейки. Для этого сначала присваиваем в DateEdit текст, который должен находиться в данной ячейке. Затем устанавлива­ем позицию и размеры компонента DateEdit и только потом показываем его.

 

Как видите, способ очень простой и элегантный. Теперь осталось только создать обработчик события onchange для компонента DateEdit. Это событие происходит, когда данные в строке ввода изменились, а это значит, что нам их надо сразу же прописать в редактируемую ячейку сетки, иначе они потеряются. Это потому, что все данные вводятся в DateEdit, а не в сетку, а переносить их мы должны вручную:

 

procedure TMainForm.DateEdi tChange(Sender: TObj ect);

begin

StringGridl.Cells[StringGridl.Col, StringGridl.Row]:=DateEdit.Text;

end;

 

Чтобы еще больше закрепить материал этой части главы, давайте сделаем в по­следней колонке появление компонента TСhесквох, по которому можно менять значение в ячейке между "Женат" и "Холост". Для этого на форму надо установить компонент CheckBox и сделать его невидимым. Потом надо изменить событие onDrawCeii, как это показано в листинге:

 

procedure TMainForm.StringGridlDrawCell(Sender: TObj ect; ACol,

ARow: Integer; Rect: TRect; State: TGridDrawState); begin

DateEdit.Visible := false;

CheckBoxl.Visible := false;

if (gdFocused in State) then begin if ACol=l then begin

DateEdit.Text:=StringGridl.Cells[ACol, ARow];

DateEdit.Left := Rect.Left + StringGridl.Left+2;

DateEdit.Top := Rect.Top + StringGridl.top+2;

DateEdit.Width := Rect.Right - Rect.Left;

DateEdit.Height := Rect.Bottom - Rect.Top;

DateEdit.Visible := true;

exp­end;

if ACol=4 then begin

CheckBoxl.Caption:=StringGridl.Cells[ACol, ARow];

i f CheckBoxl.Caption='ao' then CheckBoxl.Checked:=true

else

CheckBoxl.Checked:=false;

CheckBoxl.Left := Rect.Left + StringGridl.Left+2;

CheckBoxl.Top := Rect.Top + StringGridl.top+2;

CheckBoxl.Width := Rect.Right - Rect.Left;

CheckBoxl.Height := Rect.Bottom - Rect.Top;

CheckBoxl.Visible := true;

exp­end;

end;

end;

Ну и, конечно же, необходимо "поймать" событие onclick компонента CheckBox1, чтобы записать измененное значение обратно в сетку. В этом обработ­чике напишите код листинга:

procedure TMainForm.CheckBoxlClick(Sender: TObject);

begin

if CheckBoxl.Checked=true then CheckBoxl.Caption:='Женат' else

CheckBoxl.Caption: = гХолост1;

StringGridl.Cells[StringGridl.Col, StringGridl.Row]:=CheckBoxl.Caption;

end;

dle

Помоги проекту! Расскажи друзьям об этом сайте: