Solved

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

Posted on 2002-05-31
15
460 Views
Last Modified: 2010-04-04
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.
0
Comment
Question by:chrisgreening
  • 3
  • 3
  • 3
  • +6
15 Comments
 
LVL 3

Expert Comment

by:tongalite
Comment Utility
Hi,
you could try this:
Sst up the closequery event of your mainform.
Good luck
T.

*******************************

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

var
  h: HWND;
begin
  h := FindWindow(nil, 'your_non-modalform_caption');
  if h <> 0 then PostMessage(h, WM_CLOSE, 0, 0);
end;
0
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
Provide a onClose-event-procedure in your childform like

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

meikl ;-)
0
 

Author Comment

by:chrisgreening
Comment Utility
tongalite,

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
0
 
LVL 3

Expert Comment

by:tongalite
Comment Utility
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 :)
T.
0
 

Author Comment

by:chrisgreening
Comment Utility
soz it is a form in one of our packages(bpl)
0
 

Author Comment

by:chrisgreening
Comment Utility
LOMSlaine may add to this post as he works with me and he is the developer having this problem.
0
 

Expert Comment

by:LOMSlaine
Comment Utility
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
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 1

Expert Comment

by:thegroup
Comment Utility
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.
0
 

Expert Comment

by:LOMSlaine
Comment Utility
Well, we are getting access violations when the package that contains the form is unloaded.
0
 
LVL 4

Expert Comment

by:nestorua
Comment Utility
HI,
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).
Sincerely,
Nestorua.
0
 
LVL 1

Expert Comment

by:DavidLeeding
Comment Utility
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);
begin
  // Send message to main form...

  PostMessage(frmMain.Handle,
              WM_USER + MSG_CLOSESTUDENTS, 0, 0);
  Action := caFree;

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


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

  //.....etc
end;

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

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

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


Hope this helps!

0
 

Expert Comment

by:LOMSlaine
Comment Utility
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
0
 
LVL 3

Expert Comment

by:tongalite
Comment Utility
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:
tongalite.
********************


I get an error when closing an MDI form using:
close;
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  ;
BEGIN
   Child.Close;
   Action := caFree;
END;

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!??
 
************************  
 
REPLY:
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  ;
BEGIN
//   Child.Close;
   Action := caFree;
END;

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.
0
 
LVL 1

Expert Comment

by:pnh73
Comment Utility
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.
 
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
 
Paul (pnh73)
EE Cleanup Volunteer
0
 
LVL 6

Accepted Solution

by:
Mindphaser earned 0 total points
Comment Utility
Force accepted

** Mindphaser - Community Support Moderator **
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now