В данной статье описывается, как заменить стандартный контейнер предварительного просмотра отчетов вашим собственным компонентом, который может обеспечить функциональными возможностями просмотра отчетов всему вашему приложению, если у вас установлен SET REPORTBEHAVIOR 90.
Предварительно ознакомьтесь со статьями
Наилегчайший Просмотр
Самый легкий из возможных примеров вообще не использует API Контейнер Просмотра (Preview Container API), но использует методы объекта ReportListener для демонстрации внутреннего механизма API.
Нижеприведенный код определяет объект Shape как место вывода отчета, запускает отчет под управлением другого объекта, в данном случае это - Приемник Отчетов (ReportListener), и использует методы ReportListener для того, чтобы показать первую страницу отчета в заранее определенном месте вывода:
![]() | |
---|---|
* Определение места визуализации отчета: _SCREEN.AddObject("canvas","Shape") _SCREEN.canvas.Width = 250 _SCREEN.canvas.Height = 300 * Создать объект базового Приемника Отчета (ReportListener) и задать буферизацию всего отчета: rl = NEWOBJECT("ReportListener") * устанавливаем: * "буферизация всех страниц", * "не запускать предварительный просмотр автоматически" * с помощью задания значения свойству ListenerType rl.ListenerType = 3 * Обработка отчета: REPORT FORM (_SAMPLES+"\solution\reports\colors.frx") OBJECT rl * Показать 1-ую страницу в месте просмотра: rl.OutputPage( 1, _SCREEN.canvas, 2 ) |
После выполнения этого кода в Командном Окне, вы увидите уменьшенное изображение отчета на экране Visual Foxpro.
Обратите внимание:
- Третий параметр метода OutputPage() объекта ReportListener, равен 2, что означает, дескриптор места вывода, передаваемый вторым параметром, является ссылкой на Visual FoxPro объект, в данном случае - объект управления Shape.
- Объект Shape не обязательно должен был быть видимым, чтобы показать отчет.
- Объектами, используемыми в качестве места вывода могут быть либо Container, либо Shape
- Протаскивание командного окна мышкой над изображением отчета стирает это изображение с экрана, т.к. когда экран выполняет метод Paint(), он перерисовывает себя ничего не зная о визуализированном отчете.
Реализация Простого Контейнера Пред.Просмотра
Следующий шаг - заключить выше описанный процесс в класс, который реализует API контейнер пред.просмотра, позволяющий вам повторно использовать логику пред.просмотра
Следующий пример программы, simplepreview.prg, содержит определение класса, который также использует объект Shape в качестве места формирования изображения, только на этот раз на форме и использует API контейнер пред.просмотра:
![]() | |
---|---|
*----------------------------------------- * simplepreview.prg *----------------------------------------- DEFINE CLASS SimplePreview AS Form Caption = "Щелкните для перехода на след. страницу" ListenerRef = .NULL. PageNo = 1 AllowOutput = .F. ADD OBJECT Canvas AS Shape WITH ; Top = 12, Left = 8, ; Height = 252, Width = 209, ; Name = "Canvas" PROCEDURE Canvas.Click WITH THISFORM IF .PageNo < .ListenerRef.OutputPageCount .PageNo = .PageNo + 1 .Refresh() ENDIF ENDWITH ENDPROC PROCEDURE SetReport LPARAMETER oListenerRef THIS.ListenerRef = oListenerRef ENDPROC PROCEDURE QueryUnload IF NOT ISNULL( THIS.ListenerRef ) THIS.ListenerRef.OnPreviewClose(.F.) THIS.ListenerRef = .NULL. ENDIF THIS.Hide() NODEFAULT ENDPROC PROCEDURE Paint IF NOT ISNULL( THIS.ListenerRef ) THIS.ListenerRef.OutputPage( THIS.PageNo, THIS.Canvas, 2 ) ENDIF ENDPROC ENDDEFINE |
Данный класс обеспечивает выполнение двух методов API контейнеров пред.просмотра: путем явного определения метода SetReport(); и использование метода Show(), уже имеющегося в форме, поскольку она является производной от базового класса Form, который содержит необходимый метод .
Обратите внимание:
- Данный класс решает проблему перерисовки из предыдущего примера, с помощью добавления кода на событие формы Paint(), чтобы обеспечить перерисовку имиджа отчета, когда потребуется.
- Объект Reportlistener вызовет метод SetReport(), передав ссылку на самого себя, когда ему потребуется, чтобы контейнер пред.просмотра осуществил основную, не связанную с каким-либо отчетом, инициализацию. SetReport() будет также вызван с пустым параметром (
.NULL.
), когда вызовется его метод OnPreviewClose().
- Код в событии QueryUnload() сообщает приемнику отчета (report listener), что вы завершили просмотр отчета и обнулит ссылку на Приемник Отчета, дабы избежать зависания, которое не позволит закрыться форме.
- Код в методе Shape.Click() использует свойство OutputPageCount Приемника Отчета (report listener), чтобы застраховаться от попытки просмотра несуществующей страницы отчета.
Следующий код демонстрирует, как повторно использовать класс контейнера просмотра отчетов, определив класс SimplePreview и присвоив его свойству PreviewContainer объекта ReportListener. Запустите этот код в командном окне:
![]() | |
---|---|
pc = NEWOBJECT("SimplePreview", "simplepreview.prg") rl = NEWOBJECT("ReportListener") rl.ListenerType = 1 && Буферизация всех страниц, использовать контейнер просмотра rl.PreviewContainer = pc REPORT FORM (_SAMPLES+"\solution\reports\colors.frx") OBJECT rl REPORT FORM (HOME()+"Tools\Filespec\60frx2.frx") OBJECT rl |
После запуска данного кода, вы увидите, что форма SimplePreview появилась автоматически . Это произошло потому, что объект приемника отчета запустил метод PreviewContainer.Show() после того, как отчет завершил обработку.
Если вы в последнюю строку вышеприведенного примера включите оператор NOWAIT
, вы увидите, что форма просмотра больше не является модальной . Объект приемника отчета распознает оператор NOWAIT
и вызывает Show(0) вместо Show(1).
Hide() или Release()?
- В выше приведенной программе SimplePreview.prg, событие QueryUnload() подавляет свое стандартное выполнение командой NODEFAULT и принудительно прячет форму, вызывая метод Hide().
Для этого есть две причины:
- Все еще открытая ссылка на форму хранится в свойстве PreviewContainer приемника отчета, а это означает, что без дополнительного кода форма не закроется, когда вы нажмете на кнопку Close. Эта кнопка будет недоступной и форма останется видимой.
- Метод Hide() позволяет контейнеру просмотра быть повторно использованным при очередных просмотрах отчета, как это показывает предыдущий пример кода.
Если вы не хотите, чтобы ваш контейнер оставался доступным для будущих просмотров отчета, вы можете изменит код метода QueryUnload как показано ниже:
![]() | |
---|---|
PROCEDURE QueryUnload IF NOT ISNULL( THIS.ListenerRef ) THIS.ListenerRef.PreviewContainer = .NULL. THIS.ListenerRef.OnPreviewClose(.F.) THIS.ListenerRef = .NULL. ENDIF ENDPROC |
Как следствие данного альтернативного выполнения, контейнер выгружается из памяти после одного просмотра. Запустите повторно предыдущий код в командном окне с модифицированным классом контейнера просмотра, и вы увидите, что только первый просмотр использует форму SimplePreview. Второй запуск отчета возвращается к стандартному окну просмотра отчета, потому что объект ReportListener определил, что у него больше нет ссылки в его свойстве PreviewContainer и запрашивает новую через _REPORTPREVIEW.
Масштабирование и Печать
Масштабирование
В предыдущем примере, размеры изображения страницы определялись исключительно размерами объекта Shape. Если вы измените свойство Width объекта Shape и сделаете его в два раза меньше, то тогда вы заметите, что просматриваемый имидж также деформировался.
Вы можете получить дополнительную информацию о раскладке отчета из ссылки на ReportListener для того, чтобы отмасштабировать изображение страницы должным образом. Добавьте следующий код метода в определении класса, приведенного выше:
![]() | |
---|---|
PROCEDURE Show LPARAMETER iMode IF NOT ISNULL( THIS.ListenerRef ) LOCAL nWidthInches, nHeightInches nWidthInches = THIS.ListenerRef.GetPageWidth()/960 nHeightInches = THIS.ListenerRef.GetPageHeight()/960 * Допустим: Определяем масштаб как 50% на экране с 96 DPI : THIS.Canvas.Height = INT( nHeightInches * 96 * 0.5 ) THIS.Canvas.Width = INT( nWidthInches * 96 * 0.5 ) ENDIF DODEFAULT( iMode ) ENDPROC |
Это самое подходящее место для данного кода, потому что ReportListener гарантированно запустит метод контейнера просмотра Show(), в тот момент, когда методы GetPageHeight() и GetPageWidth() вернут корректные значения для заданного отчета, т.к. метод SetReport() будет вызван раньше.
Печать
Вы можете указать, что отчет должен быть распечатан, с помощью вызова метода приемника отчета OnPreviewClose() с параметром .Т. в момент закрытия формы.
Устанавливаем по Умолчанию
Вы можете подменить стандартный контейнер просмотра на просмотр под управлением объекта. Для этого, добавьте несколько строк в начале программы описания класса SimplePreview:
![]() | |
---|---|
*----------------------------------------- * simplepreview.prg *----------------------------------------- LPARAMETER loPreviewContainerRef * передача параметра по ссылке (т.е. косвенно) loPreviewContainerRef = CREATEOBJECT("SimplePreview") RETURN DEFINE CLASS SimplePreview AS Form : |
Теперь эта программа пригодна для определения _REPORTPREVIEW, и определяет контейнер просмотра, когда бы он ни запрашивался объектом ReportListener выполняя команду REPORT… PREVIEW в режиме под управлением объекта (т.е. с оператором OBJECT).
Вы можете испытать это в командном окне:
![]() | |
---|---|
_REPORTPREVIEW = "simplepreview.prg" SET REPORTBEHAVIOR 90 report form (HOME()+"Tools\Filespec\60frx2.frx") preview |
Едем Дальше ...
Смотри Также
Ссылки
Объект ReportListenerСистемная Переменная _REPORTOUTPUT
Системная Переменная _REPORTPREVIEW
Метод OutputPage()
Объект Container
Объект Управления Shape