Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Из DLL не в DLL [D6, Win95/98, WinME, NT4, Win2k, WinXP]


Moningstar ©   (2005-11-01 14:26:00) 

Приветствую, мастера! Вот такая ситуация: в приложении три фомы: Form1 (главная), Form2 и Form3. Form3 вызывается из DLL, динамически. На ней расположен ComboBox. При ComboBoxChange текст выбранного пункта должен отобразиться в Label1, расположенном на Form2. Вопрос, как вы уже догадались, как это сделать?
Код Dll проекта.

library Project1;
uses
 ShareMem, SysUtils, Classes, Forms,
 Unit3 in 'Unit3.pas' {Form3};

{$R *.res}

function ShowForm3: Integer; stdcall;
begin
 Form3 := TForm3.Create(Application);
 Result := Form3.ShowModal;
 Form3.Free;
end;

exports
  ShowForm3;

begin
end.


Код простого проекта.

type
 TShowForm3 = function: Integer;
 TForm2 = class(TForm)
   procedure Button1Click(Sender: TObject);
   Button1: TButton;
   Label1: TLabel;
...
procedure TForm2.Button1Click(Sender: TObject);
var ShowForm3: TShowForm3;
    DLLShowForm3Handle: THandle;
begin
try
DLLShowForm3Handle := loadLibrary ( 'Project1.dll' );
if DLLShowForm3Handle <> 0 then
begin
 @ShowForm3 := getProcAddress ( DLLShowForm3Handle, 'ShowForm3' );
 if addr ( ShowForm3 ) <> nil then
   ShowForm3 else
   showMessage ( 'Function not exists...' );
end;
finally
FreeLibrary(DLLShowForm3Handle);
end;
end;


Ну а из Form1 вызывается Form2 простым Show.


GrayFace   (2005-11-15 18:53:00) [1]

Недописал. OnClose  Action:=caFree;


Moningstar   (2005-11-10 13:11:00) [2]

>Form3.Free; - вместо этого лучше OnЧто за On?


GrayFace   (2005-11-10 08:10:00) [3]

А при чем тут освобождение памяти? Делай, например, так:

Dll:
type
  TSetTextEvent=procedure(text:PChar) of object;

var ChangeEvent:TSetTextEvent;

function ShowForm3(AEvent:TSetTextEvent): Integer;
begin
  ChangeEvent:=AEvent;
  Form3 := TForm3.Create(Application);
  Result := Form3.ShowModal;
  Form3.Free; - вместо этого лучше On
end;

procedure ComboBox1Change(sender...)
begin
  ChangeEvent(pointer(ComboBox1.Text));
end;


В приложении, соответственно
procedure TForm1.Form3ComboChange(text:PChar);
begin
  Label1.Text:=text;
end;


Вообще, форм в dll лучше избегать.


Moningstar   (2005-11-10 06:54:00) [4]

Вроде разобрался, всё работает. Но хотелось бы кое-что уточнить.
При OnChange Label'у на Form2 присваивается только одно значение ComboBox'а - которое было изначально, при создании формы Form3. Т.е. если я делаю выбор итемов, то выбранный мною итем не отображается на Label'е формы Form2. Это можно исправить, сохранив при этом освобождение памяти? Надеюсь, изложил понятно.


Moningstar   (2005-11-03 12:40:00) [5]

>wal
Это мне для развития, так сказать. Однако код не хочет работать (надеюсь, я всё сделал правильно). Ну, зато теперь хоть ошибок не возникает.


wal   (2005-11-03 09:46:00) [6]


> А чтобы работало без закрытия, так можно?
Не уверен, но попробовать можно.
Library ...
...
function ShowForm3( const OnChange: TNotifyEvent): Integer;
begin
 Form3 := TForm3.Create(Application);
  Form3.ComboBox.OnChange :=  OnChange;
 Result := Form3.ShowModal;
 Form3.Free;
end;
...


type
TShowForm3 = function( const OnChange: TNotyfyEvent): Integer;
TForm2 = class(TForm)
  procedure Button1Click(Sender: TObject);
  procedure OnChange(Sender: TObject);
  Button1: TButton;
  Label1: TLabel;
...
procedure TForm2.Button1Click(Sender: TObject);
var ShowForm3: TShowForm3;
   DLLShowForm3Handle: THandle;
begin
try
DLLShowForm3Handle := loadLibrary ( 'Project1.dll' );
if DLLShowForm3Handle <> 0 then
begin
@ShowForm3 := getProcAddress ( DLLShowForm3Handle, 'ShowForm3' );
if addr ( ShowForm3 ) <> nil then
  ShowForm3(OnChange) else
  showMessage ( 'Function not exists...' );
end;
finally
FreeLibrary(DLLShowForm3Handle);
end;

procedure TForm2.OnChange(Sender: TObject);
begin
if (Sender is TComboBox) then
   with (Sender as TComboBox) do
     Label1.Caption := Text
end;


end;


Только вот зачем такие извраты - непонимаю.


Moningstar   (2005-11-02 15:08:00) [7]

>evvcom
А чтобы работало без закрытия, так можно?


evvcom   (2005-11-02 14:23:00) [8]

В [1] результат будет отображаться в Form2 не при событии ComboBox1Change, а после закрытия модальной формы 3. Из основного модуля:
ShowForm3(NewCaption);
Form2.Label1.Caption:=NewCaption;
и все


Moningstar   (2005-11-02 13:20:00) [9]

>wal
Я не понял, как таким образом при событии ComboBox1Change из Form3 результат будет отображаться в Form2. У меня возникает ошибка Access violation. А делаю вот что (не судите строго, я начал изучать DLL буквально неделю назад):
procedure TForm3.ComboBox1Change(Sender: TObject);
begin
Form2.Label1.Caption:=ComboBox1.Text;
end;
Как применить переменную S, не могу понять.


evvcom   (2005-11-01 14:55:00) [10]


> функцию чтения текста из ComboBox, а в основной программе
> циклический вызов этой функции

Не надо так делать.

> function ShowForm3(var S: string): Integer; stdcall;

Здесь stdcall лишнее. Все равно эта функция может быть вызвана только из программ написанных в Delphi, поэтому здесь это не нужно. Ну и естественно в проекте exe тоже не упоминать об stdcall


AbrosimovA   (2005-11-01 14:41:00) [11]

Попробуй создать в длл-ке функцию чтения текста из ComboBox, а в основной программе циклический вызов этой функции. Только учесть надо, что передаваемое этой функцией значение не должно быть типа string.


wal   (2005-11-01 14:38:00) [12]

library Project1;
uses
ShareMem, SysUtils, Classes, Forms,
Unit3 in 'Unit3.pas' {Form3};

{$R *.res}

function ShowForm3 (var S: string): Integer; stdcall;
begin
Form3 := TForm3.Create(Application);
Result := Form3.ShowModal;
S := ComboBox.Text;
Form3.Free;
end;

exports
 ShowForm3;

begin
end.


Наверх

Титульная страница Поиск, карта сайта Написать письмо