How do I free a non modal window in a MDI App?

We have a MDI Application that needs a non modal window which can be left open when the user closes the application, how do I get the application to free this window automatically on closure?

We are using packages and the application doesn't know about the window.
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

you could try this:
Sst up the closequery event of your mainform.
Good luck


procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);

  h: HWND;
  h := FindWindow(nil, 'your_non-modalform_caption');
  if h <> 0 then PostMessage(h, WM_CLOSE, 0, 0);
Provide a onClose-event-procedure in your childform like

procedure TChildForm.FormClose(Sender: TObject; var Action: TCloseAction);
  Action := caFree;

meikl ;-)
chrisgreeningAuthor Commented:

thanks for that but still no joy, still getting Access Violations any other suggestions and we do have an onClose Event on the childform kretzschmar
Starting with Angular 5

Learn the essential features and functions of the popular JavaScript framework for building mobile, desktop and web applications.

Hi cg,

when you say...
" We are using packages and the application doesn't know about the window"
Do you mean it's an external window (in a dll perhaps)?
Can you be a bit more specific :)
chrisgreeningAuthor Commented:
soz it is a form in one of our packages(bpl)
chrisgreeningAuthor Commented:
LOMSlaine may add to this post as he works with me and he is the developer having this problem.
We have a MDI Application, on this application we have a window that is popped up, this is a NON-MDI form and is NON-Modal. This form is created from an object in a Package, with the application being the owner (this was changed from the object it was created in an attempt
to resolve this issue), The problem begin is that the Application is throwing errors when it trys to unload the package that the form is held.

In the forms close event i have action := CaFree, the forms destructor is called and seems to go through ok. i just get 4 run time errors and an error saying that all forms couldn't be shut down.

I will be happy to answer any questions, if anyone could help i would be really grateful
If a window in your application remains open then your application remains open. You could close (hide) the main window but this doesn't close your application.

When you close (destroy) your main form your application closes, release all bpl in use and this closes all child windows that where created in there.

In your case the non modal window close happens automatically on application close. You not need to do a thing.
Well, we are getting access violations when the package that contains the form is unloaded.
Could you tell me the following:
1.Is your Form created from the package is a ChildForm for your MDI Form.
2.How do you create that form (I mean post the simplest code
of creation your form which generates errors).
This might be a longshot...but here goes...I have come across a similar problem to yours: an application which opened a non-modal window in an MDI context would always generate errors on closing the form. The only way we could find to resolve it was to set the form variable to nil, eg:

    winStudents := nil;

where winStudents is a variable in the main form unit created using something like:

  winStudents := TfrmStudents.Create(Application);
The key bit of code sits in the OnAppMessage of the main form, and is triggered in reponse to a message sent by the problematic form when it is closed, eg:

// In child form:
// -------------
procedure TfrmStudents.FormClose(Sender: TObject; var Action: TCloseAction);
  // Send message to main form...

              WM_USER + MSG_CLOSESTUDENTS, 0, 0);
  Action := caFree;

  //NB: MSG_CLOSESTUDENTS is (obviously) a constant with
  //an arbitrary value defined for the whole project

//In main form:
// -----------
procedure TfrmMain.FormCreate(Sender: TObject);
  Application.OnMessage := OnAppMessage;


procedure TfrmMain.OnAppMessage(var Msg : TMsg; var Handled : Boolean);
  if Msg.Message = (WM_USER + MSG_CLOSESTUDENTS) then
    winStudents := nil;
    Handled := TRUE;

procedure TfrmMain.mnuStudentsClick(Sender: TObject);
  // Create/Open the students window
  // winStudents is a global variable of TfrmStudents

  winStudents := TfrmStudents.Create(Application);
  //... show window, disable menu item, yada yada

Hope this helps!

problem with this is for every window created like this we a variable will have to be held on the main application, this isn't very practical as new screens are added on a weekly basis, with this in mind it would be hard to maintain the application with all the screens
Hi again cg.

I was looking at another forum and came across this question which is similar in nature to your problem. Not a solution but you might be interested. Here it is:

I get an error when closing an MDI form using:
but it works when I click the form close button (the cross in the right corner).
Where is the difference?

I get this..... *address violation at... read of address...etc*
It has something to do with the way this close works. There is a close on the children and on the main form. If I close the children first it works now !?
The failure just happens if I try to use this in the child form:

PROCEDURE TChild.Exit1Click(Sender: TObject);
VAR Action: TCloseAction  ;
   Action := caFree;

Close alone just close the child form. Procedure CloseAll;Close; does not close the main form as well.
At the moment I close the childs from the childs menu and the main formcontains the exit button.
However I can close everyting at once via the forms right/top exit button!??
When the form executes this method it is already in the process of being closed.
If the object 'Child' refers to the instance of the form you are trying to close then I would expect an access violation. This would have the effect of sending another windows WM_CLOSE message to the form that you have just destroyed.
I suspect the line Child.Close should be removed as per code sample below.

PROCEDURE TChild.Exit1Click(Sender: TObject);
VAR Action: TCloseAction  ;
//   Child.Close;
   Action := caFree;

To be more specific, you assigned the mainform as the "Owner" of the child form, by sending it as the parameter to the Create method. This is very important and is commonly done. This is telling the mainform to call close when it is closed.
I generally don't do this with the Children of a form. I usually send Nil to the Create... This means that I need to close the Children myself, but I already know that there is an array of the Children anyway.
If you are telling it to automatically close it when the main form is closed, then you cannot allow the user to close any of the children (and instead hide it) and that makes no sense.
So, do not take out the close in the main form's close handler.... instead call the child's constructor with Nil as the parameter.
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

PAQ with No Refund

Please leave any comments here within the next seven days.
Paul (pnh73)
EE Cleanup Volunteer
Force accepted

** Mindphaser - Community Support Moderator **

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.