Инициализация компонентов на Динамически создаваемой

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Инициализация компонентов на Динамически создаваемой

Сообщение Герасим » 11.01.2008 19:26:31

Привет! Это опять я :-) Delphi->Lazarus
Есть форма, мне их нужно создавать по необходимости:
по нажатию кнопки в главном окне выполняю:
Form:=TLinkWindowFm.Create(Application);//создал форму
WindowList.Add(Form);//добавил её в список для послед. руления
Form.OpenFile(FileName); //заставил её что-то нужное мне делать

У формы есть событие OnCreate = FormCreate, которое происходит В ДЕЛЬФЯХ при при вызове Form:=TLinkWindowFm.Create(Application); так вот в Лазаре оно не вызывается (вызывается только у статических форм)

Ладно, переписал Create (constructor Create...override) и принудительно вызываю процедуру FormCreate, в ней (по мимо прочего) есть установка некоторых свойств принадлежащих форме компонентов, так вот, дебагер показывает что их нет, то есть на момент вызова Create (inherited уже отработал) компоненты не созданы!!! и обращение к их полям валит прогу. Но в Дельфи то всё ок!

Что делать?!

ЗЫ а ведь потом встанет вопрос из дестроя
Герасим
новенький
 
Сообщения: 14
Зарегистрирован: 28.12.2007 13:29:18

Сообщение shade » 11.01.2008 20:21:46

Герасим писал(а):У формы есть событие OnCreate = FormCreate, которое происходит В ДЕЛЬФЯХ при при вызове Form:=TLinkWindowFm.Create(Application); так вот в Лазаре оно не вызывается (вызывается только у статических форм)

OnCreate вызывается...
Правильный метод создания формы:

Код: Выделить всё
function create_my_form: TMyForm;
begin
  Application.CreateForm(TMyForm, Result);
end;


Вот реальный пример (обрати внимание на OnClose - наверняка тебе ещё захочется удалить форму при закрытии):
Код: Выделить всё
unit uviewer;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TFViewer }

  TFViewer = class(TForm)
    Memo1: TMemo;
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
  private
    { private declarations }
  public
    { public declarations }
    class procedure Execute(const ACaption: string; Stream: TStream);
  end;

var
  FViewer: TFViewer;

implementation

procedure TFViewer.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
  CloseAction := caFree;
end;

class procedure TFViewer.Execute(const ACaption: string; Stream: TStream);
var form: TFViewer;
begin
  Application.CreateForm(Self, form);
  form.Memo1.Lines.LoadFromStream(Stream);
  form.Caption := ACaption;
  form.Show;
end;

initialization
  {$I uviewer.lrs}

end.
Аватара пользователя
shade
энтузиаст
 
Сообщения: 879
Зарегистрирован: 21.02.2006 20:15:48
Откуда: http://shamangrad.net/

Re: Инициализация компонентов на Динамически создаваем

Сообщение Сергей Смирнов » 11.01.2008 21:42:28

Герасим писал(а):У формы есть событие OnCreate = FormCreate, которое происходит В ДЕЛЬФЯХ при при вызове Form:=TLinkWindowFm.Create(Application); так вот в Лазаре оно не вызывается (вызывается только у статических форм)
Вообще-то, Ваш способ вроде правильный. Всё должно работать. Проект конвертили инструментом "Преобразовать проект дельфи в проект лазарус" или создавали с нуля? Форма эта автоматом, надеюсь, не создаётся? То, что предлагает shade... со статическим методом... ИМХО, изврат это изрядный. В принципе, то, что описано тут вполне работает, хоть и местами информация устарела - имя новой формы теперь генерится в LCL само.
Аватара пользователя
Сергей Смирнов
энтузиаст
 
Сообщения: 595
Зарегистрирован: 28.04.2005 13:23:25
Откуда: Москва

Сообщение alexs » 11.01.2008 21:50:13

shade писал(а): Application.CreateForm(TMyForm, Result)

Кстати, а почему?
Я понимаю - для создания главной формы. А вот рабочие формы - по моему отнюдь не обязательно. Да, там есть доп. функции на обработку Форм-заставок (splash) - но это лучше делать руками.

Кстати, кто знает, какой сокральный смысл ведения списка форм FFormList в объекте TApplication? я нашёл только средства автоматизации сокрытия/убивания тех же сплешей. Но это можно было сделать и через обект TScreen - там тоже ведётся список форм. А вот зачем он дублирется в TApplication - я не понял.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Сообщение shade » 12.01.2008 13:01:21

alexs писал(а):Кстати, а почему?

Ну хотя бы потому, что так делает Lazarus/Dephi
Этот вариант работает как в Delphi так и в Lazarus и никогда мне хлопот не доставлял, если не считать не совсем очевидного вызова Application.CreateForm
Аватара пользователя
shade
энтузиаст
 
Сообщения: 879
Зарегистрирован: 21.02.2006 20:15:48
Откуда: http://shamangrad.net/

Сообщение alexs » 12.01.2008 13:50:47

Я просто по исходникам смотрел - смысла в таком ситело создания нет. А создание напрямую через конструктор - это ещё у борланда в примерах было. Пожэтому так и создаю. У меня часто бывает, что приходится переопределять конструктор создания формы - передаватьс сылки на другие формы/объекты - через Application.CreateForm это уже не сделаеш.

Хотя в стандартной ситуации, конечно, можно и так, и так.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Сообщение Sergei I. Gorelkin » 12.01.2008 15:17:11

В Дельфи Application.CreateForm служит для того, чтобы переменная Form1 была доступна во время работы конструктора. Т.е. вначале вызывается NewInstance, результат присваивается Form1, и только потом вызывается конструктор. Какой-то смысл в этом есть... например, свойство Application.MainForm присваивается только после отработки конструктора, что приводит к невозможности создать MDI child форму из FormCreate основной формы.
С другой стороны, эта возможность провоцирует к использованию в собственном коде глобальных переменных типа Form1 - чего лично я бы посоветовал всеми силами избегать.
Ну а если глобальные переменные не использовать, то разницы в способах создания формы нет.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение alexs » 12.01.2008 20:52:43

Sergei I. Gorelkin
Абсолютно согласен.

На мой взгляд - надо как можно меньше использовать глобальных переменных. Уж очень с ними легко совершать ошибки.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 67

Рейтинг@Mail.ru