Работа с отчетами Rave Report в режиме RunTime

Пример вызова процедуры GetListParentClassName:GetListParentClassName(MemoInfo.Lines, RvProjectRTR.ClassType);илиGetListParentClassName(MemoInfo.Lines, TRvProject); Как было сказано выше, для доступа к проекту отчета необходим класс TRaveProjectManager. Чтобы получить к нему доступ, необходимо обратиться к свойству «ProjMan» класса TRvProject. Как известно в проекте отчета Rave Report может содержаться несколько отчетов. Работа с отчетом осуществляется через класс TRaveReport. Для доступа к текущему активному отчету нужно обратиться к свойству «ActiveReport» класса TRaveProjectManager. Вот для свойства «ActiveReport» класса TRaveProjectManager и следует применить выше описанную процедуру GetListObjects для получения списка объектов из отчета. Для использования процедуры можно использовать, к примеру, такие строки кода: ... ListObjects.Clear; GetListObjects(ListObjects.Items, RvProjectRTR.ProjMan.ActiveReport, '', True); ... Посмотрите на результат работы процедуры GetListObjects. Вы наверняка сразу заметили одну особенность, что все имена классов представленных объектов начинаются с приставки «TRave…». Ну вот, зная имена классов, работать будет уже намного легче. Совет: Если известен некий класс, но неизвестно в каком модуле данный класс описан, то это можно выяснить с помощью поисковика файлов с поддержкой поиска текста внутри файлов. В поисковике задать маску для поиска «*.dcu» в папке «\Rave5\Lib», а в строке для поиска текста указать наименование класса, например: TRaveControl. Исследование объектов средствами технологии RTTI Получив список объектов, не мешало бы поподробнее получить информацию об интересующем объекте. В этом, безусловно, поможет технология RTTI. Если вы имеете опыт работы с RTTI, то можете пропустить данный раздел статьи. Примечание: В данной статье не будет достаточно подробно рассматриваться принцип работы с RTTI так как эта тема довольно-таки велика по объему. Будет рассмотрено только то, что поможет в дальнейшей работе. Более подробно с принципами работы технологии RTTI вы можете познакомиться в книге Стива Тейксейра и Ксавье Пачеко «DELPHI 5 Руководство разработчика. Том 2. Разработка компонентов и работа с базами данных». Процедуры, реализованные в этой статье, основаны на примерах из этой книги, и были несколько доработаны для работы с проектом, описываемым в данной статье. Для работы с RTTI в раздел проекта uses необходимо подключить модуль TypInfo. Для извлечения информации RTTI обычно требуется две структуры: PTypeInfo и PTypeData. Ниже приведена процедура, которая выводит базовую информацию об интересующем объекте.

// Извлечение базовой информации об объекте
procedure GetListClassInfo(ListInfo: TStrings; ClassX: TObject; ClearList:
 Boolean = True);
var
 // В данные структуры записывается информация об RTTI объекта
 Class_PTI: PTypeInfo;
 Class_PTD: PTypeData;
begin
 if (ClassX = nil) or (ListInfo = nil) then
  EXIT;
 if ClearList then
  ListInfo.Clear;
 // Получение информации об RTTI объекта
 Class_PTI := ClassX.ClassInfo;
 Class_PTD := GetTypeData(Class_PTI);
 // Вывод базовой информации об объекте
 with ListInfo do
 begin
  Add('Базовая информация:');
  Add(Format('Имя класса: '#9' %s',[Class_PTI.Name]));
  Add(Format('Тип класса: '#9' %s',
  [GetEnumName(TypeInfo(TTypeKind),
  Integer(Class_PTI.Kind))]));
  Add(Format('Размер объекта: '#9' %d',[ClassX.InstanceSize]));
  Add(Format('Описан в модуле: '#9' %s',[Class_PTD.UnitName]));
  Add(Format('Всего доступно свойств: %d', [Class_PTD.PropCount]));
  if ClassX is TRaveControl then
  begin
  Add('Родительский компонент:');
  Add(Format('Тип класса: %s',
  [TRaveControl(ClassX).Parent.ClassName]));
  Add(Format('Имя компонента: %s', [TRaveControl(ClassX).Parent.Name]));
  end;
  Add('Генеалогическое дерево класса:');
  // Вывод информации о предках объекта
  GetListParentClassName(ListInfo, ClassX.ClassType, False);
 end;
end;

Примечание: Следует помнить, что в RTTI доступны только те свойства и методы, которые определены в секции published исследуемого объекта, т.е. те которые видны в инспекторе объ-ектов среды разработки Delphi. Свойства и методы необъявленные в секции published через технологию RTTI будут недоступны.
Следующая процедура выводит список наименований свойств, свойств-событий (методы) и тип свойств исследуемого объекта. Также данная процедура выводит текущие значения, присвоенные свойствам объекта. Для свойств типа tkClass (в этих свойствах храниться ссылка на некий объект) выводиться имя объекта, на который ссылается данное свойство. Если же это свойство не ссылается на объект, то будет выведено значение «NIL».

// Извлечение информации о наименовании свойств и событий объекта

procedure GetListProperty(ListPropertys: TStrings; ClassX: TObject; AddObjects:

 Boolean = False; ClearList: Boolean = True);

var

 PropList: PPropList;

 Class_PTI: PTypeInfo;

 Class_PTD: PTypeData;

 I, PropertyCount: Integer;

 S, StrVal: string;

 TmpObj: TObject;

begin

 if (ClassX = nil) or (ListPropertys = nil) then

  EXIT;

 if ClearList then

  ListPropertys.Clear;

 Class_PTI := ClassX.ClassInfo;

 Class_PTD := GetTypeData(Class_PTI);

 if Class_PTD.PropCount <> 0 then

 begin

  // Выделение памяти под структуры TPropInfo, в зависимости от количества свойств объекта

  GetMem(PropList, SizeOf(PPropInfo) * Class_PTD.PropCount);

  try

  // Заполнение PropList указателями на структуры TPropInfo

  GetPropInfos(ClassX.ClassInfo, PropList);

  for I := 0 to Class_PTD.PropCount - 1 do

  // Добавляются свойства не являющиеся событиями

  if not (PropList[I]^.PropType^.Kind = tkMethod) then

  begin

  // Извлечение текущего значения свойства

  if PropList[I]^.PropType^.Kind = tkClass then

  begin

  TmpObj := GetObjectProp(ClassX, PropList[I]^.Name);

  if TmpObj = nil then

  StrVal := 'NIL'

  else

  // Если у объекта есть предок TComponent,

  // то извлекается имя объекта иначе имя класса

  if TmpObj is TComponent then

  StrVal := TComponent(TmpObj).Name

  else

  StrVal := '(' + TmpObj.ClassName + ')';

  end

  else

  StrVal := GetPropValue(ClassX, PropList[I]^.Name);

  S := Format('%s: %s = %s', [PropList[I]^.Name,

  PropList[I]^.PropType^.Name, StrVal]);

  if AddObjects then

  ListPropertys.AddObject(S, TObject(PropList[I]^.PropType^))

  else

  ListPropertys.Add(S);

  end;

  // Поиск свойств-событий

  PropertyCount := GetPropList(ClassX.ClassInfo, [tkMethod], PropList);

  ListPropertys.Add('*** Свойства-события ***');

  // Добавляются свойства-события

  for i := 0 to PropertyCount - 1 do

  begin

  S := Format('%s: %s', [PropList[I]^.Name, PropList[I]^.PropType^.Name]);

  if AddObjects then

  ListPropertys.AddObject(S, TObject(PropList[I]^.PropType^))

  else

  ListPropertys.Add(S);

  end;

  finally

  // Освобождение ранее выделенной памяти

  FreeMem(PropList, SizeOf(PPropInfo) * Class_PTD.PropCount);

  end;

 end;

end;

Отправить комментарий

Проверка
Антиспам проверка
Image CAPTCHA
...