Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

MDI Issue 1

Status
Not open for further replies.

Opieo

Programmer
Jul 26, 2006
454
GB
Okay guys, once again I am stumped.
I am trying to switch of the part of my program past the login screen to MDI.
I am doing this so that they may have the query window open to see masses of data at the same time they can go in and edit a few values and know which path to take to get there.

Anyways, I am having problems setting up the MDI.
It is there, but keeps giving me access violations.
I know precisely where too, I just do not know why.
I can NOT have the MDI Parent form change values on the child form or have the children access values on the parent.

For example:
Code:
procedure TForm2.FormActivate(Sender: TObject);
 begin
  TForm3.Create(Application);
  Form3.ProCount := 5;
 end;
Will not work.
If I comment out the Form3.ProCount line it works just fine.
In the activation of Form3, if I have it say ProCount := Form2.Counter, it will give me an access violation then as well.
Why can they not access each other's variables?

~
Give a man some fire, he will be warm for a day, Set a man on fire, he will be warm for the rest of his life.
 
I use this format all the time to populate information into a "new" form:

Code:
procedure TForm2.FormActivate(Sender: TObject);
begin
  with TForm3.create(Form2) do
  begin
    Procount := 5;
  end;
end;

Leslie

Anything worth doing is a lot more difficult than it's worth - Unknown Induhvidual

Essential reading for database developers:
The Fundamentals of Relational Database Design
Understanding SQL Joins
 
Hi Opieo,

while leslie's solution is valid, it does not explain why your piece of code is failing.

the answer is simple, you need to assign a variable.

like this :
Code:
procedure WhatEver;

var MyNewForm;

begin
 MyNewForm := TForm3.Create(Application);
 MyNewForm.AProperty := CanNowBeAssigned;
end;

Cheers,
Daddy

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
Okay, this will be a lengthy explanation for solution.
I had tried both of those, to an extent, and neither worked.
It was a combination of things.
I was getting my ideas from the About.Delphi MDI walkthrough.
Continually referencing that and going off of what Daddy suggested, I found that I needed to cast [green]MyNewForm[/green] as he put it, to be specifically
Code:
var MyNewForm : TForm3
and not just
Code:
var MyNewForm : TForm
The reason it didn't originally work when I set it up like that is because of where I put the [blue]uses[/blue] information.
Before I wanted to (or rather all the users wanted to) use MDI, I had the uses for any other forms right after the [blue]implementation[/blue] line.
I now get the feeling that this is not the way it should be done. Moving the forms that the MDI Parent will use up to the top uses clause in [blue]interface[/blue] makes everything work.
Now declaring MyNewForm as TForm3 works, and can now consequently access its variables with an access violation error.
Thank you guys for the help. =)

~
Give a man some fire, he will be warm for a day, Set a man on fire, he will be warm for the rest of his life.
 
Okay, another problem along the exact same lines.
The children accessing each other's public variables.
Like I mentioned in the previous post, I have a "uses" line right beneath the [blue]implementation[/blue] line for where forms use other forms.
I cannot move those on the children up to the [blue]interface[/blue] line or it will give me a circular reference error.
Having the uses line under implementation works perfectly fine for the children changing one of the MDI parent's variables (such as options form changing master color for form background).
And the parent can change their public variables by having moved their uses up to the interface section and having the variable.
Before MDI this setup worked perfectly and no users have reported any problems with it (well, an error here or there, but not from this =D ).

I can get it to work for a child to reference another child Through the parent. Ex:
Code:
Form2.Child2.Variable1 := 5
However, I was curious if there was an easier way to just fix my uses since neither method seems to work.
I would rather not go back and change every spot one form changes something on another, but currently I either get a compiling error for circular reference or a runtime error of access violation.
=\
Any ideas?

~
Give a man some fire, he will be warm for a day, Set a man on fire, he will be warm for the rest of his life.
 
Exactly what is your objective? I'm guessing here that you have a logon form you want to run before your MDI application starts? Is this correct?

If "yes", you can do all of this in the DPR. Load (create > get input > free) your logon form as a seperate boolean function. If "true" (logon passed) then do the rest.
The DPR:
Code:
program MyMdiApp;

uses
  Forms,
  Dialogs,  //must add just for showmessage!
  MyLogon in 'MyLogon.pas' {LogonForm},
  MyMDIForm in 'MyMDIForm.pas' {MyMDI};

{$R *.res}

function GetLogon: boolean;
begin
  result:= false; //assume failure
  LogonForm:= TLogonForm.create(nil);
  LogonForm.ShowModal;
  result:= LogonForm.LoggedOn;
  LogonForm.Free;
end;

begin
  if GetLogon then begin //wont run if logon fails!!!
    Application.Initialize;
    //Application.CreateForm(TLogonForm, LogonForm); !!you MUST comment this out or delete the line!!
    Application.CreateForm(TMyMDI, MyMDI);
    Application.Run;
  end else
    ShowMessage('Logon failed!')
end.

Just tested. Above code works!


Roo
Delphi Rules!
 
Here is the do-nothing Log-on form I used for testing.
Code:
unit MyLogon;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TLogonForm = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    LoggedOn: boolean;
  end;

var
  LogonForm: TLogonForm;

implementation

{$R *.dfm}

procedure TLogonForm.Button1Click(Sender: TObject);
//caption is "Pass"
begin
  LoggedOn:= true;
  ModalResult:= mrOk;
end;

procedure TLogonForm.Button2Click(Sender: TObject);
//caption is "Fail"
begin
  LoggedOn:= false;
  ModalResult:= mrCancel;
end;

end.

Roo
Delphi Rules!
 
Roo, why use the LoggedOn variable? you can always check the modalresult of the form to check if the OK button was pressed. also you don't have to set ModalResult in code, you can do this via the Object Inspector, offcourse the result stays the same.

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
Daddy, You're correct, but I actually used LoggedOn var for demo purposes to avoid having to explain how modal result works. I put the ModalResult in as a clue.

I've always used [blue]ModalResult:= mrOk;[/blue] to close forms and guarantee the result code, since [blue]Close;[/blue] does not always set it to true.

In a true logon process, I make LoggedOn a global, so it can be checked by other processes and force logoff in a timer event, say, no activity for a certain time period.

And of course, not set either to true unless the correct password were entered.


Roo
Delphi Rules!
 
I already have my logon form up and running perfectly.
It actually exits the program if it fails so I do not worry about the ModalResult.
But I know about the Modal Result property and use it elsewhere in the program.
I run the logon form before running the application via the Program Source.

My last question was just if there was an easier way using MDI, to allow the MDI Children to access each others variables than doing a [blue]MDIPartent.Child2.Property[/blue].
Since they cannot just do a [blue]Form2.Property[/blue], or it seems to give an access violation.
It works perfectly fine by going through MDI Parent form first, just wondered if there was an easier way.
I cannot have them use each other in the Interface section, or it gives a circular reference error, and having it in the implementation uses will still result in an access violation.
But, it works fine going through parent then back down into other form via the Children variable deal. Just seems like there should be something easier.

~
Give a man some fire, he will be warm for a day, Set a man on fire, he will be warm for the rest of his life.
 
i had no problems doing mdiform.property with my test mdi app as long as the uses is under the implementation section.

Aaron
 
you will get an access violation if you try and access properties when the mdiform is not created.

Aaron
 
Oh, the forms were created just fine.
And I saw that they were there before the access violation.
I just tested it again to make sure.
With a form being around for awhile, then making another form.
The form made later on tried to change a variable on the form that had been around awhile .. access violation.
Don't know why.
Oh well, it works by just going through the mdi parent.
I will just do it that way.

aaronjme, just wanted to double check, it was one mdichild changing another mdichild's property right? That is the only way I have the problem (child to child).

~
Give a man some fire, he will be warm for a day, Set a man on fire, he will be warm for the rest of his life.
 
yes..

try creating yourself a new test app
1 mdi form with 2 children, put a button on child 1 that changes child 2's form color and a button on child 2 that changes child 1's color.


Aaron
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top