Q&A

  • 번호108840 다시질문.. "DLL에 있는 MDI Child폼 사용하고 난 후 Free시점"-
안녕하세요

최용일님이 자료실에 작성한     "" [예제] 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;

이런식으로 구성되었습니다.
1  COMMENTS
  • Profile
    살며배우며 2006.09.21 09:48
    요즘은 델파이로 프로그램을 하지 않아 정말로 오랜만에 들어왔네요!!

    질문에 답변아닌 답변을 드리자면은

    저 같은경우는 공유메모리를 이용해서 해결했습니다.
    차일드 폼이 종료될때  공유메모리에 차일드 프로그램명을 넣어주고..
    메인에서는 타이머로 공유메모리를 계속 첵크하여 프로그램명을 있으면 해당 차일폼의 핸들을 찾아
    free해주는 방법으로 처리했습니다.

    도움이 되셨으면 합니다.
    즐프하세요..!

    ==============================================================