Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 21.12.2009, 08:49   #1
Greek9000
Форумчанин
 
Регистрация: 01.09.2009
Сообщений: 151
Сообщение Перенос формы из dll-ки в программу

Здравствуйте.

Есть задача: разработать и реализовать программу, таким образом, что бы была возможность её расширения и модернизации без перекомпилирования основного каркаса. Так же должна присутствовать возможность постоянного (возможно автоматического) обновления данного приложения. Это то, чего хочется добиться в итоге.

Решение: Создаём единственную форму с базовым компонентом, поддерживающим вкладки (напр. TPageControl и TTabSheet-ы). На вкладки загружаем формы из dll-библиотек по имени класса требуемой формы (напр. main.dll содержит классы форм TfrmDataView, TfrmDataManagment, TfrmUsers, TfrmClients и т.д.). Далее грузим из указанной dll-ки нужные классы на отдельные вкладки. Получается программа, которая выглядит как любой современный браузер, только вместо веб-страниц на вкладках отображены формы.

Проблема: проблема состоит в том, что при добавлении новой формы в dll-ку её необходимо заменить у конечного пользователя (коих может быть несколько десятков), при этом ВЕСЬМА ЖЕЛАТЕЛЬНО (читай: ЖИЗНЕННО НЕОБХОДИМО что бы эти обновления не требовали прерывания рабочего процесса (не надо было бы перезагружать программу или закрывать все вкладки).
Итак - суть проблемы в том, что до тех пор пока активна хотя бы одна форма созданная из библиотеки, эту библиотеку нельзя обновить.
То есть, я делаю следующее:
1. загружаю dll (LoadLibrary)
2. Инициализирую её, передавая туда ссылку на Application
3. Создаю нужный мне класс по имени и помещаю его на вкладку
4. ... работа пользователя с формой на вкладке ...
5. Закрываю вкладку и освобождаю класс формы.
6. Деинициализирую библиотеку.
7. Выгружаю библиотеку (FreeLibrary)
И при всём при этом, я не могу полностью скопировать нужную мне форму в программу, т.к. класс этой формы зарегистрирован внури библиотеки, и после её деинициализации информация об этом классе теряется.

Если у кого-нибудь будут мысли, как полностью извлечь класс формы из библиотеки и следать его независимым от этой самой библиотеки; или каким образом спроектировать расширяемую систему с заданными условиями - поделитесь пожалуйста.

P.S. извините за "многобуков", но этого требует нетривиальность проблеммы.
Greek9000 вне форума Ответить с цитированием
Старый 21.12.2009, 21:34   #2
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,527
По умолчанию

registerclass(TformDll); в exports LoadMyDll
unregisterclass(Tformdll); в exports FreeMyDll
и вызов этих функций при загрузке/выгрузке DLL
программа — запись алгоритма на языке понятном транслятору
evg_m вне форума Ответить с цитированием
Старый 22.12.2009, 06:38   #3
Greek9000
Форумчанин
 
Регистрация: 01.09.2009
Сообщений: 151
По умолчанию

Уважаемый evg_m, если я всё правильно понял, то Вы советуете вынести регистрацию классов в отдельные функции. Это не поможет решить указанную проблему. Сейчас регистрация классов происходит на шаге №2 (см. "Проблема:"), а разрегистрация на шаге №7.

Итак, ещё раз суть проблемы: мне необходимо выгрузить библиотеку (что бы её можно было бы заменить/обновить), но при выгрузке приходится отменять регистрацию классов форм, соответственно, прекращается возможность работы с загруженной из dll-ки формы.
То есть, как правильно (или хотя бы как-нибудь) сделать так, что бы после выгрузки библиотеки была возможность работы с загруженной оттуда формой?

На всякий случай приведу кусок кода, где вызывается форма:
Код:
  
  dllFN := ExtractFileDir(ParamStr(0))+'\'+sLibName; // Путь к dll-ке
  l_hndl := LoadLibrary(PChar(dllFN)); // Загружаем библиотеку
  try
    // Получаем нужные функции из библиотеки
    @fnInitLib    := GetProcAddress(l_hndl, PChar('Init'));
    @fnCreateFrm  := GetProcAddress(l_hndl, PChar('CreateForm'));
    @fnReleaseFrm := GetProcAddress(l_hndl, PChar('ReleaseForm'));
    @fnDeinitLib  := GetProcAddress(l_hndl, PChar('Deinit'));

    if fnInitLib(Cardinal(Application)) then begin // Инициализация (внутри вызов RegisterClasses)

      // Создаём внутри dll-ки форму (по имени класса) и возвращаем ссылку на неё
      Cardinal(frm) := fnCreateFrm(PChar(sClassName)); 

      try
        // Создаём внутри программы экземпляр формы такого же класса
        Application.CreateForm(TComponentClass(frm.ClassType), FTmpForm);

        // работа с формой. тут бы надо поместить её на вкладку, но пока так...
        FTmpForm.ShowModal;
        FTmpForm.Free;
        //  - - - - - - - - - - - - - - - - - - 
      finally
        fnReleaseFrm(Cardinal(frm)); // Освобождаем форму, созданную внутри библиотеки
        fnDeinitLib(); // Деинициализация (Здесь вызывается UnregisterClasses)
      end;
    end;
  finally
    FreeLibrary(l_hndl); // Освобождаем библиотеку
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // FTmpForm.Free;  - Очень надо что бы можно было бы этот код мог вызываться после FreeLibrary(l_hndl); 
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  end;

Последний раз редактировалось Greek9000; 22.12.2009 в 07:09.
Greek9000 вне форума Ответить с цитированием
Старый 22.12.2009, 13:49   #4
Ralf909
 
Регистрация: 22.12.2009
Сообщений: 4
По умолчанию

Цитата:
сделать так, что бы после выгрузки библиотеки была возможность работы с загруженной оттуда формой
Если я правильно понимаю требования то никак. Очень похоже на ошибку проектирования приложения. Если все же не ошибка, то разбираться с сериализацией формы (до конца не додумал-но может тогда вобще без длл можно обойтись ).

Все вышеприведенное является злостным ИМХО.
Ralf909 вне форума Ответить с цитированием
Старый 22.12.2009, 18:19   #5
Greek9000
Форумчанин
 
Регистрация: 01.09.2009
Сообщений: 151
По умолчанию

Тут больше вопрос в постановке задачи.
После усиленного поиска решения возникшей проблемы решено смягчить требования. Теперь пользователю, что бы обновить части приложения необходимо "перелогиниться". Тут проблем никаких. Деинициализируем, выгружаем, загружаем, инициализируем.
Но это доставило мне, как разработчику, массу дополнительной головной боли - решаемой но очень нудной.
Т.о. проблема обновления dll в то время, пока загруженные из неё формы активны остаётся актуальной.
В то же время эта проблема является центральной в деле разработки расширяемых приложенй (один раз написанный каркас с возможностью добавления новых компонентов "на лету" и изменения существующих).
Так что если у кого-то есть мысли, как этого добиться не выходя за рамки Delphi, поделитесь - будтье добры!
Greek9000 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Обращение из формы в dll к элементу главной формы (delphi) a_n_n_a Помощь студентам 3 10.05.2009 04:00
Перенос данных с формы на лист Lyubov1990 Microsoft Office Excel 2 07.04.2009 15:08
DLL b свойства формы ??? spamer Общие вопросы Delphi 10 09.02.2009 21:01
DLL и формы Andrei Isaev Компоненты Delphi 1 18.11.2008 18:25
Работа из dll формы mauar Общие вопросы Delphi 3 05.05.2008 11:40