Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations derfloh on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Dll with open forms cause error when application is close 1

Status
Not open for further replies.

john230873

Programmer
Oct 3, 2003
89
NZ
I have had this probelem for a couple of weeks and Have finally tracked down the cause of the issues. I have a dll which only role is to open a form. If I leave the form open and close the main form then I get a run time error. This seems to be a normal issue with Dll's because I created another quick test program which did the same thing (and other posts). I don't want to use showmodal as I would like the users to open multiple forms at once. I think I need a procedure to call all the dll forms and close them on the close of the main form. I have no idea of the code Help.
 

1) Keep a list of all open forms. Make it global (DLL wise) so the forms can add themselves to the list in the OnCreate procedure and delete themselves in the OnDestroy.

2) Create an exported function to loop the list, calling Free on any listed form.

3) From your program main form OnDestroy call said function.

"3" is important. Do not rely on DLL automatic finalization procedures. Getting detachement signals can be very tricky in a Delphi DLL.

buho (A).
 
Yes you can.

But being you the owner of the code, why to resort to a so convoluted method?

buho (A).
 
Ok now I am stuck. I have tried this in the main form but I don't know how to make it wise to the dll.
I can you the create handle to Populate the openform procedure but I can't get the closing procedure of the Dll to trigger the closing procedure


Function OpenTheForm():Dword;
begin
Form1 := TForm1.Create(application);
Form1.Show;

//Add handle then inc top of array
DllForms[ArrayTop] := Form1.Handle;
inc(ArrayTop);
end;


procedure RemoveFormFromArray(TheHandle :Dword);
//var
// i,OrgArrayTop : Integer;
// OrgDllForms : Array[1..1000] of Dword;
begin
{ //Look for the handle
For i := 1 to ArrayTop-1 do
begin
if DllForms[ArrayTop] = TheHandle then
begin
DllForms[ArrayTop] := 0;
end;
end;
///////////////////////////////////////
//Reorg array to remove deleted Handles
OrgArrayTop := 0;
For i := 1 to ArrayTop-1 do
begin
if DllForms[ArrayTop] <> 0 then
begin
OrgDllForms[OrgArrayTop] := DllForms[ArrayTop];
inc(OrgArrayTop);
end;
end;

For i := 1 to ArrayTop-1 do //copy Temp array to gobal array
DllForms[ArrayTop] := OrgDllForms[OrgArrayTop];

ArrayTop := OrgArrayTop; }

end;

I hope this is what you were meaning Buho.

 
Mmmmm... lets make it this way:

1) Create an unit named, say, FormReg and add it to the uses clause of all your forms and the DLL project.

Code:
------------ FormReg.PAS

interface
uses Contnrs, Forms, ...
type
  TFormRegister = class(TObjectList)
  public
  procedure RegisterForm(F : TForm);
  procedure UnregisterForm(F : TForm);
  procedure ReleaseAll;
  end;

var
  // Public instance of TFormRegister 
  WorkingForms : TFormRegister;


implementation

procedure TFormRegister.RegisterForm(F : TForm); 
begin
  Add(F);
end;

procedure TFormRegister.UnregisterForm(F : TForm);
begin
  Extract(F);
end;

procedure TFormRegister.ReleaseAll;
var
  O : TObject;
begin
  while Count <> 0 do
    begin
      O := First;
      O.Free;
      UnregisterForm(O);
    end;
end;

begin // Unit initialization
  // Create the public object
  WorkingForms := TFormRegister.Create(False);
end.

2) In any OnCreate/OnDestroy

Code:
procedure TSomeForm.OnCreate;
begin
  // Register the form so we know it is working 
  WorkingForms.RegisterForm(Self);
  // Any other code
end;

procedure TSomeForm.OnDestroy;
begin
  // Form is being destroyed, unregister it
  WorkingForms.UnregisterForm(Self);
  // Any other code
end;

3) In the DLL project file (DPR), create and export the next function

Code:
procedure ReleaseAllForms;
begin
  // Free all the working forms
  WorkingForms.ReleaseAll;
end;

4) In the OnDestroy event of the program main form call ReleaseAllForms, to tell the DLL the job is done and the working forms need to be freed.

buho (A).



 

DISCLAIMER: above code written "on the fly". :)

buho (A).

 
This line is giving me this error

UnregisterForm(O);

[Error] FormReg.pas(38): Incompatible types: 'TForm' and 'TObject'

I understand what it means but unsure of a solution. I am looking now but if know that would be cool
 
Ok I have changed TObject to a TFORM and that seems to work However the count never gets about 0. It seems the it create one formreg for the dll and one formreg for each form so when I close the application the Forms are not cleaned up.
I have added a button to my main form and with the sub forms open I have trid to relase them but the count is on 0

 
Thanks buho, I have made some small changes but without you code above I wouldn't have known where to start.

In the procedure
TFormRegister.ReleaseAll
I changed the
UnregisterForm(O);
to
Extract(O)

I also didn't read your instructions correctly. I added the formreg unit to the main form which was wrong it was only to be in the uses causes of the Dll and the forms it calls. When I added the Releaseallforms to the dll as an export it worked fine.

Thanks, this was great
 
Sorry... I messed the types :(.

Nice you got it working.

buho (A).

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top