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 biv343 on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How do I change form order? 1

Status
Not open for further replies.

CHeighlund

Programmer
Jun 11, 2007
163
US
I'm working on a modified version of a program produced by my predecessor. The previous version was all database withdrawal, but the current version (the one I'm working with) is supposed to allow for database input as well. Given this, my boss has requested that I place a login form into the program.

I've got the login form created (except for the actual DB drawing, which I'll get to as soon as this is finished). How do I change the program so that my login form, and not the original 'start' form, is the first one shown on the screen when the program runs?
 
Look under Projects|Options|Forms and it should list all the forms there and auto-create order. You should be able to set the login screen first there.

----------
Those who work hard are rewarded with more work and remembered come time to downsize. Those who hardly work are given a paycheck and ignored completely.
 
I am running into a problem with this.

Previously, I attempted to build a new form while part of the original project, and was able to cause it to display first by the method you suggested. However, I was unable to get all of the effects I desired out of the components on it.

I now have a new form, created elsewhere, that does handle the problems. However, even when included in the old project, I cannot get the new form to come up first. I can shift it, as mentioned above, on the Projects|Options|Forms page, but the item after my new form (the previous starting screen) is the form which actually appears at runtime.

The only major difference I know of is that the new form had a .dfm file, where the old had a .xfm fle. I do not know what, if any, difference this makes.
 
if you move a form up to be the main form then you need to revove the other forms from the Auto-Create forms list or set thier visible property to false.

Aaron
 
I'd already done so on the visibile attribute. And with all other forms removed from the autocreate list, all that happens on compile/run is a quick on-screen blink, then the program ends and I end up back in the compiler.

I'm beginning to think it's a cross-compiler error; some of what I've seen leads me to think the original forms were CLX rather than Delphi proper, but the new form I specifically created to be Delphi proper. (Some of the advice I was trying to follow wouldn't work for the components they were supposed to.) I may need to swap over to the CLX forum.
 
Couldn't you just create the login form in the program, and if the login is successful create the other forms from the login unit, and If unsuccessful show a friendly error and repeat the login process?

-a6m1n0

127*(256)^3+0*(256)^2+0*(256)^1+1
 
I'm not sure I understand your suggestion, a6m1n0.

I can't create anything from the form, because I can never get to the form. I'm trying to figure out how to do that.
 
Don't mess with the auto-create order. The very first form auto-created is the application's main form, which you probably don't want to be the login dialog.

You can do one of three things.

a6m1n0's suggestion is to edit your dpr file directly (go to Project --> View Source) and create and use the form directly:
Code:
program foo;
uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  ...,
  uLoginDialog in 'uLoginDialog.pas' {LoginDialogForm};

{$R *.res}

begin
  {begin new stuff}
  with TLoginDialogForm.create( nil ) do try
    try
      if ShowModal <> mrOK then Exit
    finally free end
  except Exit end;
  {end new stuff}

  Application.Initialize;
  Application.CreateForm( TForm1, Form1 );
  ...
  Application.Run;
end.
The TLoginDialogForm is your login dialog. In this example it is created as a parent-less top-level form. It should not appear in the auto-create project options. It should ask the user to login and attempt to verify his response (allowing the user to try one or more times, typically three). If successful, it sets ModalResult to mrOK. If not successful, it sets it to something else (like mrAbort or whatever).
If the dialog fails for any reason the program is aborted without doing anything else.

If you don't want to mess with your dpr file directly, you'll have to use one of the following variations:

Variation One (Recommended)
In your uLoginDialog unit (or whatever you named it), add the following down at the bottom:
Code:
var LastInitProc: pointer;

procedure Login;  // You can name this procedure anything you like
  begin
  with TLoginDialogForm.create( nil ) do try
    try
      if ShowModal <> mrOK then Application.Terminate
    finally free end
  except Application.Terminate end;

  if not Application.Terminated and Assigned( LastInitProc )
    then TProcedure( LastInitProc )
  end;

initialization
  LastInitProc := InitProc;
  InitProc     := @Login

end.
This method does the very same thing as the first, but it keeps stuff out of the dpr. That is the first reason why I like it: it allows you to keep related things in their own unit instead of 'contaminating' other units.

The second is that it is transparent, meaning that you don't have to worry about modifying the call to your initialization procedure ('Login' in this example) anywhere --you know that Application.Initialize will call it properly after all units are loaded but before any forms are created. Adding or removing such specialized initialization code is just a matter of including or excluding the relevant unit.

Variation Two
Put the login code in your main form's constructor.
Code:
procedure TForm1.FormCreate( Sender: TObject );
  begin
  with TLoginDialogForm.create( nil ) do try
    try
      if ShowModal <> mrOK then Application.Terminate
    finally free end
  except Application.Terminate end;

  if Application.Terminated then Exit;

  {normal constructor stuff goes here}
  end;
This works as well, but again it is entangled into a separate module's code. Also, you might see the main form flash on screen before the application terminates.

Hope this helps.
 
Duoas, not that I disagree with you in principle, but when I used to work with Delphi, I always found autocreate a pain and handled all startup via the dpr and created (and displosed of) other forms as and when necessary.

[vampire][bat]
 
I too prefer to manage my own form creation/destruction but would not advise it to beginners. I find it particularly useful with large applications with 20+ forms, which can be very slow to startup while opening all those forms.

I also arrange all my tables into logical groups of datamodules which manages which and how many tables are open at once, simply by creating and freeing the data modules, where create opens tables and free closes them.

Regarding log-on, I use the following:
First, the log-on unit
Does nothing - for example only
Click the button to simulate successful login
Click the X to simulate failed login
Code:
Code:
unit UnitLogon;

interface

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

type
  TLogonForm = class(TForm)
    Edit1: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Edit2: TEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    UserLoggedOn: boolean;
    { Public declarations }
  end;

var
  LogonForm: TLogonForm;

implementation

{$R *.dfm}

procedure TLogonForm.Button1Click(Sender: TObject);
begin
  UserLoggedOn:= true;
  close
end;

end.
Next the MainForm:
Does nothing - for example only
But you can't get to it without logging on
(More on that later...)
Code:
unit MainUnit;

interface

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

type
  TMainForm = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

procedure TMainForm.Button1Click(Sender: TObject);
begin
  close
end;

end.
How it works is in the DPR:
Code:
program LogonTest;

uses
  Forms,
  UnitLogon in 'UnitLogon.pas' {LogonForm},
  MainUnit in 'MainUnit.pas' {MainForm};

{$R *.res}

begin
  Application.CreateForm(TLogonForm, LogonForm);
  LogonForm.ShowModal;
  if LogonForm.UserLoggedOn then begin
    LogonForm.Free;
    Application.Initialize;
    Application.CreateForm(TMainForm, MainForm);
    Application.Run;
  end
end.
If you want to run this to see it in action, I've included the 2 required DFMs below:

UnitLogon.dfm
Note the use of property "PasswordChar"
Code:
object LogonForm: TLogonForm
  Left = 466
  Top = 138
  Width = 263
  Height = 311
  Caption = 'LogonForm'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 24
    Top = 112
    Width = 46
    Height = 13
    Caption = 'username'
  end
  object Label2: TLabel
    Left = 32
    Top = 144
    Width = 45
    Height = 13
    Caption = 'password'
  end
  object Edit1: TEdit
    Left = 80
    Top = 104
    Width = 121
    Height = 21
    TabOrder = 0
    Text = 'Edit1'
  end
  object Edit2: TEdit
    Left = 80
    Top = 136
    Width = 121
    Height = 21
    PasswordChar = '*'
    TabOrder = 1
    Text = 'Edit2'
  end
  object Button1: TButton
    Left = 96
    Top = 192
    Width = 75
    Height = 25
    Caption = 'Log on'
    TabOrder = 2
    OnClick = Button1Click
  end
end

MainUnit.dfm
Code:
object MainForm: TMainForm
  Left = 450
  Top = 159
  Width = 393
  Height = 185
  Caption = 'MainForm'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 136
    Top = 96
    Width = 75
    Height = 25
    Caption = 'Close'
    TabOrder = 0
    OnClick = Button1Click
  end
end

Note that this eliminates all the issues in this thread (other than confusing CLX code with Win32).
Created with D7. I hope you find this useful.

Roo
Delphi Rules!
 
You all are going way beyond the OP's needs.

Whether you like to let Delphi do it or do it yourself, the following is always true:

The very first form added to the Application is considered the Application's main form, which you cannot later change.

You'll also notice that in all my examples above, the login form was temporarily created and immediately destroyed, just as I've advised the OP to do.


In my own personal preference, I tend to let Delphi create the main form and an options form (which is what communicates with the registry, handles command-line arguments, etc). Everything else gets created and destroyed on demand.
 
??? It sound like you are saying we are not allowed to look behind the curtain.

I do a lot more that that in my dpr. Typically, in large apps, I check user registration and terms by reading the registry, server login name, verify paths to DBs, and do all INI settings which can determine which forms Object(Application) is allowed to open. All of which are freed before the main form gets created. (As in - not still in memory.) My user forms won't open until all has passed, IAW security and controls rules.

I would really appreciate some feedback on my example from any one of you that actually tries it. Please.

Roo
Help stamp out bloated code.
 
@Duoas:
Thank you for the assistance; your advice worked perfectly for me. The login form now appears where and when it is supposed to appear.
 
@CHeighlund
Glad to have been of help.

@Roo
Your example looks fine to me.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top