Link to home
Start Free TrialLog in
Avatar of Sebastion
Sebastion

asked on

Subforms - basics

Hey,

What do I need to do to load a form within another form?  I found this nice tutorial at http://www.delphipages.com/tips/thread.cfm?ID=6, but it doesn't seem to explain things enough so I can understand.

What I'm specifically looking for, is how to load a form within another form dymanically (ie, not necessarily when the program loads) as well as unload it at a later date.  It would also be nice to transfer data between the main form and subform.

Thanks
Avatar of tobjectpascal
tobjectpascal

Well unless you state the form not to be autocreated, it will be there anyway.

Delphi > File > New Form

Save the form as YourForm2 and press OK, now from your main form it's a simple case of going..

Form2.Show;

(or if you changed the name of the form, Somethingelse.Show);

But to make it truely Dynamic, you have To remove it from the list of forms, the easiest way would be to go to the Menu in Delphi

Project > Options

Auto CreateForms     |     Available Forms.

Form1
Form2


Move Form2 to Available Forms on the right.

Then on your main unit, go to the top, Add the unit name in this case if you don't save it, simply add unit2 at the uses at the top.

unit Unit1;

interface

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


Like that, then make a button on your main form..

procedure TForm1.Button1Click(Sender: TObject);
Var
 YourForm: TForm2;
begin
 YourForm:=TForm2.Create(self);
 YourForm.Visible:=True;
 //YourForm.Free; //make sure you release the memory when you finished with it
end;

That's pretty much all there is to it.
Avatar of Sebastion

ASKER

Hey tobjectpascal,

Unfortunatly, that was not what I had it mind.  From what you describe, it opens a new form window on the button click.  What I was looking for was to physically open the form within another form, so as to appear like one program.

For example, in Microsoft Access, this is achieved by using a subform.  In HTML, you could probably use a frame to load multiple webpages.  If I remember correctly, in Visual C# this is accomplished by using panels and user controls.  In Delphi though, I'm unsure.

I've played around abit with Frames, but I'm not sure that they are what I'm after.  Ultimately, I would like to have it so that the program has a menu bar up top, that continually changes what is displayed "down the bottom".  In other words, if the user is currently viewing housing information, but wanted to see undeveloped land info, they'll nagivate through the menu which in turn will refresh the main section of the program (ideally by switching out the housing form with the undeveloped land form), rather than open a new window to display the information.
Var
 YourForm: TForm2;
begin
 YourForm:=TForm2.Create(self);
 YourForm.Parent:=Self;
 YourForm.Visible:=True;
Alright, but the subform is still movable around the main.  How do I lock this in a set location?  Also, is it possible to remove the title bar from the subform, since it looks out of place.

What would I need to do to send a variable from one form to another?
I beleive that the TForm was not intended to be a "Child" (like a control, a TPanel) of another window, although it is easy enough to just set a TForms parent to a Form or other windowed control, , I have found that the Delphi TFrame, will give more control like functioning (especially for Tab and arrow-key focus change) than a TForm as a child control. So I would recomend you try to use the TFrame for what you describe. I beleive the TFrame was made to be a Form that is a child control, because they do not have a title bar.  You can access the variables of the "Public" section of a Frame or Form if you add it to your "uses" clause, hopefully the uses clause in the implementation section
Hey Slick812,

Yea, a frame was my original idea, but when I tried to add a BDE Table to it, the program kept erroring out.  To be exact, I could add the DataSource and Table, but when I tried to add fields the Table, the program kept returning the error "Table1: Duplicate field name".  If I repeat the exact same process on a form though, in the exact same project, I receive no errors.  Is there something about frames that I do not know about?
I am not sure of what your problem may or may not be? ?
But if I were to guess, I would think that you are referencing a variable (something of the Database or database conection) in your TFrame, that you have declared in your TForm, where your code works, and  the TFrame is not able to use that variable, you might try to place the unit name of your form (Form1 is the default) in the "uses" clause of your TFrame, and you need to be sure that that variable is not in a private or protected section.

I'm actually doing something similar in my own application using another database.  Using the following code, my users are able to create Child Windows from the Main Application:

procedure TFormMain1.CreateChildForm(Sender: TObject);
var
  Child: TFormChild;
begin

  Child := TFormChild.Create(Application);
  Application.ProcessMessages;
  Child.Caption := 'Your caption goes here...';

end;

The Child Form contains all of the necessary database access/control objects.
Slick812, the passing of variables is not really my main problem with frames, it's more a matter of creating a BDE Table, and adding fields to that object that causes the errors I mentioned above.  I did abit more playing around, and it seems that the problem *might* be because I am using a frame within a frame.  Take the following example:

The project has one form (MainForm), and 2 frames (Client, ClientDetails).  At the moment, MainForm only has a frame object on it, linking to the Client frame.  The Client frame has a frame object on it as well, linking to the ClientDetails frame.  If I were to add a BDE Table on the Client frame, everything works fine and I'm able to add fields to it's fields editor.  Go back a step (and remove the BDE Table from the Clients frame) and if I add a BDE Table to ClientDetails, and try to add fields, I get the same error mentioned above (duplicate field name).

I'm going to need to play around with it abit.


Hey mwbowman, maybe I'm missing some steps, but when I followed your code example the form still opens as a new window, rather than in the same window.  Is this what you intended?
Also note that I've increased the points on this question, since oddly enough it doesn't appear to be as straight forward as I initially though.

That's true, but in this case you can open many forms (with grids) dynamically, including different instances of the same database, which is what I offer my users.

Are you simply wanting to create the grid in during runtime?  if so, then using frames is probably the best way to go.
mwbownman, unfortunatly this was not the plan I had with my program.  In a previous post in this question, tobjectpascal suggested a similiar approach to what you mentioned, but I thought I had already clarified my intentions back then.

My intent with this program is to try and make the "bottom three quarters" dymanically generated, to reflect the different sections that the user is able to nagivate to.  For example, even though the bottom "data area" (which is pretty much everything in the program except the main menu) main initially start on client details, if the user nagivates to the property section using the main menu, then the data area should change to accomodate this new set of information.

I have been playing around with frames these last couple of days.  I've managed to work it so that I do not need to have 2 levels of frames (ie to avoid the form --> frame --> frame setup) as in this scenario, the second frame cannot appear to have a BDE Table (unsure about ADO, never tested).  It's looking more and more like this is what I'll need to do...
So that brings me to a question now, instead of how to pass variables between forms, how does one pass variables between frames?  A search on the Internet didn't bring up much tutorials along the lines of frames for Delphi (if any at all).  I've declared the frame in the uses section for the mainform, but I cannot seem to use any of it's custom procedures or variables, even though the procedures and variables are public?
ASKER CERTIFIED SOLUTION
Avatar of Member_2_248744
Member_2_248744
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Slick812, that's what I needed to know.  I should be able to hand things from here.  Thanks