Продолжим разбираться с компонентом TjvTFDays – сеткой для отображения запланированных событий на день или произвольный период времени.
На данный момент я постарался рассмотреть все свойства этого компонента и уместил свой обзор в двух статьях:
- Jv TimeFrameWork. Свойства компонента TjvTFDays.
- Jv TimeFrameWork. Свойства компонента TjvTFDays. Продолжение
Для начала, предлагаю написать простенькую программку, с помощью которой мы и будем исследовать действие тех или иных методов. Смысл программы будет прост – добавить в сетку расписания новое событие и по запросу прочитать те иные свойства объектов.
Заготовка для приложения
В целом листинг этой программы я уже приводил в статье, посвященной свойствам компонента, но для порядка приведу весь код и в этом посте. Итак, внешний вид программы будет таким:
На форме расположены всего три компонента:
- ScheduleManager: TJvTFScheduleManager
- DayGrid: TJvTFDays
- Memo1: TMemo
“Скелет” программы будет как показано в листинге ниже. Остальное будем дописывать по мере изучения методов компонента:
unit main; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, JvExControls, JvTFManager, JvTFDays; type TMainForm = class(TForm) ScheduleManager: TJvTFScheduleManager; DayGrid: TJvTFDays; Memo1: TMemo; procedure DayGridDblClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var MainForm: TMainForm; implementation {$R *.dfm} procedure TMainForm.DayGridDblClick(Sender: TObject); var I: Integer; Appt: TJvTFAppt; ApptStartDate, ApptEndDate: TDate; ApptStartTime, ApptEndTime: TTime; begin with DayGrid do If DayGrid.ValidSelection Then //если выделена область вне заголовка Begin {определяем время действия для будущего события} ApptStartDate := Cols[SelStart.X].SchedDate; ApptEndDate := Cols[SelEnd.X].SchedDate; ApptStartTime := RowToTime(SelStart.Y); ApptEndTime := RowEndTime(SelEnd.Y); {создаем событие} Appt := ScheduleManager.dbNewAppt(''); With Appt do Begin Appt.BeginUpdate; Try //устанавливаем дату и время SetStartEnd(ApptStartDate, ApptStartTime, ApptEndDate, ApptEndTime); Description := 'Описание события'; //добавляем в расписание Appt.AddSchedule(Cols[0].SchedName); Finally Appt.EndUpdate; End; End End; end; end.
Двойной клик по сетке расписания добавит в то место, где был курсор мыши, новое событие. Теперь приступим к изучению методов.
Методы для работы с линиями захвата
Группа этих методов предназначена для того, чтобы получить размеры и положение линий захвата, а также определить находится ли какая-либо точка внутри линии.
Всего в группу входят четыре метода:
function GetTopGrabHandleRect(Col: Integer; Appt: TJvTFAppt): TRect;
Возвращает запись TRect, соответствующую верхней линии захвата для события Appt, содержащегося в колонке расписания Col
function GetBottomGrabHandleRect(Col: Integer; Appt: TJvTFAppt): TRect;
Возвращает запись TRect, соответсвующую нижней линии захвата для события Appt, содержащегося в колонке расписания Col
function PtInTopHandle(APoint: TPoint; Col: Integer; Appt: TJvTFAppt): Boolean;
Возвращает True, если точка TPoint находится на верхней линии захвата события Appt из колонки Col
function PtInBottomHandle(APoint: TPoint; Col: Integer; Appt: TJvTFAppt): Boolean;
Возвращает True, если точка TPoint находится на нижней линии захвата события Appt из колонки Col
Пример использования методов
Для демонстрации работы этих методов добавим в раздел public главной формы переменную:
SelectedAppt: TJvTFAppt;
Теперь воспользуемся событием SelectingAppt у компонента DayGrid.
property OnSelectingAppt: TJvTFVarApptEvent read FOnSelectingAppt write FOnSelectingAppt; TJvTFVarApptEvent = procedure(Sender: TObject; var Appt: TJvTFAppt) of object;
Это событие срабатывает всегда, когда мы пробуем выделить что-либо в сетке расписания. Если выделяется событие, то в переменной Appt возвращается объект, иначе nil.
Напишем для события такой обработчик:
procedure TMainForm.DayGridSelectingAppt(Sender: TObject; var Appt: TJvTFAppt); var Rect: TRect; begin if Assigned(Appt) then begin SelectedAppt:=Appt; //верхняя линия захвата Rect := DayGrid.GetTopGrabHandleRect(0, Appt); Memo1.Lines.Add('<--- Top Grab Handle Rec --->'); Memo1.Lines.Add('Left = ' + IntToStr(Rect.Left)); Memo1.Lines.Add('Top = ' + IntToStr(Rect.Top)); Memo1.Lines.Add('Right = ' + IntToStr(Rect.Right)); Memo1.Lines.Add('Bottom = ' + IntToStr(Rect.Bottom)); //нижняя линия захвата Rect := DayGrid.GetBottomGrabHandleRect(0, Appt); Memo1.Lines.Add('<--- Bottom Grab Handle Rec --->'); Memo1.Lines.Add('Left = ' + IntToStr(Rect.Left)); Memo1.Lines.Add('Top = ' + IntToStr(Rect.Top)); Memo1.Lines.Add('Right = ' + IntToStr(Rect.Right)); Memo1.Lines.Add('Bottom = ' + IntToStr(Rect.Bottom)); end; end;
Теперь, если в сетке будет выделено событие, то в Memo1 выведутся значения прямоугольников, соответствующих линий захвата. Например так:
Для того, чтобы продемонстрировать работу методов PtInTopHandle и PtInBottomHandle создадим обработчик события OnMouseMove у DayGrid со следующим содержимым:
procedure TMainForm.DayGridMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin if Assigned(SelectedAppt) then if DayGrid.PtInTopHandle(Point(X,Y),0,SelectedAppt) then Memo1.Lines.Add(Format('Точка (%d, %d) находится на верхней линии захвата',[X,Y])) else if DayGrid.PtInBottomHandle(Point(X,Y),0,SelectedAppt) then Memo1.Lines.Add(Format('Точка (%d, %d) находится на нижней линии захвата',[X,Y])) end;
Теперь запустите приложение, добавьте новое событие, выделите его и перемещайте курсор мыши по любой линии захвата — в мемо буду выводится соответствующие сообщения:
Методы для работы с отдельными областями сетки расписания
В эту группу входят методы для получения координат ячеек их размеров, положения в сетке и т.д.
function GetAdjClientRect: TRect;
Вызывается для того, чтобы получить значение прямоугольника регулируемой клиентской части компонента. Из размеров прямоугольника исключаются полосы прокрутки.
function GetDataAreaRect: TRect;
Возвращает значения прямоугольника области сетки расписания. Из размеров прямоугольника исключаются размеры полос прокрутки, а также ширина, заданная в свойстве FancyRowHdrAttr
function GetDataWidth: Integer;
Возвращает значение ширины области для добавления данных. Это же значение можно получить из значения, возвращаемого методом GetDataAreaRect
function GetDataHeight: Integer;
Возвращает значение высоты области для добавления данных. Это же значение можно получить из значения, возвращаемого методом GetDataAreaRect
function PtToCell(X, Y: Integer): TJvTFDaysCoord;
Метод возвращает запись TJvTFDaysCoord, содержащую данные по ячейке в которой находится точка с координатами X, Y. TJvTFDaysCoord содержит следующие данные:
TJvTFDaysCoord = record Col: Integer; {индекс колонки} Row: Integer; {индекс строки} CellX: Integer;{координата X относительно левой границы ячейки} CellY: Integer;{координата Y относительно верхней границы ячейки} AbsX: Integer;{координата X точки внутри компонента} AbsY: Integer;{координата Y точки внутри компонента} {Может содержать nil, если координаты точки находятся вне сетки} {например, в области для вывода времени (FancyRowHdrAttr)} Schedule: TJvTFSched; {Может содержать nil, если ячейка не содержит никаких событий} Appt: TJvTFAppt; DragAccept: Boolean;{Ячейка может быть приемником объекта при реализации Drag&Drop} end;
function CellRect(Col, Row: Integer): TRect;
Возвращает значения прямоугольника для видимой ячейки сетки. Если ячейка не видима в данный момент, то метод вернет пустой TRect
function VirtualCellRect(Col, Row: Integer): TRect;
Возвращает значения прямоугольника для любой ячейки сетки даже если ячейка лежит вне видимой области сетки
function GetApptRect(Col: Integer; Appt: TJvTFAppt): TRect;
Возвращает значения прямоугольника для события Appt, размещенного в колонке Col. Если Appt=nil метод возвращает EmptyRect
function CalcGroupHdrHeight: Integer;
Вычисляет высоту области заголовка для группы
function CalcGroupColHdrsHeight: Integer;
Вычисляет высоту области заголовка видимой в данный момент группы
function VirtualGroupHdrRect(Col: Integer): TRect;
Возвращает значения прямоугольника ограничивающего область заголовка группы в колонке с индексом Col
procedure GetGroupStartEndCols(Col: Integer; var StartCol, EndCol: Integer);
Возвращает в индексы Начальной и Конечной колонки, входящих в группу.
Пример использования методов
Рассмотрим действие некоторых из методов, представленных в группе. Создадим такие обработчики событий:
OnCreate главной формы приложения:
procedure TMainForm.FormCreate(Sender: TObject); var Rect: TRect; DataHeight, DataWidth: integer; begin Memo1.Lines.Add('Параметры областей для DayGrid'); Rect:=DayGrid.GetAdjClientRect; Memo1.Lines.Add(Format('Adjust Client Rect: Left = %d, Top = %d, Right = %d, Bottom = %d', [Rect.Left,Rect.Top,Rect.Right,Rect.Bottom])); Rect:=DayGrid.GetDataAreaRect; Memo1.Lines.Add(Format('Data Area Rect: Left = %d, Top = %d, Right = %d, Bottom = %d', [Rect.Left,Rect.Top,Rect.Right,Rect.Bottom])); DataWidth:=DayGrid.GetDataWidth; DataHeight:=DayGrid.GetDataHeight; Memo1.Lines.Add(Format('Data. linear dimensions: Width = %d, Height = %d', [DataWidth,DataHeight])); end;
OnMouseUp компонента DayGrid
procedure TMainForm.DayGridMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var Coord: TJvTFDaysCoord; Rect: TRect; begin Coord:=DayGrid.PtToCell(X,Y); Memo1.Lines.Add(Format('Колонка %d Строка %d Координаты ячейки: X = %d Y = %d Абсолютные координаты: X = %d Y = %d', [Coord.Col, Coord.Row, Coord.CellX, Coord.CellY, Coord.AbsX, Coord.AbsY])); if Assigned(Coord.Appt) then Memo1.Lines.Add('В этой ячейке содержится событие'); Memo1.Lines.Add(Coord.Schedule.SchedName); Rect:=DayGrid.CellRect(Coord.Col,Coord.Row); Memo1.Lines.Add(Format('CellRect : Left = %d, Top = %d, Right = %d, Bottom = %d', [Rect.Left,Rect.Top,Rect.Right,Rect.Bottom])); Rect:=DayGrid.VirtualCellRect(Coord.Col, Coord.Row); Memo1.Lines.Add(Format('VirtualCellRect : Left = %d, Top = %d, Right = %d, Bottom = %d', [Rect.Left,Rect.Top,Rect.Right,Rect.Bottom])); end;
Теперь при запуске приложения в Memo1 будет выводится информация по размерам и положению клиентской области компонента TjvTFDays, а после клика по любой точке в сетке расписания — информация о ячейке.
Исходник приложения (Delphi XE), рассмотренный в посте можно сказать по приведенной ниже ссылке (приложение будет дополнятся по мере рассмотрения новых методов компонента):
[download id=»76″ format=»1″]
А как сохранить записанные события в базу данных (например ACCeSS)?
В принципе, как и в любых других случаях — подключаем необходимую БД и ручками пишем в неё событие, соответственно БД придётся писать тоже самому.
Если в ходе изучения работы компонентов обнаружится какая-то «штатная» функция типа «сохранить событие в БД Paradox», то обязательно отпишусь в блоге
Vlad, а не большой примерчик не подскажешь?
Я новичок в программировании, если с гридом ясно как подцепляться к БД, то TF DAys не очень. нет Data Sourse. Может где примерчик есть?
Пример вообще по работе с этими компонентами есть в поставке JVCL в папке Examples. Там как раз делается запись и чтение событий из БД Paradox. Пример в целом рассчитан на то, что не новичок точно разберется как и что делается и есть даже комментарии кое-какие к коду.
С Paradox понятно. а через ADO ACCESS?
аналогично и с Access. Открываете вкладку с компонентами ADO укладываете на фору ADOConnection, ADOQuery и т.д., создаете соединение и работаете. В чем проблема-то? JVCL тут даже и не при чём как бы — всё дело в компонентах для БД
И все таки, (Сон пропал), очень нужен маленький примерчик TFDays соеденить запрос -редактирование с ACCESS через ADO или Query?
Помогу на лицензию…