Как заставить работать компонент
Здравствуйте.
Пытаюсь сделать графический компонент для FastReport'a, но возникли проблемы.
Компонент является наследником TfrxView. Отдельно работает нормально - на обычный Canvas он выводит графику нормально, а при переносе на FastReport отказался работать. Для проверки я сделал простенький пример компонента, который выводит текст в FastReporte, но он тоже не работает. Видимо, я что-то делаю не так. Пожалуйста, помогите разобраться с проблемой.
Пример тестового компонента прилагается.
P.S.: Предполагается что тестовый компонент привязывается к полю датасета и выводит его содержимое в FastReporte. Этот компонент сделан на основе документации для FastReport'a - "Руководство разработчика". Под отладчиком видно, что сначала вызывается метод GetData, а затем Draw, но почему-то в при вызове обеих методов переменная Self имеет разные значения, точнее: при вызове метода GetData Self имеет одно и то же значение, в то время, как при вызове Draw - всё время разные.
Используется версия FastReport 3.21.
Пытаюсь сделать графический компонент для FastReport'a, но возникли проблемы.
Компонент является наследником TfrxView. Отдельно работает нормально - на обычный Canvas он выводит графику нормально, а при переносе на FastReport отказался работать. Для проверки я сделал простенький пример компонента, который выводит текст в FastReporte, но он тоже не работает. Видимо, я что-то делаю не так. Пожалуйста, помогите разобраться с проблемой.
Пример тестового компонента прилагается.
P.S.: Предполагается что тестовый компонент привязывается к полю датасета и выводит его содержимое в FastReporte. Этот компонент сделан на основе документации для FastReport'a - "Руководство разработчика". Под отладчиком видно, что сначала вызывается метод GetData, а затем Draw, но почему-то в при вызове обеих методов переменная Self имеет разные значения, точнее: при вызове метода GetData Self имеет одно и то же значение, в то время, как при вызове Draw - всё время разные.
Используется версия FastReport 3.21.
Комментарии
Т.е. в XML построенного отчета, записываются только published св-ва или св-ва добавленные через DefineProperties.
В Вашем случае в построенный отчет попадают св-ва DataSet и DataField, но GetData вызывается только в момент построения отчета.
Получается что строка полученная в момент построения отчета в методе GetData нигде не сохраняется.
Выходов несколько:
1. Объявить св-во Text как Published, а если его нужно скрыть св-во в инспекторе объектов дизайнера используйте функцию frxHideProperties(модуль frxDsgnIntf).
2. Использовать виртуальный метод DefineProperties для добавления св-в.
А вот такая ситуация. Если компонент наследуется от TfrxStretcheable у него есть метод: function CalcHeight: Extended.
Он вызывается до метода Draw или DrawPart.
Но в этом методе я не могу обращаться к FX, FY, FX1, FY1, FDX, FDY, FFrameWidth, FScaleX, FScaleY, FCanvas, потому что функцию BeginDraw я из CalcHeight вызвать не могу. Т.е. я не знаю масштабы, координаты и т.п. Следовательно, не могу расчитать и высоту.
Как быть?
И вообще какая-то странная ситуация с CalcHeight, DrawPart и InitPart. Из документации не понятно, для TfrxStretcheable они должны использоваться совместно с Draw или нет. Если нет, то почему им не передаются те же параметры что и Draw.
Для примера добавляете поле FRect, переопределяете BeginDraw в своем классе( в ней естественно сначала вызываете этот же метод из родительского класса), там же можно сделать нужные вычисления(смешения, добавление к высоте ширины рамки итд).
После чего все сохраняете в FRect.
Тогда метод CalcHeight будет выглядеть приблизительно так:
function TfrxMYView.CalcHeight: Extended;
begin
Создание канваса в памяти.
BeginDraw(nil, 1, 1, 0, 0);
установка границ отрисовки - FRect.
вычисление высоты текста
end;
Эти методы используются только в момент построения отчета(поэтому масштаб нужно указывать единицу), при печати и предпросмотре FR отрисовывает объекты по уже имеющимся координатам(которые в момент построения могли быть вычислены через CalcHeight).
Проще говоря эти методы не предназначены для использования их при непосредственной отрисовке в методе Draw.
InitPart используется при инициализации разрываемого объекта.
DrawPart - делает само разбиение на основе заданной высоты и возвращает величину не использованного пространства.
На примере мемки: у объекта есть поле для хранения части текста(TempText), в InitPart этому полю нужно присвоить весь текст объекта(TempText = Text), а в DrawPart берется часть текста попадающая в границ и присваивается полю Text (поле которое хранит текст для отрисовки). Остаток не попадающий в границы присваивается полю TempText(и так до полной отрисовки текста).
Теперь как ведет себя движок FR (чтобы вышеописанное стало понятно):
- Вычисляется высота объекта, вот тут -то и используется CaclHeight.
- Если объект помещается в свободное пространство, то печатается весь объект.
- Если объект не помещается в свободное пространство :
- объекту устанавливается высота = свободному пространству на странице
- вызывается метод DrawPart, вычисляется сколько строк текста может поместится в заданную высоту.
- DrawPart возвращает величину не использованного пространства.
- Проверяется может ли объект быть разорван, если нет - рисует как есть.
- Если объект разрывается, то рисуется его часть и для следующей части повторяется тоже самое.
Для наглядности могу посоветовать заглянуть в код frxClass -> TfrxCustomMemoView.