Fast Report: Preview меняет родителей

© 2003 Сергей Секела

В ранних версиях Delphi не было такого понятия как frames (кадры), но программисты могли использовать для этого стандартные формы. Вы спросите как это? А очень просто: для этого просто нужно после создания формы поменять ей родителя и все ;).

Тоесть, если у меня есть Form1 и Form2, и я хочу чтобы содержимое Form2 было на панели с именем Panel2 формы Form1 то я забираю из файла проэкта (допустим это project.dpr) строчки:

Application.CreateForm(TForm2, Form2);

И вставляю их в главной форме в событие OnShow или по нажатию какой либо кнопки вот так:


// лишнее вырезано :-)
Begin
 Application.CreateForm(TForm2, Form2);
 form2.Parent:=panel2;
 form2.Align:=alclient;
 form2.borderstyle:=bsnone;
 form2.Show;
End;

Таким образом на главной форме в панели Panel2 появится содержимое формы Form2 и мы с Вами сделали форму типа Кадра. Align’oм мы сделали так, чтобы форма заняла всю область панели; Свойство Borderstyle установили в BsNone потому что если б мы этого не сделали то, в форме был бы и заголовок окна Form2 ;) это смотрелось бы примерно вот так:

Тоесть форма2 в панели, но у нее есть заголовок, а он нам вообще сейчас не нужен ;).

А что если в рантайме поменять свойство Parent формы2 в nil? А будет то, в чем суть всей идеи - это окно перестанет быть "заложником" панели2 и будет вести себя стандартное окно :-).

Сказали – Сделали: Ставим на форму2 панель с Allign=AlTop, на нее кнопарь, в событии OnClick которого напишем:

form2.Align:=alnone;
form2.BorderStyle:=bssizetoolwin;
form2.Parent:=nil;
form2.windowstate:=wsMaximized;

Поставили свойство BorderStyle в bssizetoolwin, чтобы окно было на окно похоже :-). Но если юзер сейчас нажмет на кнопку Close, то формочка то наша утютю... :-( Не дадим ей это сделать:

Ставим в событие OnCloseQuery второй формы:


procedure TForm2.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  if parent=nil then
  begin
    form2.Parent:=form1.panel2;
    form2.Align:=alclient;
    form2.borderstyle:=bsnone;
    canclose:=false;
  end
  else canclose:=true;
end;

Тесть форма закроется только в том случае если у нее есть Parent, а если такового не имеется, так мы его прикрутим назад и окошко наше опять влезет в панель :-).

А теперь сама идея:

Значит есть у нас разные там накладные, счета, короче любые документы, которые мы выписываем не все вместе, а только тогда когда нам это нужно, то есть пришел Вася, сказал: "Дай мне счет на то и это" - Мы бац бац, данные в таблицу внесли, а потом запустили отчетник и все. А теперь мы хотим пройтись по Васям, Петям, Толям и Нинам и посмотреть какие документы мы им выписали (только без всяких там реестров счетов и так далее… просто нужно и все тут ) Значит смотрим мы на Васю, смотрим на таблички— не красиво :-(

А что если б мы ставали на Васю и сразу б видели его документ? Эту идею разработчики ФастРепорта предусмотрели и сделали для нас frPreview а так же возможность получить в репортере данные из Dataset, который находится на форме (того или иного движка, тоесть если Вы используете БДЕ или FibPlus, то должны включить соответствующий компонент) и вроде жизнь-малина. Но, допустим у нас есть Две таблицы, в Первой допустим есть типы клиентов, то есть Брат, друг, знакомый, и т.д. а во второй те же Васи Коли Пети (с признаком типа, то есть друг он или нет). Все это должно быть на одной форме, с превьювом,… но тогда на нем (превьюве) мало что будет видно. Вот тут то и пригодится вариант когда frPreview будет совсем в другой форме (также на форме будет вышеописаный "кнопарь", так же CheckBox, который будет говорить нам показывать ли превью или нет а так же по желанию стандартные кнопки управления превьювом), а вызывать мы его будем так как я показывал выше, то есть будет впечатление, что frpreview тут - на формочке, но когда нужно ближе присмотреться к документу, то preview выскочит в отдельное окошко. Для этого в событие OnAfterScroll нашей таблички, по которой будет строится документ – мы поставим следующее:


procedure TForm1.Table2AfterScroll(DataSet: TDataSet);
begin
 if assigned(form2) Then  //проверяем есть ли вообще форма
   Begin 
     if form2.CheckBox1.checked then //Мы можем не всегда показывать превью,
                                     //только тогда когда этого захочет пользер
      begin
         form2.frreport1.LoadFromFile('a1.frf');
         form2.frreport1.PrepareReport;
         form2.frreport1.ShowPreparedReport;
      end
      else 
      if form2.frreport1.Pages.count<>0 then
        begin
         form2.frreport1.Clear;
         form2.frReport1.Preview.Clear;
        end;
   end;
end;

Итого у нас получиться что-то вроде этого:

Между табличками можно еще поставить несколько сплитеров, чтобы можно было все это дело передвигать и менять размерчики. Так же в событии формы 2 я поставил такие строчку:

frpreview1.PageWidth;

Это чтобы когда формочка меняет размер, чтобы менялся масштаб отображения документа. А вот он- "кнопарик":

А это результат нажимания на "кнопарике":

P.S. Пример кода прилагается, но учтите, что в нем использованы таблицы из стандартного БДЕшного примера DBDemos.

Copyright© 2003 Сергей Секела  Специально для Delphi Plus