안녕하세요
최용일님이 자료실에 작성한 "" [예제] DLL에 있는 MDI Child폼 사용하기. "" 이용해서 Dll프로그램을 개발하고있습니다.
근데 문제점은 어느시점에서 Dll을 Free시켜줘야 할지 모르겠습니다.
개발환경은 델파이6입니다.
프로그램 종료시 스택오버플로워가 걸립니다.
해결방안이있으면 좀 찾아 주시길 바랍니다 ㅠㅠ
그리고 밑에 제가 질문했었는데
감사하게도 최용일님이 답변을 달아 주셨더라구요
근데 제가 한폼만 열다면 상관이 없겠지만 계속 여러개폼을 열어야 하고 그 폼을 종료시키질 않을수도 있고
그래서 인터넷을 찾다가 Postmessage사용해서 하면 된다고 해서 찾아서 해 보았는데
에러가 발생합니다
여러 고견님들의 답변 부탁 드립니다.
감사합니다.
//////////DLL폼////////////////////////
library P001;
{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }
uses
Windows,
Messages,
SysUtils,
Classes,
Graphics,
Controls,
Forms,
Dialogs,
w_001 in 'w_001.pas' {fw_001};
{$R *.res}
var
DllApplication: TApplication;
procedure ProvaChild(ParentApplication: TApplication; ParentForm: TForm ); export; stdcall; //; DllHandle : THandle
var
Fw_001 : TFw_001;
begin
Application:=ParentApplication;
Fw_001:=TFw_001.Create(ParentForm);
with Fw_001 do begin
MyParentForm:=ParentForm;
MyParentApplication:=ParentApplication;
Show;
end;
end;
procedure DLLUnloadProc(Reason: Integer); register;
begin
if Reason = DLL_PROCESS_DETACH then begin
Application:=DllApplication;
end;
end;
exports
ProvaChild;
begin
DllApplication:=Application;
DllProc := @DLLUnloadProc;
end.
//////////////////////DLL : P001 unit//////////////////////////////////////
unit w_001;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
Tfw_001 = class(TForm)
Label1: TLabel;
Memo1: TMemo;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
MyParentForm: TForm; //todo : 추가된것 //DLL화면의 Parent 정의
MyParentApplication: TApplication; //todo : 추가된것 //DLL화면의 Parent 정의
end;
var
fw_001: Tfw_001;
implementation
{$R *.dfm}
procedure Tfw_001.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := Cafree;
end;
procedure Tfw_001.FormDestroy(Sender: TObject);
begin
PostMessage(Application.MainForm.Handle,WM_USER + 1,0,0) ;
end;
////////////////////////main폼/////////////////////
unit Main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus;
type
TForm1 = class(TForm)
MainMenu1: TMainMenu;
DLL1: TMenuItem;
N11: TMenuItem;
N21: TMenuItem;
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure N21Click(Sender: TObject);
private
{ Private declarations }
public
DllHandle : THandle;
procedure WndProc(var message : TMessage); override;
{ Public declarations }
end;
T_ProvaChild = procedure (ParentApplication: TApplication; ParentForm: TForm); stdcall; //; Dllhandle : THandle
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var
i : integer ;
begin
for i:=0 to Screen.FormCount - 1 do
if Screen.Forms[i].Name <> 'FMain' then
Screen.Forms[i].close ;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := Cafree;
end;
procedure TForm1.N21Click(Sender: TObject);
var
DllName : String;
ProcAddr: FarProc;
ProvaChild: T_ProvaChild;
begin
LockWindowUpdate(Handle);
DllName := (Sender as TMenuItem).Hint;
DllHandle := LoadLibrary(pchar(DllName));
ProcAddr := GetProcAddress(DllHandle, 'ProvaChild');
if ProcAddr <> nil then begin
ProvaChild := ProcAddr;
ProvaChild(Application,Self); //,DllHandle
end
else begin
showmessage('dll 없다네');
LockWindowUpdate(0);
exit;
end;
end;
procedure TForm1.WndProc(var message: TMessage);
begin
case message.Msg of
WM_USER + 1 :
begin
FreeLibrary(DllHandle) ;
end ;
end;
inherited;
end;
이런식으로 구성되었습니다.
질문에 답변아닌 답변을 드리자면은
저 같은경우는 공유메모리를 이용해서 해결했습니다.
차일드 폼이 종료될때 공유메모리에 차일드 프로그램명을 넣어주고..
메인에서는 타이머로 공유메모리를 계속 첵크하여 프로그램명을 있으면 해당 차일폼의 핸들을 찾아
free해주는 방법으로 처리했습니다.
도움이 되셨으면 합니다.
즐프하세요..!
==============================================================