Link to home
Create AccountLog in
Avatar of sepknow
sepknow

asked on

Delphi 6 form question

Further to my question in
https://www.experts-exchange.com/questions/26914474/Delphi-6-form-question.html

1) There is no code in OnClose or OnCloseQuery or finalization.
2) I have added log statement in every event handler and functions/procedures.
3) The OnShow was trigger once only.
4) There was no exception. Nothing to catch in my exception handler.
5) I do have other event handlers shown below. But I think they do not
pose any problem.

What else could have caused my form not to close?



procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if (Key = VK_F4) and (ssAlt in Shift) then
    Key:=0;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  if (gStatus = Open) then begin
    //If the form is opened/visible
    //Bring it to the front
    //position it to the center
    self.BringToFront;
    self.Left:=(Screen.DesktopWidth - self.Width) div 2;
    self.Top:=(Screen.DesktopHeight - self.Height) div 2;
    //log
  end;
end;
Avatar of Geert G
Geert G
Flag of Belgium image

not closing of a form is prevented ?

do you inherit this form from another one you created ?
> a handler could be set in the parent
type
  TForm1 = class(TOtherForm)

or have you done any subclassing of TForm in one of your own units like this:
type
  TForm = class(forms.TForm)

do you have exception handling for the application ?
application.OnException := ...

are any handlers fired from other forms, eg:
procedure TForm2.OnBtn1Click(Sender: TObject);
begin
  Form1.HandleSomething(Self);
end;
>> Form1 variable would be the problem here ... it's destroying ...

Avatar of sepknow
sepknow

ASKER

Thanks.

There is no inheritance.
No subclassing either.
I do handler global exception but no error message was reported.
No handlers in Form1 was fired from other forms.

But I do set the variables declared in Form1 from the main form.
for example, gStatus declared in Form1:

type
  TForm1 = class(TForm)
    rg1: TRadioGroup;
  private
    { Private declarations }
  public
    { Public declarations }
    gStatus:EStatusType;
  end;



so there are references between forms
and modifications of variables from other forms

how do you do the changes ?

it may be best to use property getters/setters for public variables

type
  TForm1 = class(TForm)
  private
    fgStatus: EStatusType;
    function GetGStatus: EStatusType;
    procedure SetGStatus(const Value: EStatusType);
  public
    property gStatus: EStatusType read GetGStatus write SetGStatus;
  end;

function TForm1.GetGStatus: EStatusType;
begin
  Result := fgStatus;
end;

procedure TForm1.SetGStatus(const Value: EStatusType);
begin
  if csDestroying in ComponentState then
    raise Exception.Create('TForm1 instance is being destroying.  Check call stack with Ctrl-F3');
  fgStatus := Value;
end;
Avatar of sepknow

ASKER

I need at least one day to test it.
Thanks.
don't give this to the users ...
you need to run this in delphi itself

after you hit close, you may get an exception
hit Ctrl-F3 to see where the call came from
Avatar of sepknow

ASKER

Will it helps if I use Tbutton instead of TBitBtn?
no difference, they are both descendants of TWinControl

there would be a difference if using a TSpeedBtn instead
TSpeedBtn doesn't get focus when clicked, other button types do
in unit1, are you "using mainunit" ?

if so, you have circular unit reference ...
not really a culprit, but a secondary problem, which may complicate the matters a little
Avatar of sepknow

ASKER

yes, but it is after the implementation.
Avatar of sepknow

ASKER

And, will it helps, if I hide the form instead of closing the form?
>>yes, but it is after the implementation.
????

hiding will not give an error ... the error will happen when closing the application completely
aha>>yes, but it is after the implementation.
lol, i got it ... you indeed have circular unit reference

it would be best to avoid that practice
if you need help in solving that problem too
> remove the mainunit from the uses section from unit1
> and post the code where the problem occurs
> i'll show the way to do it without circular unit reference
> this may also solve your closing problem
Avatar of sepknow

ASKER

Thanks.

The line in the save button click event:

procedure TForm1.bbSaveClick(Sender: TObject);
begin
    ...
    MainForm.FillGrid('HighCount');
    ...
end;
what does that save do ?

do you reference Form1 information from MainForm.Fillgrid ?

post the code with the references to Form1 from FillGrid/MainUnit
this is probably the cause of your problem ... i'm guessing probably 99% ... :)
Avatar of sepknow

ASKER

This function does quite a few things.
1) Read some data from the sql database
2) Fill the data into the TStringGrid
3) and finally issue a "Close" statement in the finally block.
no references to the Form1.
what TStringGrid ?
where is that located on Main Form ?

what information are you putting in the grid and where does it come from ?

and why do you put that code in TForm1 ?
shouldn't it be in Main Form ?
after all, it's probably changing something in main form ...
Avatar of sepknow

ASKER

Yes, the TStringGrid is located in the Main Form.
It reads the data from SQL server and populate into the grid.
TForm1 merely called the function in mainform to populate the grid.
to tell the user that data entered in TForm1 is saved into the database.
that's not the good way to program
it's quick, yes, but it makes mainform dependant on form1 and vice versa

not good if you design multiple apps with common code

I assume you show Form1 ShowModal ?
and want to close it with save button ?

unit1 sample (most simple form)
 
unit Unit1;

type
  TForm1 = class(TForm)
    ...
  end;

function ShowSubForm1Modal(aOwner: TComponent): boolean;

implementation

function ShowSubForm1Modal(aOwner: TComponent): boolean;
var F: TForm;
begin
  Result := False;
  F := TForm1.Create(aOwner);
  try
    if F.ShowModal = mrOk then 
      Result := True;
  finally
    F.Free;
  end;
end;

Open in new window


main unit call
 
uses Unit1;

procedure TMainForm.Button1Click(Sender: TObject);
begin
  if ShowSubForm1Modal(Self) then 
    FillGrid('HighCount');
end;

Open in new window


in unit1 there is no "uses MainUnit"
Avatar of sepknow

ASKER

Thanks.

Its Form1.Show()

=(

That is why I put all the tasks in Form1.

May I know what is the best practice, in this case?
ASKER CERTIFIED SOLUTION
Avatar of Geert G
Geert G
Flag of Belgium image

Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
See answer
Avatar of sepknow

ASKER

Thank you for your help.