Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Urgent Help: Closing a modal form programmatically -- reposted

28 views
Skip to first unread message

Bobby Jones

unread,
May 28, 1997, 3:00:00 AM5/28/97
to

I left a message a few hours ago and got one reply, however, I neglected
to provide enough detail in my earlier message. Here goes again.

I am familiar with the ModalResult property. But I haven't been able to
get it to work for me. What I am doing is from the main form, I create
the subsidiary form. Then I show that form with ShowModal.

In brief, that subsidiary form looks like:

procedure TfrmPrtOrd.FormShow(Sender: TObject);
var
caAction: TCloseAction;
begin
caAction:= caFree;
prtOrd(Sender); {this routine prints the report}
FormClose(Sender, caAction);
end;

procedure TfrmPrtOrd.FormClose(Sender: TObject; var Action:
TCloseAction);
begin
frmPrtOrd.ModalResult:= mrOk;
frmPrtOrd.Close;
Action:= caFree;
end;

What actually happens, though, is that the report prints just fine, but
the form does not close after printing the report, unless I manually
close it. I want my code to do the close, however. The reason for the
ShowModal in the first place is that if the user so much as moves the
mouse while the report is printing, the program GPFs. (if there is a
simpler way to get rid of the GPF, that's great, too!) Any suggestions?

Thanks!
Bob Jones

DosMan

unread,
May 29, 1997, 3:00:00 AM5/29/97
to

Several problems with your code. First, since you are already inside the
form's methods, you do not need to specify the form name in front of the
method calls.

For instance:
(Your code)


procedure TfrmPrtOrd.FormClose(Sender: TObject; var Action:
TCloseAction);
begin
frmPrtOrd.ModalResult:= mrOk;
frmPrtOrd.Close;
Action:= caFree;
end;


frmPrtOrd is not needed in front of the methods. It should read:

Procedure TfrmPrtOrd.FormClose(Sender: TObject; var Action:
TCloseAction);
begin
ModalResult:= mrOk;
end;

You are also adding alot of extra code here. Your GPF problem stems from
the fact that you are trying to create the form from within itself. You
would need to create this form from inside another form(the one calling
it). Instead, you are calling a method inside the form before the form is
even initialized. Thus your GPF problem.

The correct way is to create the from, then show it.

Assuming you are in a Unit called MAIN and that is showing your form, the
correct syntax is:


Procedure ShowAForm;
Begin
Try Try
MyForm := TMyForm.Create(Nil);
MyForm.ShowModal;
Except
On E: Exception Do
MessageDlg('There Was An Error: '+E.Message,mtError,[mbOK],0);
End;
Finally
MyForm.Free;
End;
End;


You need to start using Try..Except..Finally blocls to ensure robust code.
The code shown above will trap off errors that might arise instantiating
the form. The code then deallocates the memory used for the form when it is
done.

In the code for MYFORM, when you want the form to close, simply set:
ModalResult := mrOK;

That should solve your problem.


Dan

Kirk B. Spadt

unread,
May 30, 1997, 3:00:00 AM5/30/97
to

In article <338C01...@earthlink.net>,
Bobby Jones <ct...@earthlink.net> wrote:

>I am familiar with the ModalResult property. But I haven't been able to
>get it to work for me. What I am doing is from the main form, I create
>the subsidiary form. Then I show that form with ShowModal.
>
>In brief, that subsidiary form looks like:
>
>procedure TfrmPrtOrd.FormShow(Sender: TObject);
>var
> caAction: TCloseAction;
>begin
> caAction:= caFree;
> prtOrd(Sender); {this routine prints the report}
> FormClose(Sender, caAction);
>end;
>

>procedure TfrmPrtOrd.FormClose(Sender: TObject; var Action:
>TCloseAction);
>begin
> frmPrtOrd.ModalResult:= mrOk;
> frmPrtOrd.Close;
> Action:= caFree;
>end;
>

>What actually happens, though, is that the report prints just fine, but
>the form does not close after printing the report, unless I manually
>close it. I want my code to do the close, however. The reason for the
>ShowModal in the first place is that if the user so much as moves the
>mouse while the report is printing, the program GPFs. (if there is a
>simpler way to get rid of the GPF, that's great, too!) Any suggestions?


ShowModal works this way (simplified): The application's other form(s) are
disabled, your FormShow method is executed, the form is displayed,
ModalResult is set to mrNone, then the form waits for events to happen.
Since the system resets ModalResult after your FormShow is executed, the
system never sees your Close method or ModalResult assignment. You may also
have noticed that your processing was completed before the form ever
appeared.

To display the form before starting the processing, I send a user-defined
message to the form in FormShow, then do the processing in the procedure
that handles that message. Since the form is already displayed during my
processing, the Close method and ModalResult assignments take effect.

Here is what I mean:

- - - - Example - - - -

unit Cashent;

interface

uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, Ctrls, ExtCtrls, DB;

const
umStartupSales = wm_User + $111;

type
TFormCashent = class(TForm)
PanelHint: TPanel;
GroupTranInfo: TGroupBox;
EditCashier: TEditNum;
procedure FormShow(Sender: TObject);
private
procedure StartUpSales(var Msg: TMessage); message umStartupSales;
public
end;

var
FormCashent: TFormCashent;

implementation

{$R *.DFM}

procedure TFormCashent.FormShow(Sender: TObject);
begin
PostMessage(Handle, umStartupSales, 0, 0);
end;

procedure TFormCashent.StartUpSales(var Msg: TMessage);
begin
{Do your processing here}
ModalResult := mrOK;
end;

end.

- - - - End of example - - - -

I noticed that you referenced the instance of the form within a method of
the form ("frmPrtOrd.Close" should be "Close"). Since the current instance
of the form is implied, that is not necessary (and will give the wrong
result if you have multiple instances of the form). In some methods, e.g.
Create, that will cause GPF's.

Also, I have had bad luck specifying caFree for a form within its close
procedure, unless it is an MDI child. That may be the cause of the GPF.
Instead, I free the form after the ShowModal call. Using my example:

Application.CreateForm(TFormCashent, FormCashent);
FormCashent.ShowModal;
FormCashent.Free;
FormCashent := Nil;

would be used in the calling form.

-Kirk


------------------------------------------------
Kirk B. Spadt ksp...@keyware.com
Keyware Systems, Inc.
570 Lindsey Drive (610) 964-9530
Radnor, PA 19087 (610) 964-0543 fax

Rob Powers

unread,
May 30, 1997, 3:00:00 AM5/30/97
to

Bobby Jones <ct...@earthlink.net> wrote in article
<338C01...@earthlink.net>...


> I left a message a few hours ago and got one reply, however, I neglected
> to provide enough detail in my earlier message. Here goes again.
>

> I am familiar with the ModalResult property. But I haven't been able to
> get it to work for me. What I am doing is from the main form, I create
> the subsidiary form. Then I show that form with ShowModal.
>
> In brief, that subsidiary form looks like:
>
> procedure TfrmPrtOrd.FormShow(Sender: TObject);
> var
> caAction: TCloseAction;
> begin
> caAction:= caFree;
> prtOrd(Sender); {this routine prints the report}
> FormClose(Sender, caAction);
> end;
>
> procedure TfrmPrtOrd.FormClose(Sender: TObject; var Action:
> TCloseAction);
> begin
> frmPrtOrd.ModalResult:= mrOk;
> frmPrtOrd.Close;
> Action:= caFree;
> end;


I ran into this same problem last week. The issue is that you cannot set
the ModalResult in the OnShow or OnActivate events to close the window. The
reason for this can be seen in FORMS.PAS, in the TForm.ShowModal function.
Right after the CM_ACTIVATE message is sent to the form, the ModalResult is
set to 0. So if you set a ModalResult any time before the Activate event
has occurred, you're out of luck.

Here's one method to solve this:

Create a variable in your form's class to store a temporary ModalResult.
When you would normally set the ModalResult in your OnActivate or OnShow
events, set this temporary variable instead.

Put a timer on your form called CloseWindowTimer. Set the interval to 1000
or less and make its default enabled value to be False.

At the end of your OnActivate method, set the CloseWindowTimer enabled to
True.

In the CloseWindowTimer's OnTimer event, turn off the timer, and set the
form's ModalResult to the temporary one stored in the variable you created
above. This will close the window. No need to call Form.Close (which always
sets the ModalResult to 0 by the way) or to put code in the OnClose event
to shut the window down.

Sometimes problems like these look really nasty. A quick look at the VCL
source often reveals all. If you don't have the source, it is definitely
worth getting...

Rob Powers
rob...@registrysystems.com

Jason M. Perry

unread,
Jun 4, 1997, 3:00:00 AM6/4/97
to Bobby Jones

Bobby Jones wrote:

> I left a message a few hours ago and got one reply, however, I
> neglected
> to provide enough detail in my earlier message. Here goes again.
>
> I am familiar with the ModalResult property. But I haven't been able
> to
> get it to work for me. What I am doing is from the main form, I create
>
> the subsidiary form. Then I show that form with ShowModal.
>
> In brief, that subsidiary form looks like:
>
> procedure TfrmPrtOrd.FormShow(Sender: TObject);
> var
> caAction: TCloseAction;
> begin
> caAction:= caFree;
> prtOrd(Sender); {this routine prints the report}
> FormClose(Sender, caAction);
> end;
>
> procedure TfrmPrtOrd.FormClose(Sender: TObject; var Action:
> TCloseAction);
> begin
> frmPrtOrd.ModalResult:= mrOk;
> frmPrtOrd.Close;
> Action:= caFree;
> end;
>

> What actually happens, though, is that the report prints just fine,
> but
> the form does not close after printing the report, unless I manually
> close it. I want my code to do the close, however. The reason for the
> ShowModal in the first place is that if the user so much as moves the
> mouse while the report is printing, the program GPFs. (if there is a
> simpler way to get rid of the GPF, that's great, too!) Any
> suggestions?
>

> Thanks!
> Bob Jones

In the formshow, you print. When done printing you close the form.
Why are you assigning the caFree action? This will free the form -
hence access voilations. Are you creating the form to begin with? Then
showing it modally? To close a modal form, you can set modalresult :=
mrOk (or whatever) whereever you want to, and it will close the form.
Also, instead of using frmPrtOrd.Modal......... use SELF.Modal.........
If you are creating the form, it isn't called frmPrtOrd but is instead
called frmPrtOrd_1 in memory. That is probably the real reason that the
form is not closing.

Sincerely,
Jason 'Wedge' Perry.


0 new messages