Конференция "Начинающим" » Как зарегистрировать TFormClass имея string "TForm2" [D7, WinXP]
 
  • ухты © (09.03.17 16:37) [20]

    > В проекте появилось 10 новых форм. Будем наращивать в IF
    > еще 10 этажей?
    >
    > Или используем [15] в сочетании с [12] - и все произойдет
    > автоматически.
    а сама регистрация пропишется конечно не руками, .. работы по большому счету столько же, знай себе копируй да правиь названия )
  • Юрий Зотов © (09.03.17 16:49) [21]
    Только для восстановления состояния одного создания форм мало. Как минимум, надо еще восстановить состояние всех компонентов. Это можно сделать так.

    1. При завершении программы пишем все формы в потоки (WriteComponent). Потоки можно хранить, например, в файлах (это будут аналоги DFM).

    2. При запуске программы создаем формы через CreateNew (а не Create) и заполняем их из ранее сохраненных потоков (ReadComponent).

    Конечно, владельцами компонентов на формах должны быть сами формы.

    Но еще надо придумать механизм сохранения и восстановления объектов и переменных, не являющихся членами классов. А также придумать механизм сохранения и восстановления объектов, не являющихся потомками TPersistent. И вот две эти задачки могут оказаться гораздо сложнее.
  • Юрий Зотов © (09.03.17 16:53) [22]
    > ухты ©   (09.03.17 16:37) [20]

    Что ж, если к небоскребам Вы относитесь спокойно, то дело Ваше.
  • веловня (09.03.17 20:11) [23]
    Я кусок старого кода переписываю. У меня и так там набралось несколько десятков
    if string='tform2' then tform2.create и т.д.
    Теперь я просто столкнулся с невозможностью зарегистрировать этот класс из строки в рантайме, и никак не могу отказаться от этой идеи.
    А без этого опять нужно помнить, что надо к новой форме добавить очередной if и т.д.
    Опять же по [12] и [15] надо будет не добавлять еще один RegisterClass() в родительскую форму;
    Некрасиво. Неужели нет решения?
  • ухты © (09.03.17 21:31) [24]
    Если бы была возможность регистрации из строки, то в самой такой регистрации особого смысла не было бы, сразу получаешь тип и вперед. Вам не хочется делать регистрацию потому что писать, ифы нет  потому что тоже писать, как же тогда быть..)
    Посмотрите на ртти, может прокатит.
  • Юрий Зотов © (09.03.17 22:20) [25]
    > веловня   (09.03.17 20:11) [23]

    > по [12] и [15] надо будет не добавлять еще один
    > RegisterClass() в родительскую форму


    В том-то и кайф, что в главную форму ничего добавлять или убавлять никогда не придется (кроме uses, конечно). Как сказано в [15], RegisterClass пишется в каждой TForm2 (в секции initialiization), а в главной форме ОДИН раз пишется что-то вроде этого:

    uses
     Unit2;

    procedure TForm1.FormCreate(Sender: TObject);
    var
     ClassNames: TStringList;
     i: integer;  
     C: TFormClass;
     F: TForm;
    begin
     ClassNames := TStringList.Create;
     try  
       // ... Здесь читаем настройки и заполняем ClassNames  
       for i := 0 to ClassNames.Count - 1 do
       begin
         C := TFormClass(GetClass(ClassNames[i]));
         if C = nil then
           continue;
         F := C.Create(Application);
         F.Show
       end
     finally
       ClassNames.Free
     end
    end;


    И этот код никогда не меняется (кроме uses). Добавили в проект новую форму - все автоматом работает (причем, если у новой формы нет регистрации,  то все работает, как обычно). Убрали из проекта форму - тоже все автоматом работает как надо.
  • Юрий Зотов © (09.03.17 22:40) [26]
    Кстати, насчет uses я погорячился - при таком коде uses просто не нужен и его надо убрать. То есть, код в главной форме вообще никогда не меняется - ни при добавлении форм в проект, ни при удалении форм из проекта.

    В отличие от суперIF'ов.
  • Германн © (10.03.17 02:09) [27]

    > Юрий Зотов ©   (09.03.17 05:16) [12]
    >
    > 1. Автор хочет, чтобы при старте приложения автоматически
    > восстанавливались все формы, которые были открыты при завершении
    > предыдущего сеанса. Нормальное желание, а никакое не извращение.
    >
    >
    > 2. Для этого он при закрытии сеанса сохраняет нужную информацию
    > в настройках программы (конечно, в строковом виде - а в
    > каком еще?). Тоже вполне нормальный способ, а никакое не
    > извращение.
    >

    Согласен. В таком варианте это не блажь.
  • sniknik © (10.03.17 08:41) [28]
    > В отличие от суперIF'ов.
    в отличие от них, у вас логика разнесена в 2 места, обработчик и зависимые от него регистрации в каждом модуле, которые "автоматом" дельфей делаться не будут. с точки зрения поддержки очень не хорошо, вот понадобится добавить формочку лет через пять, уже в забытом, почти умершем но кем то еще используемом проекте... - проблема на ровном месте. не говоря уже о том что добавлять можете не вы... хотя это будет уже не проблема, а показатель вашей незаменимости. да.

    если же переносить регистрацию к месту использования, то и там будет что то типа ифов, + а то и дополнение в виде проверки на разовость, чтобы не дублировать регистрации.
    если уж так то почему бы просто не поставить у форм (родителя) невидимость, и пусть все создается/генерится автоматом, и только днлать видимыми необходимые формы... ?

    > Согласен. В таком варианте это не блажь.
    блажь, блажь... у меня сделан тако вариант, и ничего подобного не требовалось, вообще к именам классов привязки нет, просто в общем родителе написал сохранение данных формы, а при старте, по имени форм (не по классу) если запись есть создаю форму - восстанавливаю параметры (это тоже в методе формы).
  • веловня (10.03.17 10:13) [29]
    Мне тоже кажется что если от IFов не избавиться, то лучше их в одной куче держать.
  • sniknik © (10.03.17 10:26) [30]
    напиши что то подобное такому, да пользуйся, проблем меньше ИМХО будет.
    добавлять легко, ничего в каждом модуле лишнего не нужно, как дельфя сгенерит так и пойдет
    procedure TFormMain.ShowForm(const ClassName: string);

     function FindClass(const ClassName: string): TPersistentClass;
     begin
       if ClassName = 'TForm1' then result:= TForm1 else
       if ClassName = 'TForm2' then result:= TForm2 else
       raise EClassNotFound.CreateFmt('Class %s not found', [ClassName]);
     end;

    begin
     with TFormClass(FindClass(ClassName)).Create(Application) do
       try
         ShowModal;
       finally
         Free;
       end;
    end;

  • ухты © (10.03.17 11:34) [31]
    не нравятся ифы (хотя что в них плохого), сделать словарик, потом по имени сразу получать то что требуется
    только и тут придется руками в него заносить, куда ни крути приходится что то писать
  • Eraser © (10.03.17 14:21) [32]

    > Юрий Зотов ©   (09.03.17 16:49) [21]


    > При завершении программы пишем все формы в потоки (WriteComponent)

    а потом новый билд, с каким-нибудь удаленным компонентом, который присутствовал ранее, будет радостно вылетать в трубу при запуске, с не до конца понятными последствиями для продолжения работы приложения.

    идея с WriteComponent красивая, в одном проекте я даже так настройки храню, но минусов больше, чем плюсов, жаль что я это сразу не понял.

    автору лучше найти готовый велосипед для сохранения настроек GUI, серьезный фреймворки вроде devexp предлагают такие велосипеды.

    что касается сабжа - у автора что там сотня форм в проекте, которые нужно восстанавливать при старте?
  • Eraser © (10.03.17 14:25) [33]

    > WriteComponent

    им бы сделать встроенную сериализацию (по желанию, любых объектов) на базе того же JSON - цены бы не было. но увы.
  • Игорь Шевченко © (10.03.17 15:50) [34]
    Eraser ©   (10.03.17 14:21) [32]


    > а потом новый билд, с каким-нибудь удаленным компонентом,
    >  который присутствовал ранее, будет радостно вылетать в
    > трубу при запуске, с не до конца понятными последствиями
    > для продолжения работы приложения.


    Обычно для этого в сохраненную конфигурацию прописывают ее версию и ничего не вылетает.
  • Eraser © (10.03.17 18:19) [35]

    > Игорь Шевченко ©   (10.03.17 15:50) [34]

    хорошо бы, чтобы новая версия понимала настройки от предыдущей версии.
  • Игорь Шевченко © (10.03.17 22:24) [36]
    Eraser ©   (10.03.17 18:19) [35]


    > хорошо бы, чтобы новая версия понимала настройки от предыдущей
    > версии.


    По-моему, мы уже далеко отходим от темы. Речь идет о сохранении "рабочего пространства", насколько я понимаю, поэтому для разных версий то самое пространство может быть совсем разным. Как например, десктоп у Delphi 7 и 2007.
  • Германн © (11.03.17 02:33) [37]

    > sniknik ©   (10.03.17 08:41) [28]
    >
    > > Согласен. В таком варианте это не блажь.
    > блажь, блажь... у меня сделан тако вариант, и ничего подобного
    > не требовалось, вообще к именам классов привязки нет, просто
    > в общем родителе написал сохранение данных формы, а при
    > старте, по имени форм (не по классу) если запись есть создаю
    > форму - восстанавливаю параметры (это тоже в методе формы).

    Как сформулировал Юра более общую задачу - это не блажь. Как ты решил свою задачу - это другое.
    Но автор вопроса до сих пор не обнародовал свою задачу. Если не считать
  • Германн © (11.03.17 02:34) [38]

    > веловня   (09.03.17 20:11) [23]
    >
    > Я кусок старого кода переписываю.

    веловня   (09.03.17 20:11) [23]

    Я кусок старого кода переписываю.
  • Eraser © (12.03.17 07:02) [39]

    > Игорь Шевченко ©   (10.03.17 22:24) [36]

    да нет, как раз, это по теме. чтобы метод сохранения настроек через Read/WriteComponent дал сбой, достаточно удалить хотя бы одно published свойство. в версии 5.4445.123 оно может присутствовать, а в версии 5.4445.124 какую-нибудь кнопку нужно будет убрать и старые настройки станут бесполезны. если выпускать релизы раз в 2 года может быть ничего страшного и нет, но, зачастую, релизы раз в месяц бывают.
 
Конференция "Начинающим" » Как зарегистрировать TFormClass имея string "TForm2" [D7, WinXP]
Есть новые Нет новых   [118451   +42][b:0.001][p:0.001]