Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.11.13;
Скачать: CL | DM;

Вниз

DLL и немодальный формы в них   Найти похожие ветки 

 
Rianon ©   (2005-10-17 23:36) [0]

Кто может показать полный код, который покажет как правильно использовать немодальные формы в Dll и потом вызывать их в программе. На разных форумах иного всего написано но не до конца.
А проблема в чем:
Есть Dll в ней немодальная форма, в которую надо потом при вызове передать ряд параметров и потом по завершению тоже ряд других забрать.Dll связывается динамически
Так вот создал 2 функции CreateForm(...), FreeForm но если вызов происходит более или менее нормально то завершить корректно немодальную форму не удается никогда то вообще проэкт закроет то  ошибку выдаст.. Делфи то на Free матюгом кричит то на FreeLibrary...
Помогите плз... но лучше всего реально работающим  проектом Всю эту муть хочется использовать в некоторое подобие плагинов..


 
Германн ©   (2005-10-18 01:04) [1]

Имхо, "DLL" и "форма" есть понятия совместимые только с учётом "геморроя"!
И "DLL" изначально разрабатывалось без учета наличия "форм". И "формы" изначально разрабатывались без учета "DLL".
Некая "затычка" в сём вопросе в Дельфи - "BPL". Но и там есть претензии. И есть свой геморрой.


 
Джо ©   (2005-10-18 02:58) [2]

Вот, например, достаточно "безгеморройный" способ, основанный на отдельном менеджере, занимающемся загрузкой/выгрузкой.


//
//  Модуль главного окна тестовой программы
//  На форме - одна кнопка и обработчик к ней
//

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   procedure Button1Click(Sender: TObject);
 public
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

type
 // Менеджер, отвечающий за загрузку/выгрузку модулей
 // и уничтожение форм
 TFormLoader = class
 private
   FLibs,
   FHandles: TList;
   procedure UnloadLibraries;
 public
   // этот метод вызывает указанную функцию в указанном модуле
   // и регистрирует все необходимое для последующей "очистки"
   procedure LoadForm (DllName,ProcName: string);
   constructor Create;
   destructor Destroy; override;
 end;

var
 FormLoader: TFormLoader;

// щелчок на кнопке
procedure TForm1.Button1Click(Sender: TObject);
begin
 // загружаем еще один экземпляр формы
 // нашим менеджером
 // указывая имя DLL и имя функции в нем
 FormLoader.LoadForm("mydll.dll","ShowForm");
end;

{ TFormLoader }

constructor TFormLoader.Create;
begin
 inherited Create;
 FLibs := TList.Create;
 FHandles := TList.Create;
end;

destructor TFormLoader.Destroy;
begin
 // уберем за собой
 UnloadLibraries;
 FLibs.Free;
 FHandles.Free;
 inherited;
end;

procedure TFormLoader.LoadForm(DllName, ProcName: string);
type
 // вызываемая функция должна соответствовать этой декларации!!
 TProc = function(MainFrmHandle: Cardinal): Cardinal;
 //
var
 Lib: THandle;
 Proc: TProc;
 Err,
 WindowHandle: Cardinal;
begin
 Lib := LoadLibrary(PChar(DllName));
 if Lib <> 0 then
 begin
   Proc := GetProcAddress(Lib,PChar(ProcName));
   if @Proc <> nil then
   begin
     // выполняем функцию в DLL
     // и получаем хэндл созданного окна
     WindowHandle := Proc(Application.Handle);
     // добавляем модуль и хэндл окна
     // в свои списки
     FHandles.Add(Pointer(WindowHandle)) ;
     FLibs.Add(Pointer(Lib));
   end
   else
   begin
     // библиотеку необходимо выгрузить
     // ибо GetProcAddress завершился неуспешно
     Err := GetLastError;
     FreeLibrary(Lib);
     raise Exception.Create(SysErrorMessage(Err));
   end
 end
 else
   RaiseLastOSError;
end;

procedure TFormLoader.UnloadLibraries;
var
 I: Integer;
 WH,
 LH: Cardinal;
begin
 // 1. "убивание" окон если они еще существуют на момент вызова
 // 2. выгрузка соответствующих библиотек
 for I := 0 to FLibs.Count-1 do
 begin
   WH := Cardinal(FHandles[I]);
   if IsWindow(WH) then
     DestroyWindow(WH);
   LH := Cardinal(FLibs[I]);
   FreeLibrary(LH);
 end;
end;

initialization
 // инициализируем менеджер при старте программы
 FormLoader := TFormLoader.Create;

finalization
 // удаляем менеджер
 // (при уничтожении он автоматически "убъет" все загруженные формы
 // и выгрузит библиотеки)
 FormLoader.Free;
end.


Теперь библиотека

library mydll;

uses
 SysUtils,
 Classes,
 Forms,
 DllFormUnit in "DllFormUnit.pas" {DllForm};

{$R *.res}

// Функция, вызов которой создает и показывает форму,
// находящуюся в DLL
// Должна возвращать handle созданного окна
// В MainFrmHandle передаем Application.Handle
// вызывающей программы (для того, чтобы не создавать новый tab
// на полосе задач). Можно игнорировать
function ShowForm (MainFrmHandle: Cardinal): Cardinal;
var
 Frm: TDllForm;
begin
 if MainFrmHandle <> 0 then
    Application.Handle := MainFrmHandle;
   
 Frm := TDllForm.Create(nil);
 Result := Frm.Handle;
 Frm.Show
end;

exports
 ShowForm;

end.

Ну, и к ней, разумеется, идет соответствующий модуль с классом формы. Здесь - TDllForm.
------
Надеюсь, все достаточно понятно.


 
Leonid Troyanovsky ©   (2005-10-18 09:39) [3]


> Джо ©   (18.10.05 02:58) [2]
> Вот, например, достаточно "безгеморройный" способ, основанный
..
> Надеюсь, все достаточно понятно.


Понятно, конечно.
Непонятно, почему даже после многочисленних здешних дискуссий на эту
тему оный способ позиционируется как безгеморойный для
немодальных форм.
Ведь, только недавно  некто искал потерянные CM_MOUSELEAVE.

IMHO, нельзя создавать немодальные формы в dll.
Или, лучше сказать так: эти dll обязаны быть либо bpl, либо ocx.
Ну, или, какая-нибудь гремучая комбинация.

--
Regards, LVT.


 
Rianon ©   (2005-10-18 20:35) [4]

Да это конечно все весело, но насчет
- Или, лучше сказать так: эти dll обязаны быть либо bpl, либо ocx.
посмотрите на Тотал Комманлдер там ведь работает....


 
Джо ©   (2005-10-18 21:32) [5]


>  [4] Rianon ©   (18.10.05 20:35)

Ты с [2], надо полагать, уже разобрался до конца?


 
Джо ©   (2005-10-18 21:35) [6]

Кроме того, ГДЕ в TC используется то, о чем ты говоришь? Например, окно Листера создается, насколько я знаю, в программе, а не в ДЛЛ.


 
Rianon ©   (2005-10-19 19:34) [7]

Да и плагины листера (напр по расширениям) - посмотрите их описания там черным по белому пищут  File is Dll есть даже перечень экспортных процедур
но спасибо всеравно я нашел способ


 
Джо ©   (2005-10-19 19:57) [8]


> [7] Rianon ©   (19.10.05 19:34)

Еще раз: главное окно Lister"а создается НЕ в DLL! Оно создается самим TotalCommander, т.е., в программе. См. описание функции ListLoad в LISTPLUGIN.HLP.


 
Джо ©   (2005-10-19 19:59) [9]


> [3] Leonid Troyanovsky ©   (18.10.05 09:39)
> IMHO, нельзя создавать немодальные формы в dll.

"Форма" создается в DLL. Но для вызывающей программы - это никакая не форма. Все, что она знает об этом окне - это его Handle.


 
Leonid Troyanovsky ©   (2005-10-20 09:31) [10]


> Джо ©   (19.10.05 19:59) [9]

> > IMHO, нельзя создавать немодальные формы в dll.

> "Форма" создается в DLL. Но для вызывающей программы - это
> никакая не форма. Все, что она знает об этом окне - это
> его Handle.


Проблема в том, что в хосте и библиотеке свои копии кода всех ключевых
модулей. И переменных, причем, не только Screen, Application & etc, но и
таких, которые объявлены в разделе implementation.
Ну, и отсюда вытекает много проблем, как известных: hints, actions &etc,
так и малоизученных (кому оно нужно).
Создание модальных форм в длл предложенным способом еще более-менее
терпимо. А от такого использования немодальных (и MDI), прогрессивное
дельфийское сообщество отказалось, AFAIK, еще в прошлом веке.

--
Regards, LVT.



Страницы: 1 вся ветка

Текущий архив: 2005.11.13;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.046 c
2-1129563459
Rasher
2005-10-17 19:37
2005.11.13
Вопрос о всплывающих окнах


2-1130299499
UVV
2005-10-26 08:04
2005.11.13
Можно ли так, или я многого хочу от Delphi


14-1129869784
Nic
2005-10-21 08:43
2005.11.13
Никто не сталкивался с такой задачей со шрифтами...


14-1129821760
BerkeleyMan
2005-10-20 19:22
2005.11.13
Посоветуйте программу (Audio CD -> MP3)


3-1128068250
KeyC
2005-09-30 12:17
2005.11.13
Direct access to MS Access