[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 470
  • Last Modified:

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.
0
chrisgreening
Asked:
chrisgreening
  • 3
  • 3
  • 3
  • +6
1 Solution
 
tongaliteCommented:
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
 
kretzschmarCommented:
Provide a onClose-event-procedure in your childform like

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

meikl ;-)
0
 
chrisgreeningAuthor Commented:
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
tongaliteCommented:
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
 
chrisgreeningAuthor Commented:
soz it is a form in one of our packages(bpl)
0
 
chrisgreeningAuthor Commented:
LOMSlaine may add to this post as he works with me and he is the developer having this problem.
0
 
LOMSlaineCommented:
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
 
thegroupCommented:
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
 
LOMSlaineCommented:
Well, we are getting access violations when the package that contains the form is unloaded.
0
 
nestoruaCommented:
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
 
DavidLeedingCommented:
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
 
LOMSlaineCommented:
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
 
tongaliteCommented:
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
 
pnh73Commented:
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
 
MindphaserCommented:
Force accepted

** Mindphaser - Community Support Moderator **
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 3
  • 3
  • 3
  • +6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now