Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2005.11.13;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.046 c
14-1129637788
Opilki_Inside
2005-10-18 16:16
2005.11.13
Где бы взять описание .bat


1-1129822852
CaptainAlex
2005-10-20 19:40
2005.11.13
Обработчик события указывает на "псевдометод"


2-1128954918
serko
2005-10-10 18:35
2005.11.13
QuickRep


14-1130088231
alexsis
2005-10-23 21:23
2005.11.13
Бесплатный посыл СМС-ок


4-1126609187
Cherrex
2005-09-13 14:59
2005.11.13
Как использовать GetUserName





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский